From 74da6e84932ddfc5acce00268b714f0a049b62d0 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Tue, 21 Nov 2023 23:54:20 -0500 Subject: [PATCH 01/62] Migrate service classes to null safety --- lib/core/services/analytics_service.dart | 7 ++-- lib/core/services/app_widget_service.dart | 11 ++++--- lib/core/services/github_api.dart | 18 +++++------ lib/core/services/in_app_review_service.dart | 2 +- lib/core/services/internal_info_service.dart | 4 +-- lib/core/services/launch_url_service.dart | 2 +- lib/core/services/navigation_service.dart | 32 +++++++++++++------ lib/core/services/preferences_service.dart | 25 ++++++++------- lib/core/services/rive_animation_service.dart | 7 ++-- lib/core/services/siren_flutter_service.dart | 10 +++--- lib/core/utils/animation_exception.dart | 11 +++---- pubspec.yaml | 2 +- 12 files changed, 70 insertions(+), 61 deletions(-) diff --git a/lib/core/services/analytics_service.dart b/lib/core/services/analytics_service.dart index d98fab89a..3ca534b4a 100644 --- a/lib/core/services/analytics_service.dart +++ b/lib/core/services/analytics_service.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; @@ -18,7 +15,7 @@ class AnalyticsService { /// Log a error. [prefix] should be the service where the error was triggered. Future logError(String prefix, String message, - [Exception error, StackTrace stackTrace]) async { + [Exception? error, StackTrace? stackTrace]) async { final mesTruncated = message.length > 100 ? message.substring(0, 99) : message; await _analytics.logEvent( @@ -38,7 +35,7 @@ class AnalyticsService { } /// Set user properties to identify the user against firebase app. - Future setUserProperties({@required String userId, String domain}) async { + Future setUserProperties({required String userId, required String domain}) async { await _analytics.setUserId(id: userId); await _analytics.setUserProperty( name: _userPropertiesDomainKey, value: domain); diff --git a/lib/core/services/app_widget_service.dart b/lib/core/services/app_widget_service.dart index 078ba8449..16c3e07e4 100644 --- a/lib/core/services/app_widget_service.dart +++ b/lib/core/services/app_widget_service.dart @@ -22,14 +22,14 @@ import 'package:notredame/locator.dart'; class AppWidgetService { static const String tag = "AppWidgetService"; - final AnalyticsService _analyticsService = locator(); + late final AnalyticsService _analyticsService = locator(); - Future init() async { + Future init() async { return HomeWidget.setAppGroupId('group.ca.etsmtl.applets.ETSMobile'); } /// Update session progress widget with provided data - Future sendProgressData(ProgressWidgetData progressWidgetData) async { + Future sendProgressData(ProgressWidgetData progressWidgetData) async { try { await HomeWidget.saveWidgetData( '${ProgressWidgetData.keyPrefix}progress', @@ -52,7 +52,7 @@ class AppWidgetService { } /// Update grades widget with provided data - Future sendGradesData(GradesWidgetData gradeWidgetData) async { + Future sendGradesData(GradesWidgetData gradeWidgetData) async { try { await HomeWidget.saveWidgetData>( '${GradesWidgetData.keyPrefix}courseAcronyms', @@ -68,7 +68,7 @@ class AppWidgetService { } /// Tell the system to update the given widget type - Future updateWidget(WidgetType type) async { + Future updateWidget(WidgetType type) async { try { return HomeWidget.updateWidget( name: type.androidName, @@ -76,6 +76,7 @@ class AppWidgetService { iOSName: type.iOSname); } on PlatformException { _analyticsService.logError(tag, 'Error updating widget ${type.iOSname}.'); + return false; } } } diff --git a/lib/core/services/github_api.dart b/lib/core/services/github_api.dart index 8b38a2c14..a12f48ec6 100644 --- a/lib/core/services/github_api.dart +++ b/lib/core/services/github_api.dart @@ -27,13 +27,13 @@ class GithubApi { static const String _repositorySlug = "ApplETS/Notre-Dame"; static const String _repositoryReportSlug = "ApplETS/Notre-Dame-Bug-report"; - GitHub _github; + late GitHub _github; - final Logger _logger = locator(); + late final Logger _logger = locator(); - final AnalyticsService _analyticsService = locator(); + late final AnalyticsService _analyticsService = locator(); - final InternalInfoService _internalInfoService = + late final InternalInfoService _internalInfoService = locator(); GithubApi() { @@ -48,7 +48,7 @@ class GithubApi { } /// Upload a file to the ApplETS/Notre-Dame-Bug-report repository - void uploadFileToGithub({@required String filePath, @required File file}) { + void uploadFileToGithub({required String filePath, required File file}) { _github.repositories .createFile( RepositorySlug.full(_repositoryReportSlug), @@ -74,10 +74,10 @@ class GithubApi { /// The bug report will contain a file, a description [feedbackText] and also some information about the /// application/device. Future createGithubIssue( - {@required String feedbackText, - @required String fileName, - @required String feedbackType, - String email}) async { + {required String feedbackText, + required String fileName, + required String feedbackType, + String? email}) async { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); return _github.issues .create( diff --git a/lib/core/services/in_app_review_service.dart b/lib/core/services/in_app_review_service.dart index 2e5b03008..f3da402d3 100644 --- a/lib/core/services/in_app_review_service.dart +++ b/lib/core/services/in_app_review_service.dart @@ -22,7 +22,7 @@ class InAppReviewService { /// Opens the Play Store on Android, the App Store with a review Future openStoreListing({ String appStoreId = AppInfo.appStoreId, - String microsoftStoreId, + String? microsoftStoreId, }) => _inAppReview.openStoreListing( appStoreId: appStoreId, diff --git a/lib/core/services/internal_info_service.dart b/lib/core/services/internal_info_service.dart index 5d30cc1af..d5ecbfe79 100644 --- a/lib/core/services/internal_info_service.dart +++ b/lib/core/services/internal_info_service.dart @@ -19,7 +19,7 @@ class InternalInfoService { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final NetworkingService networkingService = locator(); final DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - String deviceName; + String? deviceName; if (Platform.isAndroid) { final AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; @@ -30,7 +30,7 @@ class InternalInfoService { } return "**Device Infos** \n" - "- **Device:** $deviceName \n" + "- **Device:** ${deviceName ?? 'Not Provided'} \n" "- **Version:** ${packageInfo.version} \n" "- **Connectivity:** ${await networkingService.getConnectionType()} \n" "- **Build number:** ${packageInfo.buildNumber} \n" diff --git a/lib/core/services/launch_url_service.dart b/lib/core/services/launch_url_service.dart index b52bb4d22..7d9fc655e 100644 --- a/lib/core/services/launch_url_service.dart +++ b/lib/core/services/launch_url_service.dart @@ -17,7 +17,7 @@ import 'package:notredame/ui/utils/app_theme.dart'; // OTHER class LaunchUrlService { - final SettingsManager settingsManager = locator(); + late final SettingsManager settingsManager = locator(); Future canLaunch(String url) async { final uri = Uri.parse(url); diff --git a/lib/core/services/navigation_service.dart b/lib/core/services/navigation_service.dart index 06ff0599d..2565f8ea3 100644 --- a/lib/core/services/navigation_service.dart +++ b/lib/core/services/navigation_service.dart @@ -14,16 +14,18 @@ import 'package:notredame/locator.dart'; /// Navigation service who doesn't use the BuildContext which allow us to call it from anywhere. class NavigationService { - final RemoteConfigService remoteConfigService = + late final RemoteConfigService remoteConfigService = locator(); - final GlobalKey _navigatorKey = GlobalKey(); + late final GlobalKey _navigatorKey = GlobalKey(); GlobalKey get navigatorKey => _navigatorKey; /// Pop the last route of the navigator if possible bool pop() { - if (_navigatorKey.currentState.canPop()) { - _navigatorKey.currentState.pop(); + final currentState = _navigatorKey.currentState; + + if (currentState != null && currentState.canPop()) { + currentState.pop(); return true; } return false; @@ -31,11 +33,17 @@ class NavigationService { /// Push a named route ([routeName] onto the navigator. Future pushNamed(String routeName, {dynamic arguments}) { + final currentState = _navigatorKey.currentState; + + if(currentState == null) { + return Future.error("Navigator state is null"); + } + if (remoteConfigService.outage) { - return _navigatorKey.currentState + return currentState .pushNamedAndRemoveUntil(RouterPaths.serviceOutage, (route) => false); } - return _navigatorKey.currentState + return currentState .pushNamed(routeName, arguments: arguments); } @@ -43,12 +51,18 @@ class NavigationService { /// [routeName] and then delete the stack of previous routes Future pushNamedAndRemoveUntil(String routeName, [String removeUntilRouteNamed = RouterPaths.dashboard, - Object arguments]) { + Object? arguments]) { + + final currentState = _navigatorKey.currentState; + if(currentState == null) { + return Future.error("Navigator state is null"); + } + if (remoteConfigService.outage) { - return _navigatorKey.currentState + return currentState .pushNamedAndRemoveUntil(RouterPaths.serviceOutage, (route) => false); } - return _navigatorKey.currentState.pushNamedAndRemoveUntil( + return currentState.pushNamedAndRemoveUntil( routeName, ModalRoute.withName(removeUntilRouteNamed), arguments: arguments); } diff --git a/lib/core/services/preferences_service.dart b/lib/core/services/preferences_service.dart index 110a42b23..592d2f3fe 100644 --- a/lib/core/services/preferences_service.dart +++ b/lib/core/services/preferences_service.dart @@ -1,5 +1,4 @@ // Flutter imports: -import 'package:flutter/material.dart'; // Package imports: import 'package:shared_preferences/shared_preferences.dart'; @@ -22,7 +21,7 @@ class PreferencesService { PreferencesFlag.hasRatingBeenRequested ]; - Future setBool(PreferencesFlag flag, {@required bool value}) async { + Future setBool(PreferencesFlag flag, {required bool value}) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.setBool(flag.toString(), value); @@ -73,7 +72,7 @@ class PreferencesService { }); } - Future getPreferencesFlag(PreferencesFlag flag) async { + Future getPreferencesFlag(PreferencesFlag flag) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.get(flag.toString()); } @@ -100,35 +99,37 @@ class PreferencesService { return prefs.setString(flag.toString(), value.toIso8601String()); } - Future getBool(PreferencesFlag flag) async { + Future getBool(PreferencesFlag flag) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool(flag.toString()); } - Future getInt(PreferencesFlag flag) async { + Future getInt(PreferencesFlag flag) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getInt(flag.toString()); } - Future getString(PreferencesFlag flag) async { + Future getString(PreferencesFlag flag) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getString(flag.toString()); } - Future getDynamicString(PreferencesFlag flag, String key) async { + Future getDynamicString(PreferencesFlag flag, String key) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getString('${flag.toString()}_$key'); } - Future getDateTime(PreferencesFlag flag) async { + Future getDateTime(PreferencesFlag flag) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); - try { - return DateTime.parse(prefs.getString(flag.toString())); - } catch (e) { - return null; + final flagPreference = prefs.getString(flag.toString()); + + if(flagPreference != null) { + return DateTime.parse(flagPreference); } + + return null; } } diff --git a/lib/core/services/rive_animation_service.dart b/lib/core/services/rive_animation_service.dart index c1f910b7b..4a8079620 100644 --- a/lib/core/services/rive_animation_service.dart +++ b/lib/core/services/rive_animation_service.dart @@ -1,5 +1,4 @@ // Flutter imports: -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // Package imports: @@ -10,7 +9,7 @@ import 'package:notredame/core/utils/animation_exception.dart'; /// Manage the rive animation for the application class RiveAnimationService { - Future loadRiveFile({@required String riveFileName}) async { + Future loadRiveFile({required String riveFileName}) async { final bytes = await rootBundle.load("assets/animations/$riveFileName.riv"); try { @@ -27,8 +26,8 @@ class RiveAnimationService { } void addControllerToAnimation( - {@required Artboard artboard, - RiveAnimationController controller}) { + {required Artboard artboard, + RiveAnimationController? controller}) { try { controller ??= SimpleAnimation(artboard.animations[0].name); artboard.addController(controller); diff --git a/lib/core/services/siren_flutter_service.dart b/lib/core/services/siren_flutter_service.dart index 407a2ed7c..238ef9f1c 100644 --- a/lib/core/services/siren_flutter_service.dart +++ b/lib/core/services/siren_flutter_service.dart @@ -8,7 +8,7 @@ import 'package:pub_semver/pub_semver.dart'; // SERVICES class SirenFlutterService { - Siren _siren; + late Siren _siren; SirenFlutterService() { _siren = Siren(); @@ -33,10 +33,10 @@ class SirenFlutterService { // Relay prompt update info to Siren package Future promptUpdate(BuildContext context, - {String title, - String message, - String buttonUpgradeText, - String buttonCancelText, + {required String title, + required String message, + String buttonUpgradeText = 'Upgrade', + String buttonCancelText = 'Cancel', bool forceUpgrade = false}) async { return _siren.promptUpdate(context, title: title, diff --git a/lib/core/utils/animation_exception.dart b/lib/core/utils/animation_exception.dart index cc89e1daf..d82d61faf 100644 --- a/lib/core/utils/animation_exception.dart +++ b/lib/core/utils/animation_exception.dart @@ -1,16 +1,13 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - /// Exception that can be thrown by the rive animation service class AnimationException implements Exception { final String _message; final String _prefix; - final Exception _nestedException; + final Exception? _nestedException; const AnimationException( - {@required String prefix, - @required String message, - Exception nestedException}) + {required String prefix, + required String message, + Exception? nestedException}) : _message = message, _prefix = prefix, _nestedException = nestedException; diff --git a/pubspec.yaml b/pubspec.yaml index 2b6401101..d03fa4148 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 4.33.2+1 environment: - sdk: ">=2.10.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: From b61dbae58ee9bc3a35f5c77dca5095f9124a0984 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 00:26:03 -0500 Subject: [PATCH 02/62] Migrate constants to null safety --- lib/core/constants/preferences_flags.dart | 7 ++----- lib/core/constants/widget_helper.dart | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/core/constants/preferences_flags.dart b/lib/core/constants/preferences_flags.dart index 6e9ee9507..67ef95b64 100644 --- a/lib/core/constants/preferences_flags.dart +++ b/lib/core/constants/preferences_flags.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/cupertino.dart'; - // Package imports: import 'package:enum_to_string/enum_to_string.dart'; @@ -62,8 +59,8 @@ class DynamicPreferencesFlag { PreferencesFlag groupAssociationFlag; DynamicPreferencesFlag( - {@required this.groupAssociationFlag, - @required this.uniqueKey, + {required this.groupAssociationFlag, + required this.uniqueKey, this.separator = "_"}); String get data => groupAssociationFlag.toString() + separator + uniqueKey; diff --git a/lib/core/constants/widget_helper.dart b/lib/core/constants/widget_helper.dart index 09bdcaa2a..5b47557e4 100644 --- a/lib/core/constants/widget_helper.dart +++ b/lib/core/constants/widget_helper.dart @@ -4,7 +4,7 @@ enum WidgetType { progress, grades } /// The extension corresponding to WidgetType to get associated constants extension WidgetTypeExtension on WidgetType { /// ID used by iOS systems to update the corresponding widget - String get iOSname { + String? get iOSname { switch (this) { case WidgetType.progress: return 'ETSMobile_ProgressWidget'; @@ -22,7 +22,7 @@ extension WidgetTypeExtension on WidgetType { /// /// Another option would be to use qualifiedAndroidName instead of androidName /// (see home_widget's updateWidget method for more info) - String get androidName { + String? get androidName { switch (this) { case WidgetType.progress: return 'ProgressWidgetProvider'; From 9ff31eb5980926aa87f094060f500dfa6fd3d824 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 00:26:55 -0500 Subject: [PATCH 03/62] Migrate utils to null safety --- lib/core/utils/cache_exception.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/core/utils/cache_exception.dart b/lib/core/utils/cache_exception.dart index 7f73f8e30..5f6745608 100644 --- a/lib/core/utils/cache_exception.dart +++ b/lib/core/utils/cache_exception.dart @@ -1,12 +1,9 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - /// Exception that can be thrown by the [CacheManager] class CacheException implements Exception { final String _message; final String _prefix; - const CacheException({@required String prefix, @required String message}) + const CacheException({required String prefix, required String message}) : _message = message, _prefix = prefix; From 9eea61280a28eba5402ecd3eb05a7b7c5e3c8115 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 00:50:48 -0500 Subject: [PATCH 04/62] Remove late from GetIt --- lib/core/services/app_widget_service.dart | 2 +- lib/core/services/github_api.dart | 6 +++--- lib/core/services/launch_url_service.dart | 2 +- lib/core/services/navigation_service.dart | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/core/services/app_widget_service.dart b/lib/core/services/app_widget_service.dart index 16c3e07e4..9c5725f16 100644 --- a/lib/core/services/app_widget_service.dart +++ b/lib/core/services/app_widget_service.dart @@ -22,7 +22,7 @@ import 'package:notredame/locator.dart'; class AppWidgetService { static const String tag = "AppWidgetService"; - late final AnalyticsService _analyticsService = locator(); + final AnalyticsService _analyticsService = locator(); Future init() async { return HomeWidget.setAppGroupId('group.ca.etsmtl.applets.ETSMobile'); diff --git a/lib/core/services/github_api.dart b/lib/core/services/github_api.dart index a12f48ec6..593bc01f3 100644 --- a/lib/core/services/github_api.dart +++ b/lib/core/services/github_api.dart @@ -29,11 +29,11 @@ class GithubApi { late GitHub _github; - late final Logger _logger = locator(); + final Logger _logger = locator(); - late final AnalyticsService _analyticsService = locator(); + final AnalyticsService _analyticsService = locator(); - late final InternalInfoService _internalInfoService = + final InternalInfoService _internalInfoService = locator(); GithubApi() { diff --git a/lib/core/services/launch_url_service.dart b/lib/core/services/launch_url_service.dart index 7d9fc655e..b52bb4d22 100644 --- a/lib/core/services/launch_url_service.dart +++ b/lib/core/services/launch_url_service.dart @@ -17,7 +17,7 @@ import 'package:notredame/ui/utils/app_theme.dart'; // OTHER class LaunchUrlService { - late final SettingsManager settingsManager = locator(); + final SettingsManager settingsManager = locator(); Future canLaunch(String url) async { final uri = Uri.parse(url); diff --git a/lib/core/services/navigation_service.dart b/lib/core/services/navigation_service.dart index 2565f8ea3..1119fe311 100644 --- a/lib/core/services/navigation_service.dart +++ b/lib/core/services/navigation_service.dart @@ -14,9 +14,9 @@ import 'package:notredame/locator.dart'; /// Navigation service who doesn't use the BuildContext which allow us to call it from anywhere. class NavigationService { - late final RemoteConfigService remoteConfigService = + final RemoteConfigService remoteConfigService = locator(); - late final GlobalKey _navigatorKey = GlobalKey(); + final GlobalKey _navigatorKey = GlobalKey(); GlobalKey get navigatorKey => _navigatorKey; From 536ae0868b9b740d0fdd68173e1275991930e705 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 00:52:34 -0500 Subject: [PATCH 05/62] Change @required to required --- lib/core/managers/user_repository.dart | 4 ++-- lib/core/models/discovery.dart | 8 ++++---- lib/core/models/emergency_procedure.dart | 2 +- lib/core/models/faq_actions.dart | 14 +++++++------- lib/core/models/faq_questions.dart | 4 ++-- lib/core/models/group_discovery.dart | 4 ++-- lib/core/models/quick_link.dart | 8 ++++---- lib/core/models/quick_link_data.dart | 2 +- lib/core/models/widget_models.dart | 16 ++++++++-------- .../viewmodels/choose_language_viewmodel.dart | 2 +- lib/core/viewmodels/dashboard_viewmodel.dart | 2 +- lib/core/viewmodels/emergency_viewmodel.dart | 2 +- lib/core/viewmodels/feedback_viewmodel.dart | 2 +- .../viewmodels/grades_details_viewmodel.dart | 2 +- lib/core/viewmodels/grades_viewmodel.dart | 2 +- lib/core/viewmodels/login_viewmodel.dart | 2 +- lib/core/viewmodels/more_viewmodel.dart | 2 +- lib/core/viewmodels/not_found_viewmodel.dart | 2 +- lib/core/viewmodels/profile_viewmodel.dart | 2 +- lib/core/viewmodels/schedule_viewmodel.dart | 2 +- lib/core/viewmodels/security_viewmodel.dart | 2 +- lib/core/viewmodels/settings_viewmodel.dart | 2 +- lib/ui/widgets/dismissible_card.dart | 4 ++-- test/helpers.dart | 2 +- .../services/flutter_secure_storage_mock.dart | 8 ++++---- .../services/siren_flutter_service_mock.dart | 4 ++-- 26 files changed, 53 insertions(+), 53 deletions(-) diff --git a/lib/core/managers/user_repository.dart b/lib/core/managers/user_repository.dart index 0befb05ad..80f6947e9 100644 --- a/lib/core/managers/user_repository.dart +++ b/lib/core/managers/user_repository.dart @@ -70,8 +70,8 @@ class UserRepository { /// will be saved in the secure storage of the device to authorize a silent /// authentication next time. Future authenticate( - {@required String username, - @required String password, + {required String username, + required String password, bool isSilent = false}) async { try { _monETSUser = await _monEtsApiClient.authenticate( diff --git a/lib/core/models/discovery.dart b/lib/core/models/discovery.dart index c2d9949cf..a91385cd6 100644 --- a/lib/core/models/discovery.dart +++ b/lib/core/models/discovery.dart @@ -8,8 +8,8 @@ class Discovery { final Widget details; Discovery( - {@required this.path, - @required this.featureId, - @required this.title, - @required this.details}); + {required this.path, + required this.featureId, + required this.title, + required this.details}); } diff --git a/lib/core/models/emergency_procedure.dart b/lib/core/models/emergency_procedure.dart index 606f32ffd..95e8b5ced 100644 --- a/lib/core/models/emergency_procedure.dart +++ b/lib/core/models/emergency_procedure.dart @@ -5,5 +5,5 @@ class EmergencyProcedure { final String title; final String detail; - EmergencyProcedure({@required this.title, @required this.detail}); + EmergencyProcedure({required this.title, required this.detail}); } diff --git a/lib/core/models/faq_actions.dart b/lib/core/models/faq_actions.dart index 17c268540..251a5f8f6 100644 --- a/lib/core/models/faq_actions.dart +++ b/lib/core/models/faq_actions.dart @@ -11,13 +11,13 @@ class ActionItem { final Color circleColor; ActionItem({ - @required this.title, - @required this.description, - @required this.type, - @required this.link, - @required this.iconName, - @required this.iconColor, - @required this.circleColor, + required this.title, + required this.description, + required this.type, + required this.link, + required this.iconName, + required this.iconColor, + required this.circleColor, }); } diff --git a/lib/core/models/faq_questions.dart b/lib/core/models/faq_questions.dart index d7ea0ba98..2cb32a558 100644 --- a/lib/core/models/faq_questions.dart +++ b/lib/core/models/faq_questions.dart @@ -6,7 +6,7 @@ class QuestionItem { final Map description; QuestionItem({ - @required this.title, - @required this.description, + required this.title, + required this.description, }); } diff --git a/lib/core/models/group_discovery.dart b/lib/core/models/group_discovery.dart index adfb0d3e0..85fdfd5bc 100644 --- a/lib/core/models/group_discovery.dart +++ b/lib/core/models/group_discovery.dart @@ -9,7 +9,7 @@ class GroupDiscovery { final List discoveries; GroupDiscovery({ - @required this.name, - @required this.discoveries, + required this.name, + required this.discoveries, }); } diff --git a/lib/core/models/quick_link.dart b/lib/core/models/quick_link.dart index 60a28c0e1..635a8fc3f 100644 --- a/lib/core/models/quick_link.dart +++ b/lib/core/models/quick_link.dart @@ -8,8 +8,8 @@ class QuickLink { final String link; QuickLink( - {@required this.id, - @required this.image, - @required this.name, - @required this.link}); + {required this.id, + required this.image, + required this.name, + required this.link}); } diff --git a/lib/core/models/quick_link_data.dart b/lib/core/models/quick_link_data.dart index 7895b9917..bda323c9f 100644 --- a/lib/core/models/quick_link_data.dart +++ b/lib/core/models/quick_link_data.dart @@ -5,7 +5,7 @@ class QuickLinkData { final int id; final int index; - QuickLinkData({@required this.id, @required this.index}); + QuickLinkData({required this.id, required this.index}); factory QuickLinkData.fromJson(Map json) { return QuickLinkData( diff --git a/lib/core/models/widget_models.dart b/lib/core/models/widget_models.dart index ef447a687..69e2c9970 100644 --- a/lib/core/models/widget_models.dart +++ b/lib/core/models/widget_models.dart @@ -9,9 +9,9 @@ class GradesWidgetData { String title; GradesWidgetData({ - @required this.title, - @required this.courseAcronyms, - @required this.grades, + required this.title, + required this.courseAcronyms, + required this.grades, }); } @@ -25,9 +25,9 @@ class ProgressWidgetData { String suffix; ProgressWidgetData( - {@required this.title, - @required this.progress, - @required this.elapsedDays, - @required this.totalDays, - @required this.suffix}); + {required this.title, + required this.progress, + required this.elapsedDays, + required this.totalDays, + required this.suffix}); } diff --git a/lib/core/viewmodels/choose_language_viewmodel.dart b/lib/core/viewmodels/choose_language_viewmodel.dart index 84f7bd280..f4fe0b338 100644 --- a/lib/core/viewmodels/choose_language_viewmodel.dart +++ b/lib/core/viewmodels/choose_language_viewmodel.dart @@ -25,7 +25,7 @@ class ChooseLanguageViewModel extends BaseViewModel { /// Localization class of the application. final AppIntl _appIntl; - ChooseLanguageViewModel({@required AppIntl intl}) : _appIntl = intl; + ChooseLanguageViewModel({required AppIntl intl}) : _appIntl = intl; List get languages { return [_appIntl.settings_english, _appIntl.settings_french]; diff --git a/lib/core/viewmodels/dashboard_viewmodel.dart b/lib/core/viewmodels/dashboard_viewmodel.dart index 64b416b6d..37d023bbd 100644 --- a/lib/core/viewmodels/dashboard_viewmodel.dart +++ b/lib/core/viewmodels/dashboard_viewmodel.dart @@ -192,7 +192,7 @@ class DashboardViewModel extends FutureViewModel> { /// List of courses for the current session final List courses = []; - DashboardViewModel({@required AppIntl intl}) : _appIntl = intl; + DashboardViewModel({required AppIntl intl}) : _appIntl = intl; @override Future> futureToRun() async { diff --git a/lib/core/viewmodels/emergency_viewmodel.dart b/lib/core/viewmodels/emergency_viewmodel.dart index aeb410d82..abd63065b 100644 --- a/lib/core/viewmodels/emergency_viewmodel.dart +++ b/lib/core/viewmodels/emergency_viewmodel.dart @@ -15,7 +15,7 @@ import 'package:notredame/core/viewmodels/security_viewmodel.dart'; class EmergencyViewModel extends SecurityViewModel { WebViewController webViewController; - EmergencyViewModel({@required AppIntl intl}) : super(intl: intl); + EmergencyViewModel({required AppIntl intl}) : super(intl: intl); /// used to load the emergency procedures html files inside the webView Future loadHtmlFromAssets(String filename, Brightness brightness) async { diff --git a/lib/core/viewmodels/feedback_viewmodel.dart b/lib/core/viewmodels/feedback_viewmodel.dart index a6ca32345..01b9b78c0 100644 --- a/lib/core/viewmodels/feedback_viewmodel.dart +++ b/lib/core/viewmodels/feedback_viewmodel.dart @@ -37,7 +37,7 @@ class FeedbackViewModel extends FutureViewModel { // get the list of issues List get myIssues => _myIssues; - FeedbackViewModel({@required AppIntl intl}) : _appIntl = intl; + FeedbackViewModel({required AppIntl intl}) : _appIntl = intl; /// Create a Github issue with [UserFeedback] and the screenshot associated. Future sendFeedback( diff --git a/lib/core/viewmodels/grades_details_viewmodel.dart b/lib/core/viewmodels/grades_details_viewmodel.dart index 69dabe0d1..922fb3423 100644 --- a/lib/core/viewmodels/grades_details_viewmodel.dart +++ b/lib/core/viewmodels/grades_details_viewmodel.dart @@ -27,7 +27,7 @@ class GradesDetailsViewModel extends FutureViewModel { /// Used to get the current course selected of the student Course course; - GradesDetailsViewModel({this.course, @required AppIntl intl}) + GradesDetailsViewModel({this.course, required AppIntl intl}) : _appIntl = intl; @override diff --git a/lib/core/viewmodels/grades_viewmodel.dart b/lib/core/viewmodels/grades_viewmodel.dart index 1b2fb41d2..b799c6157 100644 --- a/lib/core/viewmodels/grades_viewmodel.dart +++ b/lib/core/viewmodels/grades_viewmodel.dart @@ -30,7 +30,7 @@ class GradesViewModel extends FutureViewModel>> { /// session. final List sessionOrder = []; - GradesViewModel({@required AppIntl intl}) : _appIntl = intl; + GradesViewModel({required AppIntl intl}) : _appIntl = intl; @override Future>> futureToRun() async => diff --git a/lib/core/viewmodels/login_viewmodel.dart b/lib/core/viewmodels/login_viewmodel.dart index 749955761..93c190b79 100644 --- a/lib/core/viewmodels/login_viewmodel.dart +++ b/lib/core/viewmodels/login_viewmodel.dart @@ -39,7 +39,7 @@ class LoginViewModel extends BaseViewModel { /// Used to enable/disable the "log in" button bool get canSubmit => _universalCode.isNotEmpty && _password.isNotEmpty; - LoginViewModel({@required AppIntl intl}) : _appIntl = intl; + LoginViewModel({required AppIntl intl}) : _appIntl = intl; /// Use to get the value associated to each settings key final PreferencesService _preferencesService = locator(); diff --git a/lib/core/viewmodels/more_viewmodel.dart b/lib/core/viewmodels/more_viewmodel.dart index 8a941098a..a7ce1674c 100644 --- a/lib/core/viewmodels/more_viewmodel.dart +++ b/lib/core/viewmodels/more_viewmodel.dart @@ -54,7 +54,7 @@ class MoreViewModel extends FutureViewModel { /// Get the application version String get appVersion => _appVersion; - MoreViewModel({@required AppIntl intl}) : _appIntl = intl; + MoreViewModel({required AppIntl intl}) : _appIntl = intl; @override Future futureToRun() async { diff --git a/lib/core/viewmodels/not_found_viewmodel.dart b/lib/core/viewmodels/not_found_viewmodel.dart index 3e4b7945d..c59b1d7cd 100644 --- a/lib/core/viewmodels/not_found_viewmodel.dart +++ b/lib/core/viewmodels/not_found_viewmodel.dart @@ -32,7 +32,7 @@ class NotFoundViewModel extends BaseViewModel { Artboard _artboard; Artboard get artboard => _artboard; - NotFoundViewModel({@required String pageName}) : notFoundPageName = pageName { + NotFoundViewModel({required String pageName}) : notFoundPageName = pageName { _analyticsService.logEvent( tag, "An unknown page ($pageName) has been access from the app."); } diff --git a/lib/core/viewmodels/profile_viewmodel.dart b/lib/core/viewmodels/profile_viewmodel.dart index 58139e95f..2bb87959e 100644 --- a/lib/core/viewmodels/profile_viewmodel.dart +++ b/lib/core/viewmodels/profile_viewmodel.dart @@ -38,7 +38,7 @@ class ProfileViewModel extends FutureViewModel> { String get universalAccessCode => _userRepository?.monETSUser?.universalCode ?? ''; - ProfileViewModel({@required AppIntl intl}) : _appIntl = intl; + ProfileViewModel({required AppIntl intl}) : _appIntl = intl; double get programProgression { final ProgramCredits programCredits = ProgramCredits(); diff --git a/lib/core/viewmodels/schedule_viewmodel.dart b/lib/core/viewmodels/schedule_viewmodel.dart index 9321a7b28..132d6126d 100644 --- a/lib/core/viewmodels/schedule_viewmodel.dart +++ b/lib/core/viewmodels/schedule_viewmodel.dart @@ -73,7 +73,7 @@ class ScheduleViewModel extends FutureViewModel> { /// Get current locale Locale get locale => _settingsManager.locale; - ScheduleViewModel({@required AppIntl intl, DateTime initialSelectedDate}) + ScheduleViewModel({required AppIntl intl, DateTime initialSelectedDate}) : _appIntl = intl, selectedDate = initialSelectedDate ?? DateTime.now(), focusedDate = ValueNotifier(initialSelectedDate ?? DateTime.now()); diff --git a/lib/core/viewmodels/security_viewmodel.dart b/lib/core/viewmodels/security_viewmodel.dart index 32cc23981..d0c5c53f7 100644 --- a/lib/core/viewmodels/security_viewmodel.dart +++ b/lib/core/viewmodels/security_viewmodel.dart @@ -19,7 +19,7 @@ class SecurityViewModel extends BaseViewModel { final List markersList; - SecurityViewModel({@required AppIntl intl}) + SecurityViewModel({required AppIntl intl}) : emergencyProcedureList = emergencyProcedures(intl), markersList = markers(intl); diff --git a/lib/core/viewmodels/settings_viewmodel.dart b/lib/core/viewmodels/settings_viewmodel.dart index 20ebed7e2..187fc6701 100644 --- a/lib/core/viewmodels/settings_viewmodel.dart +++ b/lib/core/viewmodels/settings_viewmodel.dart @@ -46,7 +46,7 @@ class SettingsViewModel extends FutureViewModel { _currentLocale = value; } - SettingsViewModel({@required AppIntl intl}) : _appIntl = intl; + SettingsViewModel({required AppIntl intl}) : _appIntl = intl; @override Future futureToRun() async { diff --git a/lib/ui/widgets/dismissible_card.dart b/lib/ui/widgets/dismissible_card.dart index 80ba3919b..2c0390922 100644 --- a/lib/ui/widgets/dismissible_card.dart +++ b/lib/ui/widgets/dismissible_card.dart @@ -14,8 +14,8 @@ class DismissibleCard extends StatelessWidget { const DismissibleCard( {Key key, - @required this.onDismissed, - @required this.child, + required this.onDismissed, + required this.child, this.elevation = 1, this.cardColor, this.isBusy = false}) diff --git a/test/helpers.dart b/test/helpers.dart index 798cb6b61..65f401ea4 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -61,7 +61,7 @@ void unregister() { /// Load the l10n classes. Take the [child] widget to test Widget localizedWidget( - {@required Widget child, + {required Widget child, bool useScaffold = true, String locale = 'en', double textScaleFactor = 0.9}) => diff --git a/test/mock/services/flutter_secure_storage_mock.dart b/test/mock/services/flutter_secure_storage_mock.dart index 6775d7f80..5e1a8a59d 100644 --- a/test/mock/services/flutter_secure_storage_mock.dart +++ b/test/mock/services/flutter_secure_storage_mock.dart @@ -9,26 +9,26 @@ import 'package:mockito/mockito.dart'; class FlutterSecureStorageMock extends Mock implements FlutterSecureStorage { /// Stub the read function of [FlutterSecureStorage] static void stubRead(FlutterSecureStorageMock mock, - {@required String key, @required String valueToReturn}) { + {required String key, required String valueToReturn}) { when(mock.read(key: key)).thenAnswer((_) async => valueToReturn); } /// Stub the read function of [FlutterSecureStorage] with an [Exception] static void stubReadException(FlutterSecureStorageMock mock, - {@required String key, @required Exception exceptionToThrow}) { + {required String key, required Exception exceptionToThrow}) { when(mock.read(key: key)).thenThrow(exceptionToThrow); } /// Stub the write function of [FlutterSecureStorage] with an [Exception] static void stubWriteException(FlutterSecureStorageMock mock, - {@required String key, @required Exception exceptionToThrow}) { + {required String key, required Exception exceptionToThrow}) { when(mock.write(key: key, value: anyNamed("value"))) .thenThrow(exceptionToThrow); } /// Stub the delete function of [FlutterSecureStorage] with an [Exception] static void stubDeleteException(FlutterSecureStorageMock mock, - {@required String key, @required Exception exceptionToThrow}) { + {required String key, required Exception exceptionToThrow}) { when(mock.delete(key: key)).thenThrow(exceptionToThrow); } } diff --git a/test/mock/services/siren_flutter_service_mock.dart b/test/mock/services/siren_flutter_service_mock.dart index 36826c96b..46ff35783 100644 --- a/test/mock/services/siren_flutter_service_mock.dart +++ b/test/mock/services/siren_flutter_service_mock.dart @@ -18,13 +18,13 @@ class SirenFlutterServiceMock extends Mock implements SirenFlutterService { /// Stub the localVersion function of [SirenFlutterService] static void stubLocalVersion(SirenFlutterServiceMock mock, - {@required Version valueToReturn}) { + {required Version valueToReturn}) { when(mock.localVersion).thenAnswer((_) async => valueToReturn); } /// Stub the storeVersion function of [SirenFlutterService] static void stubStoreVersion(SirenFlutterServiceMock mock, - {@required Version valueToReturn}) { + {required Version valueToReturn}) { when(mock.storeVersion).thenAnswer((_) async => valueToReturn); } } From d7fc81a0321062f325671b7eee68464db8e3c2e7 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 00:58:06 -0500 Subject: [PATCH 06/62] Migrate models to null safety --- lib/core/models/feedback.dart | 4 ++-- lib/core/models/feedback_issue.dart | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/core/models/feedback.dart b/lib/core/models/feedback.dart index 476022c59..50aa08a99 100644 --- a/lib/core/models/feedback.dart +++ b/lib/core/models/feedback.dart @@ -4,8 +4,8 @@ class CustomFeedback { this.feedbackText, }); - String feedbackText; - String feedbackEmail; + String? feedbackText; + String? feedbackEmail; @override String toString() { diff --git a/lib/core/models/feedback_issue.dart b/lib/core/models/feedback_issue.dart index 5dccbb517..88d673b85 100644 --- a/lib/core/models/feedback_issue.dart +++ b/lib/core/models/feedback_issue.dart @@ -2,13 +2,14 @@ import 'package:github/github.dart'; class FeedbackIssue { - int id; - String htmlUrl; - String simpleDescription; - String state; - bool isOpen; - int number; - String createdAt; + late int id; + late String htmlUrl; + late String simpleDescription; + late String state; + late bool isOpen; + late int number; + late String createdAt; + // Constructor FeedbackIssue(Issue issue) { id = issue.id; From ac2dba1fc88105ad08a8b6a2e01f9f721b486ca1 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 01:34:18 -0500 Subject: [PATCH 07/62] Migrate main to null safety --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 6be1ef4db..c04e222b6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -80,7 +80,7 @@ class ETSMobile extends StatelessWidget { feedbackBuilder: (context, onSubmit, scrollController) => CustomFeedbackForm( onSubmit: onSubmit, - scrollController: scrollController, + scrollController: scrollController ?? ScrollController(), ), localizationsDelegates: [ GlobalMaterialLocalizations.delegate, From 50ce75e5e8ec7f9bd747f1f847f7e556e1d33154 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 22 Nov 2023 23:51:14 -0500 Subject: [PATCH 08/62] Migrate managers to null safety --- lib/core/managers/cache_manager.dart | 2 +- lib/core/managers/course_repository.dart | 188 ++++++++++++----------- lib/core/managers/settings_manager.dart | 32 ++-- lib/core/managers/user_repository.dart | 78 ++++++---- 4 files changed, 166 insertions(+), 134 deletions(-) diff --git a/lib/core/managers/cache_manager.dart b/lib/core/managers/cache_manager.dart index 79b529661..87a57860e 100644 --- a/lib/core/managers/cache_manager.dart +++ b/lib/core/managers/cache_manager.dart @@ -28,7 +28,7 @@ class CacheManager { /// Get from the cache the value associated with [key]. /// Throw a [CacheException] if the [key] doesn't exist. Future get(String key) async { - final lib.FileInfo fileInfo = await _cacheManager.getFileFromCache(key); + final lib.FileInfo? fileInfo = await _cacheManager.getFileFromCache(key); if (fileInfo == null) { _analyticsService.logEvent( diff --git a/lib/core/managers/course_repository.dart b/lib/core/managers/course_repository.dart index fc81c31f5..cf963dd6b 100644 --- a/lib/core/managers/course_repository.dart +++ b/lib/core/managers/course_repository.dart @@ -52,25 +52,25 @@ class CourseRepository { final SignetsAPIClient _signetsApiClient = locator(); /// Student list of courses - List _courses; + List? _courses; - List get courses => _courses; + List? get courses => _courses; /// List of the courses activities for the student - List _coursesActivities; + List? _coursesActivities; - List get coursesActivities => _coursesActivities; + List? get coursesActivities => _coursesActivities; /// List of the schedule activities for the student in the active session - List _scheduleActivities; + List? _scheduleActivities; - List get scheduleActivities => _scheduleActivities; + List? get scheduleActivities => _scheduleActivities; /// List of session where the student has been registered. /// The sessions are organized from oldest to youngest - List _sessions; + List? _sessions; - List get sessions => _sessions; + List? get sessions => _sessions; /// Return the active sessions which mean the sessions that the endDate isn't already passed. List get activeSessions { @@ -81,14 +81,14 @@ class CourseRepository { ?.where((session) => session.endDate.isAfter(now) || session.endDate.isAtSameMomentAs(now)) - ?.toList() ?? + .toList() ?? []; } /// Get and update the list of courses activities for the active sessions. /// After fetching the new activities from the [SignetsApi] the [CacheManager] /// is updated with the latest version of the activities. - Future> getCoursesActivities( + Future?> getCoursesActivities( {bool fromCacheOnly = false}) async { // Force fromCacheOnly mode when user has no connectivity if (!(await _networkingService.hasConnectivity())) { @@ -109,7 +109,7 @@ class CourseRepository { .map((e) => CourseActivity.fromJson(e as Map)) .toList(); _logger.d( - "$tag - getCoursesActivities: ${_coursesActivities.length} activities loaded from cache"); + "$tag - getCoursesActivities: ${_coursesActivities?.length ?? 0} activities loaded from cache"); } on CacheException catch (_) { _logger.e( "$tag - getCoursesActivities: exception raised will trying to load activities from cache."); @@ -128,15 +128,17 @@ class CourseRepository { await getSessions(); } - final String password = await _userRepository.getPassword(); - for (final Session session in activeSessions) { - fetchedCoursesActivities.addAll( - await _signetsApiClient.getCoursesActivities( - username: _userRepository.monETSUser.universalCode, - password: password, - session: session.shortName)); - _logger.d( - "$tag - getCoursesActivities: fetched ${fetchedCoursesActivities.length} activities."); + if(_userRepository.monETSUser != null) { + final String password = await _userRepository.getPassword(); + for (final Session session in activeSessions) { + fetchedCoursesActivities.addAll( + await _signetsApiClient.getCoursesActivities( + username: _userRepository.monETSUser!.universalCode, + password: password, + session: session.shortName)); + _logger.d( + "$tag - getCoursesActivities: fetched ${fetchedCoursesActivities.length} activities."); + } } } on Exception catch (e, stacktrace) { _analyticsService.logError(tag, @@ -152,13 +154,13 @@ class CourseRepository { activeSessionStartDate = element.startDate; } } - _coursesActivities.removeWhere( + _coursesActivities?.removeWhere( (element) => element.startDateTime.isAfter(activeSessionStartDate)); // Update the list of activities to avoid duplicate activities for (final CourseActivity activity in fetchedCoursesActivities) { - if (!_coursesActivities.contains(activity)) { - _coursesActivities.add(activity); + if (_coursesActivities != null && !_coursesActivities!.contains(activity)) { + _coursesActivities!.add(activity); } } @@ -199,7 +201,7 @@ class CourseRepository { .map((e) => ScheduleActivity.fromJson(e as Map)) .toList(); _logger.d( - "$tag - getScheduleActivities: ${_scheduleActivities.length} activities loaded from cache"); + "$tag - getScheduleActivities: ${_scheduleActivities!.length} activities loaded from cache"); } on CacheException catch (_) { _logger.e( "$tag - getScheduleActivities: exception raised will trying to load activities from cache."); @@ -207,7 +209,7 @@ class CourseRepository { } if (fromCacheOnly) { - return _scheduleActivities; + return _scheduleActivities!; } final List fetchedScheduleActivities = []; @@ -218,16 +220,19 @@ class CourseRepository { await getSessions(); } - final String password = await _userRepository.getPassword(); + if(_userRepository.monETSUser != null) { + final String password = await _userRepository.getPassword(); - for (final Session session in activeSessions) { - fetchedScheduleActivities.addAll( - await _signetsApiClient.getScheduleActivities( - username: _userRepository.monETSUser.universalCode, - password: password, - session: session.shortName)); - _logger.d( - "$tag - getScheduleActivities: fetched ${fetchedScheduleActivities.length} activities."); + for (final Session session in activeSessions) { + fetchedScheduleActivities.addAll( + await _signetsApiClient.getScheduleActivities( + username: _userRepository.monETSUser!.universalCode, + password: password, + session: session.shortName)); + + _logger.d( + "$tag - getScheduleActivities: fetched ${fetchedScheduleActivities.length} activities."); + } } } on Exception catch (e, stacktrace) { _analyticsService.logError(tag, @@ -238,8 +243,8 @@ class CourseRepository { // Update the list of activities to avoid duplicate activities for (final ScheduleActivity activity in fetchedScheduleActivities) { - if (!_scheduleActivities.contains(activity)) { - _scheduleActivities.add(activity); + if (_scheduleActivities != null && !_scheduleActivities!.contains(activity)) { + _scheduleActivities!.add(activity); } } @@ -253,7 +258,7 @@ class CourseRepository { "$tag - getScheduleActivities: exception raised will trying to update the cache."); } - return _scheduleActivities; + return _scheduleActivities!; } /// Get the list of session on which the student was active. @@ -272,7 +277,7 @@ class CourseRepository { .map((e) => Session.fromJson(e as Map)) .toList(); _logger.d( - "$tag - getSessions: ${_sessions.length} sessions loaded from cache."); + "$tag - getSessions: ${_sessions?.length ?? 0} sessions loaded from cache."); } on CacheException catch (_) { _logger.e( "$tag - getSessions: exception raised will trying to load the sessions from cache."); @@ -281,37 +286,39 @@ class CourseRepository { // Don't try to update cache when offline if (!(await _networkingService.hasConnectivity())) { - return _sessions; + return _sessions!; } try { - // getPassword will try to authenticate the user if not authenticated. - final String password = await _userRepository.getPassword(); - - final List fetchedSession = await _signetsApiClient.getSessions( - username: _userRepository.monETSUser.universalCode, - password: password); - _logger - .d("$tag - getSessions: ${fetchedSession.length} sessions fetched."); - for (final Session session in fetchedSession) { - if (!_sessions.contains(session)) { - _sessions.add(session); + if(_userRepository.monETSUser != null) { + // getPassword will try to authenticate the user if not authenticated. + final String password = await _userRepository.getPassword(); + + final List fetchedSession = await _signetsApiClient.getSessions( + username: _userRepository.monETSUser!.universalCode, + password: password); + _logger + .d("$tag - getSessions: ${fetchedSession.length} sessions fetched."); + for (final Session session in fetchedSession) { + if (!_sessions!.contains(session)) { + _sessions!.add(session); + } } - } - // Update cache - _cacheManager.update(sessionsCacheKey, jsonEncode(_sessions)); + // Update cache + _cacheManager.update(sessionsCacheKey, jsonEncode(_sessions)); + } } on CacheException catch (_) { _logger.e( "$tag - getSessions: exception raised will trying to update the cache."); - return _sessions; + return _sessions!; } on Exception catch (e, stacktrace) { _analyticsService.logError( tag, "Exception raised during getSessions: $e", e, stacktrace); rethrow; } - return _sessions; + return _sessions!; } /// Get the student's course list. After fetching the courses from [SignetsApi], @@ -336,7 +343,7 @@ class CourseRepository { .map((e) => Course.fromJson(e as Map)) .toList(); _logger.d( - "$tag - getCourses: ${_courses.length} courses loaded from cache"); + "$tag - getCourses: ${_courses!.length} courses loaded from cache"); } on CacheException catch (_) { _logger.e( "$tag - getCourses: exception raised will trying to load courses from cache."); @@ -344,19 +351,21 @@ class CourseRepository { } if (fromCacheOnly) { - return _courses; + return _courses!; } final List fetchedCourses = []; final Map> fetchedCourseReviews = {}; try { - final String password = await _userRepository.getPassword(); + if(_userRepository.monETSUser != null) { + final String password = await _userRepository.getPassword(); - fetchedCourses.addAll(await _signetsApiClient.getCourses( - username: _userRepository.monETSUser.universalCode, - password: password)); - _logger.d("$tag - getCourses: fetched ${fetchedCourses.length} courses."); + fetchedCourses.addAll(await _signetsApiClient.getCourses( + username: _userRepository.monETSUser!.universalCode, + password: password)); + _logger.d("$tag - getCourses: fetched ${fetchedCourses.length} courses."); + } } on Exception catch (e, stacktrace) { _analyticsService.logError( tag, "Exception raised during getCourses: $e", e, stacktrace); @@ -370,7 +379,7 @@ class CourseRepository { _logger.d("$tag - getCourses: $e during getCoursesEvaluations. Ignored"); } - _courses.clear(); + _courses!.clear(); // If there isn't the grade yet, will fetch the summary. // We don't do this for every course to avoid losing time. @@ -383,10 +392,10 @@ class CourseRepository { _logger.e( "$tag - getCourses: Exception raised while trying to get summary " "of ${course.acronym}."); - _courses.add(course); + _courses!.add(course); } } else { - _courses.add(course); + _courses!.add(course); } } @@ -399,14 +408,14 @@ class CourseRepository { "$tag - getCourses: exception raised will trying to update the cache."); } - return _courses; + return _courses!; } /// Get the summary (detailed evaluations) of [course]. After fetching the /// summary from [SignetsApi], the [CacheManager] is updated with the latest /// version of the course. Return the course with the summary set. Future getCourseSummary(Course course) async { - CourseSummary summary; + CourseSummary? summary; // Don't try to update the summary when user has no connection if (!(await _networkingService.hasConnectivity())) { @@ -414,13 +423,15 @@ class CourseRepository { } try { - final String password = await _userRepository.getPassword(); + if(_userRepository.monETSUser != null) { + final String password = await _userRepository.getPassword(); - summary = await _signetsApiClient.getCourseSummary( - username: _userRepository.monETSUser.universalCode, - password: password, - course: course); - _logger.d("$tag - getCourseSummary: fetched ${course.acronym} summary."); + summary = await _signetsApiClient.getCourseSummary( + username: _userRepository.monETSUser!.universalCode, + password: password, + course: course); + _logger.d("$tag - getCourseSummary: fetched ${course.acronym} summary."); + } } on Exception catch (e, stacktrace) { if (e is ApiException) { if (e.errorCode == SignetsError.gradesEmpty || @@ -439,10 +450,10 @@ class CourseRepository { _courses ??= []; // Update courses list - _courses.removeWhere((element) => + _courses!.removeWhere((element) => course.acronym == element.acronym && course.session == element.session); course.summary = summary; - _courses.add(course); + _courses!.add(course); try { // Update cache @@ -470,15 +481,17 @@ class CourseRepository { await getSessions(); } - for (final Session session in _sessions) { - sessionReviews = await _signetsApiClient.getCourseReviews( - username: _userRepository.monETSUser.universalCode, - password: password, - session: session); - reviews.putIfAbsent(session.shortName, () => sessionReviews); - _logger.d( - "$tag - getCoursesEvaluations: fetched ${reviews[session.shortName].length} " - "evaluations for session ${session.shortName}."); + if(_userRepository.monETSUser != null) { + for (final Session session in _sessions!) { + sessionReviews = await _signetsApiClient.getCourseReviews( + username: _userRepository.monETSUser!.universalCode, + password: password, + session: session); + reviews.putIfAbsent(session.shortName, () => sessionReviews); + _logger.d( + "$tag - getCoursesEvaluations: fetched ${reviews[session.shortName]?.length ?? 0} " + "evaluations for session ${session.shortName}."); + } } } on Exception catch (e, stacktrace) { _analyticsService.logError(tag, e.toString(), e, stacktrace); @@ -490,14 +503,13 @@ class CourseRepository { } /// Get the evaluation for a course or null if not found. - CourseReview _getReviewForCourse( + CourseReview? _getReviewForCourse( Course course, Map> reviews) { if (reviews.containsKey(course.session)) { - return reviews[course.session].firstWhere( + return reviews[course.session]!.firstWhere( (element) => element.acronym == course.acronym && - element.group == course.group, - orElse: () => null); + element.group == course.group); } return null; } diff --git a/lib/core/managers/settings_manager.dart b/lib/core/managers/settings_manager.dart index 93160f8c6..699c05e31 100644 --- a/lib/core/managers/settings_manager.dart +++ b/lib/core/managers/settings_manager.dart @@ -30,16 +30,16 @@ class SettingsManager with ChangeNotifier { locator(); /// current ThemeMode - ThemeMode _themeMode; + ThemeMode? _themeMode; /// current Locale - Locale _locale; + Locale? _locale; /// Get current time DateTime get dateTimeNow => DateTime.now(); /// Get ThemeMode - ThemeMode get themeMode { + ThemeMode? get themeMode { _preferencesService.getString(PreferencesFlag.theme).then((value) => { if (value != null) { @@ -72,7 +72,7 @@ class SettingsManager with ChangeNotifier { } /// Get Locale - Locale get locale { + Locale? get locale { _preferencesService.getString(PreferencesFlag.locale).then((value) { if (value != null) { _locale = @@ -136,7 +136,7 @@ class SettingsManager with ChangeNotifier { /// Set ThemeMode void setThemeMode(ThemeMode value) { _preferencesService.setString(PreferencesFlag.theme, value.toString()); - // Log the event + _analyticsService.logEvent( "${tag}_${EnumToString.convertToString(PreferencesFlag.theme)}", EnumToString.convertToString(value)); @@ -144,16 +144,18 @@ class SettingsManager with ChangeNotifier { notifyListeners(); } - /// Set Locale void setLocale(String value) { _locale = AppIntl.supportedLocales.firstWhere((e) => e.toString() == value); - _preferencesService.setString(PreferencesFlag.locale, _locale.languageCode); - // Log the event + _analyticsService.logEvent( "${tag}_${EnumToString.convertToString(PreferencesFlag.locale)}", - _locale.languageCode); - _locale = Locale(_locale.languageCode); - notifyListeners(); + _locale?.languageCode ?? 'Not found'); + + if(_locale != null) { + _preferencesService.setString(PreferencesFlag.locale, _locale!.languageCode); + _locale = Locale(_locale!.languageCode); + notifyListeners(); + } } /// Get the settings of the schedule, these are loaded from the user preferences. @@ -221,7 +223,7 @@ class SettingsManager with ChangeNotifier { /// Add/update the value of [flag] Future setDynamicString( - PreferencesFlag flag, String key, String value) async { + PreferencesFlag flag, String key, String? value) async { if (value == null) { return _preferencesService.removeDynamicPreferencesFlag(flag, key); } @@ -241,7 +243,7 @@ class SettingsManager with ChangeNotifier { } /// Get the value of [flag] - Future getString(PreferencesFlag flag) async { + Future getString(PreferencesFlag flag) async { // Log the event _analyticsService.logEvent( "${tag}_${EnumToString.convertToString(flag)}", 'getString'); @@ -249,7 +251,7 @@ class SettingsManager with ChangeNotifier { } /// Get the value of [flag] - Future getDynamicString(PreferencesFlag flag, String key) async { + Future getDynamicString(PreferencesFlag flag, String key) async { // Log the event _analyticsService.logEvent("${tag}_${flag.toString()}", 'getString'); return _preferencesService.getDynamicString(flag, key); @@ -265,7 +267,7 @@ class SettingsManager with ChangeNotifier { } /// Get the value of [flag] - Future getBool(PreferencesFlag flag) async { + Future getBool(PreferencesFlag flag) async { // Log the event _analyticsService.logEvent( "${tag}_${EnumToString.convertToString(flag)}", 'getBool'); diff --git a/lib/core/managers/user_repository.dart b/lib/core/managers/user_repository.dart index 80f6947e9..fd2061d1a 100644 --- a/lib/core/managers/user_repository.dart +++ b/lib/core/managers/user_repository.dart @@ -50,19 +50,19 @@ class UserRepository { final MonETSAPIClient _monEtsApiClient = locator(); /// Mon ETS user for the student - MonETSUser _monETSUser; + MonETSUser? _monETSUser; - MonETSUser get monETSUser => _monETSUser; + MonETSUser? get monETSUser => _monETSUser; /// Information for the student profile - ProfileStudent _info; + ProfileStudent? _info; - ProfileStudent get info => _info; + ProfileStudent? get info => _info; /// List of the programs for the student - List _programs; + List? _programs; - List get programs => _programs; + List? get programs => _programs; /// Authenticate the user using the [username] (for a student should be the /// universal code like AAXXXXX). @@ -105,7 +105,7 @@ class UserRepository { } await _analyticsService.setUserProperties( - userId: username, domain: _monETSUser.domain); + userId: username, domain: _monETSUser!.domain); // Save the credentials in the secure storage if (!isSilent) { @@ -133,6 +133,13 @@ class UserRepository { final username = await _secureStorage.read(key: usernameSecureKey); if (username != null) { final password = await _secureStorage.read(key: passwordSecureKey); + if(password == null) { + await _secureStorage.deleteAll(); + _analyticsService.logError( + tag, + "SilentAuthenticate - PlatformException(Handled) - $passwordSecureKey not found"); + return false; + } return await authenticate( username: username, password: password, isSilent: true); } @@ -178,6 +185,12 @@ class UserRepository { } try { final password = await _secureStorage.read(key: passwordSecureKey); + if(password == null) { + await _secureStorage.deleteAll(); + _analyticsService.logError(tag, + "getPassword - $passwordSecureKey not found"); + throw const ApiException(prefix: tag, message: "Not authenticated"); + } return password; } on PlatformException catch (e, stacktrace) { await _secureStorage.deleteAll(); @@ -211,7 +224,7 @@ class UserRepository { .map((e) => Program.fromJson(e as Map)) .toList(); _logger.d( - "$tag - getPrograms: ${_programs.length} programs loaded from cache."); + "$tag - getPrograms: ${_programs!.length} programs loaded from cache."); } on CacheException catch (_) { _logger.e( "$tag - getPrograms: exception raised while trying to load the programs from cache."); @@ -219,31 +232,33 @@ class UserRepository { } if (fromCacheOnly) { - return _programs; + return _programs!; } try { // getPassword will try to authenticate the user if not authenticated. final String password = await getPassword(); - _programs = await _signetsApiClient.getPrograms( - username: _monETSUser.universalCode, password: password); - - _logger.d("$tag - getPrograms: ${_programs.length} programs fetched."); + if(_monETSUser != null) { + _programs = await _signetsApiClient.getPrograms( + username: _monETSUser!.universalCode, password: password); + + _logger.d("$tag - getPrograms: ${_programs!.length} programs fetched."); - // Update cache - _cacheManager.update(programsCacheKey, jsonEncode(_programs)); + // Update cache + _cacheManager.update(programsCacheKey, jsonEncode(_programs)); + } } on CacheException catch (_) { _logger.e( "$tag - getPrograms: exception raised while trying to update the cache."); - return _programs; + return _programs!; } on Exception catch (e, stacktrace) { _analyticsService.logError( tag, "Exception raised during getPrograms: $e", e, stacktrace); rethrow; } - return _programs; + return _programs!; } /// Get the profile information. @@ -272,45 +287,48 @@ class UserRepository { } if (fromCacheOnly) { - return _info; + return _info!; } try { // getPassword will try to authenticate the user if not authenticated. final String password = await getPassword(); - final fetchedInfo = await _signetsApiClient.getStudentInfo( - username: _monETSUser.universalCode, password: password); + if(_monETSUser != null) { + final fetchedInfo = await _signetsApiClient.getStudentInfo( + username: _monETSUser!.universalCode, password: password); - _logger.d("$tag - getInfo: $fetchedInfo info fetched."); + _logger.d("$tag - getInfo: $fetchedInfo info fetched."); - if (_info != fetchedInfo) { - _info = fetchedInfo ?? _info; + if (_info != fetchedInfo) { + _info = fetchedInfo; - // Update cache - _cacheManager.update(infoCacheKey, jsonEncode(_info)); + // Update cache + _cacheManager.update(infoCacheKey, jsonEncode(_info)); + } } + } on CacheException catch (_) { _logger.e( "$tag - getInfo: exception raised while trying to update the cache."); - return _info; + return _info!; } on Exception catch (e, stacktrace) { _analyticsService.logError( tag, "Exception raised during getInfo: $e", e, stacktrace); rethrow; } - return _info; + return _info!; } /// Check whether the user was previously authenticated. Future wasPreviouslyLoggedIn() async { try { - final String username = await _secureStorage.read(key: passwordSecureKey); + final username = await _secureStorage.read(key: passwordSecureKey); if (username != null) { - final String password = + final password = await _secureStorage.read(key: passwordSecureKey); - return password.isNotEmpty; + return password != null && password.isNotEmpty; } } on PlatformException catch (e, stacktrace) { await _secureStorage.deleteAll(); From 1714af2464c0e325e4e543648e7a11dd31e74998 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 21 Dec 2023 00:00:44 -0500 Subject: [PATCH 09/62] Migrate ViewModels to null safety --- .../viewmodels/choose_language_viewmodel.dart | 3 - .../viewmodels/contributors_viewmodel.dart | 4 +- lib/core/viewmodels/dashboard_viewmodel.dart | 85 +++++++++---------- lib/core/viewmodels/emergency_viewmodel.dart | 6 +- lib/core/viewmodels/faq_viewmodel.dart | 4 +- lib/core/viewmodels/feedback_viewmodel.dart | 31 +++---- .../viewmodels/grades_details_viewmodel.dart | 12 +-- lib/core/viewmodels/grades_viewmodel.dart | 8 +- lib/core/viewmodels/login_viewmodel.dart | 4 +- lib/core/viewmodels/more_viewmodel.dart | 6 +- lib/core/viewmodels/not_found_viewmodel.dart | 11 ++- lib/core/viewmodels/profile_viewmodel.dart | 9 +- .../schedule_settings_viewmodel.dart | 31 ++++--- lib/core/viewmodels/schedule_viewmodel.dart | 44 +++++----- lib/core/viewmodels/security_viewmodel.dart | 4 +- lib/core/viewmodels/settings_viewmodel.dart | 16 ++-- lib/core/viewmodels/startup_viewmodel.dart | 2 +- 17 files changed, 129 insertions(+), 151 deletions(-) diff --git a/lib/core/viewmodels/choose_language_viewmodel.dart b/lib/core/viewmodels/choose_language_viewmodel.dart index f4fe0b338..d31a48f82 100644 --- a/lib/core/viewmodels/choose_language_viewmodel.dart +++ b/lib/core/viewmodels/choose_language_viewmodel.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:stacked/stacked.dart'; diff --git a/lib/core/viewmodels/contributors_viewmodel.dart b/lib/core/viewmodels/contributors_viewmodel.dart index 2272a88f9..523c4a22b 100644 --- a/lib/core/viewmodels/contributors_viewmodel.dart +++ b/lib/core/viewmodels/contributors_viewmodel.dart @@ -6,10 +6,10 @@ class ContributorsViewModel extends FutureViewModel { /// Create a GitHub Client, with anonymous authentication by default GitHub github = GitHub(); - Future> get contributors => _contributors; + Future>? get contributors => _contributors; /// List of contributors - Future> _contributors; + Future>? _contributors; @override Future futureToRun() { diff --git a/lib/core/viewmodels/dashboard_viewmodel.dart b/lib/core/viewmodels/dashboard_viewmodel.dart index 37d023bbd..45b57076b 100644 --- a/lib/core/viewmodels/dashboard_viewmodel.dart +++ b/lib/core/viewmodels/dashboard_viewmodel.dart @@ -44,16 +44,16 @@ class DashboardViewModel extends FutureViewModel> { locator(); /// All dashboard displayable cards - Map _cards; + Map? _cards; /// Localization class of the application. final AppIntl _appIntl; /// Update code that must be used to prompt user for update if necessary. - UpdateCode updateCode; + UpdateCode? updateCode; /// Cards to display on dashboard - List _cardsToDisplay; + List? _cardsToDisplay; /// Percentage of completed days for the session double _progress = 0.0; @@ -91,10 +91,10 @@ class DashboardViewModel extends FutureViewModel> { } /// Get the status of all displayable cards - Map get cards => _cards; + Map? get cards => _cards; /// Get cards to display - List get cardsToDisplay => _cardsToDisplay; + List? get cardsToDisplay => _cardsToDisplay; ProgressBarText _currentProgressBarText = ProgressBarText.daysElapsedWithTotalDays; @@ -114,7 +114,7 @@ class DashboardViewModel extends FutureViewModel> { final PreferencesService preferencesService = locator(); final InAppReviewService inAppReviewService = locator(); - DateTime ratingTimerFlagDate = + DateTime? ratingTimerFlagDate = await preferencesService.getDateTime(PreferencesFlag.ratingTimer); final hasRatingBeenRequested = await preferencesService @@ -251,19 +251,19 @@ class DashboardViewModel extends FutureViewModel> { final List grades = courses.map((course) { // Code copied from GradeButton.gradeString if (course.grade != null) { - return course.grade; + return course.grade!; } else if (course.summary != null && - course.summary.markOutOf > 0 && - !(course.inReviewPeriod && !course.reviewCompleted)) { + course.summary!.markOutOf > 0 && + !(course.inReviewPeriod && (course.reviewCompleted != null && !course.reviewCompleted!))) { return _appIntl.grades_grade_in_percentage( - course.summary.currentMarkInPercent.round()); + course.summary!.currentMarkInPercent.round()); } return _appIntl.grades_not_available; }).toList(); await _appWidgetService.sendGradesData(GradesWidgetData( title: - "${_appIntl.grades_title} - ${_courseRepository.activeSessions.first.shortName ?? _appIntl.session_without}", + "${_appIntl.grades_title} - ${_courseRepository.activeSessions.first.shortName.isEmpty ? _appIntl.session_without : ''}", courseAcronyms: acronyms, grades: grades)); await _appWidgetService.updateWidget(WidgetType.grades); @@ -280,8 +280,8 @@ class DashboardViewModel extends FutureViewModel> { /// Change the order of [flag] card from [oldIndex] to [newIndex]. void setOrder(PreferencesFlag flag, int newIndex) { - _cardsToDisplay.remove(flag); - _cardsToDisplay.insert(newIndex, flag); + _cardsToDisplay?.remove(flag); + _cardsToDisplay?.insert(newIndex, flag); updatePreferences(); @@ -292,9 +292,9 @@ class DashboardViewModel extends FutureViewModel> { /// Hide [flag] card from dashboard by setting int value -1 void hideCard(PreferencesFlag flag) { - _cards.update(flag, (value) => -1); + _cards?.update(flag, (value) => -1); - _cardsToDisplay.remove(flag); + _cardsToDisplay?.remove(flag); updatePreferences(); @@ -305,7 +305,7 @@ class DashboardViewModel extends FutureViewModel> { /// Reset all card indexes to their default values void setAllCardsVisible() { - _cards.updateAll((key, value) { + _cards?.updateAll((key, value) { _settingsManager .setInt(key, key.index - PreferencesFlag.broadcastCard.index) .then((value) { @@ -329,11 +329,11 @@ class DashboardViewModel extends FutureViewModel> { if (_cards != null) { final orderedCards = SplayTreeMap.from( - _cards, (a, b) => _cards[a].compareTo(_cards[b])); + _cards!, (a, b) => _cards![a]!.compareTo(_cards![b]!)); orderedCards.forEach((key, value) { if (value >= 0) { - _cardsToDisplay.insert(value, key); + _cardsToDisplay?.insert(value, key); } }); } @@ -349,24 +349,21 @@ class DashboardViewModel extends FutureViewModel> { // Update pref _preferencesService.setString(PreferencesFlag.broadcastChange, remoteConfigService.dashboardMessageEn); - if (_cards[PreferencesFlag.broadcastCard] < 0) { - _cards.updateAll((key, value) { - if (value >= 0) { - return value + 1; - } else { - return value; - } + if (_cards != null && _cards![PreferencesFlag.broadcastCard]! < 0) { + _cards?.updateAll((key, value) { + return value >= 0 + ? value + 1 + : value; }); - _cards[PreferencesFlag.broadcastCard] = 0; + _cards![PreferencesFlag.broadcastCard] = 0; } } } Future> futureToRunSessionProgressBar() async { - String progressBarText = - await _settingsManager.getString(PreferencesFlag.progressBarText); - - progressBarText ??= ProgressBarText.daysElapsedWithTotalDays.toString(); + final progressBarText = + await _settingsManager.getString(PreferencesFlag.progressBarText) + ?? ProgressBarText.daysElapsedWithTotalDays.toString(); _currentProgressBarText = ProgressBarText.values .firstWhere((e) => e.toString() == progressBarText); @@ -398,11 +395,11 @@ class DashboardViewModel extends FutureViewModel> { // ignore: return_type_invalid_for_catch_error .catchError(onError) .whenComplete(() async { - if (_todayDateEvents.isEmpty) { + if (_todayDateEvents.isEmpty && _courseRepository.coursesActivities != null) { final DateTime tomorrowDate = todayDate.add(const Duration(days: 1)); // Build the list for (final CourseActivity course - in _courseRepository.coursesActivities) { + in _courseRepository.coursesActivities!) { final DateTime dateOnly = course.startDateTime; if (isSameDay(todayDate, dateOnly) && todayDate.compareTo(course.endDateTime) < 0) { @@ -424,7 +421,7 @@ class DashboardViewModel extends FutureViewModel> { setBusyForObject(_tomorrowDateEvents, false); }); - return value; + return value ?? []; }); } @@ -435,7 +432,7 @@ class DashboardViewModel extends FutureViewModel> { for (final courseAcronym in todayDateEvents) { final courseKey = courseAcronym.courseGroup.split('-')[0]; - final String activityCodeToUse = await _settingsManager.getDynamicString( + final String? activityCodeToUse = await _settingsManager.getDynamicString( PreferencesFlag.scheduleLaboratoryGroup, courseKey); if (activityCodeToUse == ActivityCode.labGroupA) { @@ -454,10 +451,13 @@ class DashboardViewModel extends FutureViewModel> { /// Update cards order and display status in preferences void updatePreferences() { - for (final MapEntry element in _cards.entries) { - _cards[element.key] = _cardsToDisplay.indexOf(element.key); + if(_cards == null || _cardsToDisplay == null) { + return; + } + for (final MapEntry element in _cards!.entries) { + _cards![element.key] = _cardsToDisplay!.indexOf(element.key); _settingsManager - .setInt(element.key, _cardsToDisplay.indexOf(element.key)) + .setInt(element.key, _cardsToDisplay!.indexOf(element.key)) .then((value) { if (!value) { Fluttertoast.showToast(msg: _appIntl.error); @@ -497,7 +497,7 @@ class DashboardViewModel extends FutureViewModel> { if (!busy(courses)) { setBusyForObject(courses, true); if (_courseRepository.sessions == null || - _courseRepository.sessions.isEmpty) { + _courseRepository.sessions!.isEmpty) { // ignore: return_type_invalid_for_catch_error await _courseRepository.getSessions().catchError(onError); } @@ -520,7 +520,6 @@ class DashboardViewModel extends FutureViewModel> { notifyListeners(); // ignore: return_type_invalid_for_catch_error _courseRepository.getCourses().catchError(onError).then((value) { - if (value != null) { // Update the courses list courses.clear(); for (final Course course in value) { @@ -528,7 +527,6 @@ class DashboardViewModel extends FutureViewModel> { courses.add(course); } } - } }).whenComplete(() { setBusyForObject(courses, false); }); @@ -536,13 +534,14 @@ class DashboardViewModel extends FutureViewModel> { return courses; }, onError: onError); } + return courses; } /// Prompt the update for the app if the navigation service arguments passed /// is not none. When [UpdateCode] is forced, the user will be force to update. /// If [UpdateCode] is not forced, the user will be prompted to update. static Future promptUpdate( - BuildContext context, UpdateCode updateCode) async { + BuildContext context, UpdateCode? updateCode) async { if (updateCode != null && updateCode != UpdateCode.none) { final appIntl = AppIntl.of(context); @@ -551,11 +550,11 @@ class DashboardViewModel extends FutureViewModel> { switch (updateCode) { case UpdateCode.force: isAForcedUpdate = true; - message = appIntl.update_version_message_force; + message = appIntl!.update_version_message_force; break; case UpdateCode.ask: isAForcedUpdate = false; - message = appIntl.update_version_message; + message = appIntl!.update_version_message; break; case UpdateCode.none: return; diff --git a/lib/core/viewmodels/emergency_viewmodel.dart b/lib/core/viewmodels/emergency_viewmodel.dart index abd63065b..ad412464f 100644 --- a/lib/core/viewmodels/emergency_viewmodel.dart +++ b/lib/core/viewmodels/emergency_viewmodel.dart @@ -2,7 +2,6 @@ import 'dart:convert'; // Flutter imports: -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // Package imports: @@ -13,12 +12,11 @@ import 'package:webview_flutter/webview_flutter.dart'; import 'package:notredame/core/viewmodels/security_viewmodel.dart'; class EmergencyViewModel extends SecurityViewModel { - WebViewController webViewController; - EmergencyViewModel({required AppIntl intl}) : super(intl: intl); /// used to load the emergency procedures html files inside the webView - Future loadHtmlFromAssets(String filename, Brightness brightness) async { + Future loadHtmlFromAssets(String filename, Brightness brightness, + WebViewController webViewController) async { final String fileText = await rootBundle.loadString(filename); final String data = Uri.dataFromString( diff --git a/lib/core/viewmodels/faq_viewmodel.dart b/lib/core/viewmodels/faq_viewmodel.dart index 4381124fb..e82e8275c 100644 --- a/lib/core/viewmodels/faq_viewmodel.dart +++ b/lib/core/viewmodels/faq_viewmodel.dart @@ -17,7 +17,7 @@ class FaqViewModel extends BaseViewModel { final LaunchUrlService _launchUrlService = locator(); - Locale get locale => _settingsManager.locale; + Locale? get locale => _settingsManager.locale; String mailtoStr(String email, String subject) { return 'mailto:$email?subject=$subject'; @@ -30,7 +30,7 @@ class FaqViewModel extends BaseViewModel { Future openMail(String addressEmail, BuildContext context) async { var email = ""; if (addressEmail == AppInfo.email) { - email = mailtoStr(addressEmail, AppIntl.of(context).email_subject); + email = mailtoStr(addressEmail, AppIntl.of(context)!.email_subject); } else { email = mailtoStr(addressEmail, ""); } diff --git a/lib/core/viewmodels/feedback_viewmodel.dart b/lib/core/viewmodels/feedback_viewmodel.dart index 01b9b78c0..94f16e438 100644 --- a/lib/core/viewmodels/feedback_viewmodel.dart +++ b/lib/core/viewmodels/feedback_viewmodel.dart @@ -2,9 +2,6 @@ import 'dart:io'; import 'dart:typed_data'; -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: import 'package:feedback/feedback.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -55,21 +52,19 @@ class FeedbackViewModel extends FutureViewModel { feedbackText: feedback.text, fileName: fileName, feedbackType: reportType.name, - email: feedback.extra.containsKey('email') - ? feedback.extra['email'].toString() + email: feedback.extra != null && feedback.extra!.containsKey('email') + ? feedback.extra!['email'].toString() : null); - if (issue != null) { - setBusy(true); - _myIssues.add(FeedbackIssue(issue)); - // Sort by state open first and by number descending - _myIssues.sort( - (a, b) => b.state.compareTo(a.state) * 100000 + b.number - a.number); - setBusy(false); - // Save the issue number in the preferences - _preferencesService.setString( - PreferencesFlag.ghIssues, _myIssues.map((e) => e.number).join(',')); - } + setBusy(true); + _myIssues.add(FeedbackIssue(issue)); + // Sort by state open first and by number descending + _myIssues.sort( + (a, b) => b.state.compareTo(a.state) * 100000 + b.number - a.number); + setBusy(false); + // Save the issue number in the preferences + _preferencesService.setString( + PreferencesFlag.ghIssues, _myIssues.map((e) => e.number).join(',')); file.deleteSync(); @@ -80,7 +75,7 @@ class FeedbackViewModel extends FutureViewModel { } List encodeScreenshotForGithub(Uint8List screenshot) { - return image.encodePng(image.copyResize(image.decodeImage(screenshot), + return image.encodePng(image.copyResize(image.decodeImage(screenshot) ?? image.Image(0, 0), width: _screenshotImageWidth)); } @@ -88,7 +83,7 @@ class FeedbackViewModel extends FutureViewModel { @override Future futureToRun() async { // Get the issues number from the preferences - final String issuesString = + final String? issuesString = await _preferencesService.getString(PreferencesFlag.ghIssues); // If there is no issues, return 0 diff --git a/lib/core/viewmodels/grades_details_viewmodel.dart b/lib/core/viewmodels/grades_details_viewmodel.dart index 922fb3423..953190b1c 100644 --- a/lib/core/viewmodels/grades_details_viewmodel.dart +++ b/lib/core/viewmodels/grades_details_viewmodel.dart @@ -27,7 +27,7 @@ class GradesDetailsViewModel extends FutureViewModel { /// Used to get the current course selected of the student Course course; - GradesDetailsViewModel({this.course, required AppIntl intl}) + GradesDetailsViewModel({required this.course, required AppIntl intl}) : _appIntl = intl; @override @@ -39,11 +39,9 @@ class GradesDetailsViewModel extends FutureViewModel { .getCourseSummary(course) // ignore: return_type_invalid_for_catch_error .catchError(onError) - ?.then((value) { - if (value != null) { + .then((value) { course = value; - } - })?.whenComplete(() { + }).whenComplete(() { setBusyForObject(course, false); }); @@ -68,10 +66,8 @@ class GradesDetailsViewModel extends FutureViewModel { Future refresh() async { try { setBusyForObject(course, true); - await _courseRepository.getCourseSummary(course)?.then((value) { - if (value != null) { + await _courseRepository.getCourseSummary(course).then((value) { course = value; - } }); notifyListeners(); setBusyForObject(course, false); diff --git a/lib/core/viewmodels/grades_viewmodel.dart b/lib/core/viewmodels/grades_viewmodel.dart index b799c6157..635ad41e4 100644 --- a/lib/core/viewmodels/grades_viewmodel.dart +++ b/lib/core/viewmodels/grades_viewmodel.dart @@ -39,9 +39,9 @@ class GradesViewModel extends FutureViewModel>> { _buildCoursesBySession(coursesCached); // ignore: return_type_invalid_for_catch_error _courseRepository.getCourses().catchError(onError).then((value) { - if (value != null) { + if (_courseRepository.courses != null) { // Update the courses list - _buildCoursesBySession(_courseRepository.courses); + _buildCoursesBySession(_courseRepository.courses!); } }).whenComplete(() { setBusy(false); @@ -61,7 +61,9 @@ class GradesViewModel extends FutureViewModel>> { // ignore: return_type_invalid_for_catch_error try { await _courseRepository.getCourses(); - _buildCoursesBySession(_courseRepository.courses); + if(_courseRepository.courses != null) { + _buildCoursesBySession(_courseRepository.courses!); + } notifyListeners(); } on Exception catch (error) { onError(error); diff --git a/lib/core/viewmodels/login_viewmodel.dart b/lib/core/viewmodels/login_viewmodel.dart index 93c190b79..dacc6948b 100644 --- a/lib/core/viewmodels/login_viewmodel.dart +++ b/lib/core/viewmodels/login_viewmodel.dart @@ -45,7 +45,7 @@ class LoginViewModel extends BaseViewModel { final PreferencesService _preferencesService = locator(); /// Validate the format of the universal code - String validateUniversalCode(String value) { + String? validateUniversalCode(String value) { if (value.isEmpty) { _universalCode = ""; return _appIntl.login_error_field_required; @@ -58,7 +58,7 @@ class LoginViewModel extends BaseViewModel { } /// Validate there is a password typed - String validatePassword(String value) { + String? validatePassword(String value) { if (value.isEmpty) { _password = ""; return _appIntl.login_error_field_required; diff --git a/lib/core/viewmodels/more_viewmodel.dart b/lib/core/viewmodels/more_viewmodel.dart index a7ce1674c..0be36a325 100644 --- a/lib/core/viewmodels/more_viewmodel.dart +++ b/lib/core/viewmodels/more_viewmodel.dart @@ -47,12 +47,12 @@ class MoreViewModel extends FutureViewModel { /// Used to redirect on the dashboard. final NavigationService navigationService = locator(); - String _appVersion; + String? _appVersion; final AppIntl _appIntl; /// Get the application version - String get appVersion => _appVersion; + String? get appVersion => _appVersion; MoreViewModel({required AppIntl intl}) : _appIntl = intl; @@ -62,7 +62,7 @@ class MoreViewModel extends FutureViewModel { await PackageInfo.fromPlatform() .then((value) => _appVersion = value.version) - .onError((error, stackTrace) => null); + .onError((error, stackTrace) => 'Error: $error'); setBusy(false); return true; diff --git a/lib/core/viewmodels/not_found_viewmodel.dart b/lib/core/viewmodels/not_found_viewmodel.dart index c59b1d7cd..c7068488f 100644 --- a/lib/core/viewmodels/not_found_viewmodel.dart +++ b/lib/core/viewmodels/not_found_viewmodel.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: import 'package:rive/rive.dart'; import 'package:stacked/stacked.dart'; @@ -29,8 +26,8 @@ class NotFoundViewModel extends BaseViewModel { final String notFoundPageName; - Artboard _artboard; - Artboard get artboard => _artboard; + Artboard? _artboard; + Artboard? get artboard => _artboard; NotFoundViewModel({required String pageName}) : notFoundPageName = pageName { _analyticsService.logEvent( @@ -56,7 +53,9 @@ class NotFoundViewModel extends BaseViewModel { void startRiveAnimation() { try { - _riveAnimationService.addControllerToAnimation(artboard: _artboard); + if(artboard != null) { + _riveAnimationService.addControllerToAnimation(artboard: _artboard!); + } } on Exception catch (e, stacktrace) { _analyticsService.logError(tag, "An Error has occured during rive animation start.", e, stacktrace); diff --git a/lib/core/viewmodels/profile_viewmodel.dart b/lib/core/viewmodels/profile_viewmodel.dart index 2bb87959e..e1e5f387d 100644 --- a/lib/core/viewmodels/profile_viewmodel.dart +++ b/lib/core/viewmodels/profile_viewmodel.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: import 'package:ets_api_clients/models.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -36,7 +33,7 @@ class ProfileViewModel extends FutureViewModel> { /// Return the universal access code of the student String get universalAccessCode => - _userRepository?.monETSUser?.universalCode ?? ''; + _userRepository.monETSUser?.universalCode ?? ''; ProfileViewModel({required AppIntl intl}) : _appIntl = intl; @@ -83,11 +80,11 @@ class ProfileViewModel extends FutureViewModel> { /// Return the list of programs for the student List get programList { - if (_programList == null || _programList.isEmpty) { + if (_programList.isEmpty) { _programList = []; } if (_userRepository.programs != null) { - _programList = _userRepository.programs; + _programList = _userRepository.programs!; } _programList.sort((a, b) => b.status.compareTo(a.status)); diff --git a/lib/core/viewmodels/schedule_settings_viewmodel.dart b/lib/core/viewmodels/schedule_settings_viewmodel.dart index 7f035fa59..ee922b412 100644 --- a/lib/core/viewmodels/schedule_settings_viewmodel.dart +++ b/lib/core/viewmodels/schedule_settings_viewmodel.dart @@ -19,11 +19,11 @@ class ScheduleSettingsViewModel final CourseRepository _courseRepository = locator(); /// Current calendar format - CalendarFormat _calendarFormat; + CalendarFormat? _calendarFormat; - CalendarFormat get calendarFormat => _calendarFormat; + CalendarFormat? get calendarFormat => _calendarFormat; - set calendarFormat(CalendarFormat format) { + set calendarFormat(CalendarFormat? format) { setBusy(true); _settingsManager.setString(PreferencesFlag.scheduleCalendarFormat, EnumToString.convertToString(format)); @@ -39,11 +39,11 @@ class ScheduleSettingsViewModel ]; /// Current starting day of week - StartingDayOfWeek _startingDayOfWeek; + StartingDayOfWeek? _startingDayOfWeek; - StartingDayOfWeek get startingDayOfWeek => _startingDayOfWeek; + StartingDayOfWeek? get startingDayOfWeek => _startingDayOfWeek; - set startingDayOfWeek(StartingDayOfWeek day) { + set startingDayOfWeek(StartingDayOfWeek? day) { setBusy(true); _settingsManager.setString(PreferencesFlag.scheduleStartWeekday, EnumToString.convertToString(day)); @@ -59,11 +59,11 @@ class ScheduleSettingsViewModel ]; /// Current weekend day shown - WeekDays _otherDayOfWeek; + WeekDays? _otherDayOfWeek; - WeekDays get otherDayOfWeek => _otherDayOfWeek; + WeekDays? get otherDayOfWeek => _otherDayOfWeek; - set otherDayOfWeek(WeekDays day) { + set otherDayOfWeek(WeekDays? day) { setBusy(true); _settingsManager.setString(PreferencesFlag.scheduleOtherWeekday, EnumToString.convertToString(day)); @@ -135,7 +135,7 @@ class ScheduleSettingsViewModel /// This function is used to save the state of the selected course settings /// for a given course that has different laboratory group Future selectScheduleActivity( - String courseAcronym, ScheduleActivity scheduleActivityToSave) async { + String courseAcronym, ScheduleActivity? scheduleActivityToSave) async { setBusy(true); if (scheduleActivityToSave == null) { await _settingsManager.setDynamicString( @@ -145,8 +145,8 @@ class ScheduleSettingsViewModel PreferencesFlag.scheduleLaboratoryGroup, courseAcronym, scheduleActivityToSave.activityCode); + _selectedScheduleActivity[courseAcronym] = scheduleActivityToSave; } - _selectedScheduleActivity[courseAcronym] = scheduleActivityToSave; setBusy(false); } @@ -173,9 +173,9 @@ class ScheduleSettingsViewModel _scheduleActivitiesByCourse[activity.courseAcronym] = [activity]; } else { // Add the activity to the course. - if (!_scheduleActivitiesByCourse[activity.courseAcronym] - .contains(activity)) { - _scheduleActivitiesByCourse[activity.courseAcronym].add(activity); + final course = _scheduleActivitiesByCourse[activity.courseAcronym]; + if (course != null && !course.contains(activity)) { + course.add(activity); } } } @@ -188,8 +188,7 @@ class ScheduleSettingsViewModel final scheduleActivityCode = await _settingsManager.getDynamicString( PreferencesFlag.scheduleLaboratoryGroup, courseKey); final scheduleActivity = _scheduleActivitiesByCourse[courseKey] - .firstWhere((element) => element.activityCode == scheduleActivityCode, - orElse: () => null); + ?.firstWhere((element) => element.activityCode == scheduleActivityCode); if (scheduleActivity != null) { _selectedScheduleActivity[courseKey] = scheduleActivity; } diff --git a/lib/core/viewmodels/schedule_viewmodel.dart b/lib/core/viewmodels/schedule_viewmodel.dart index 132d6126d..9d01bfe98 100644 --- a/lib/core/viewmodels/schedule_viewmodel.dart +++ b/lib/core/viewmodels/schedule_viewmodel.dart @@ -41,7 +41,7 @@ class ScheduleViewModel extends FutureViewModel> { Map> _coursesActivities = {}; /// Courses associated to the student - List courses; + List? courses; /// Day currently selected DateTime selectedDate; @@ -71,9 +71,9 @@ class ScheduleViewModel extends FutureViewModel> { AppTheme.schedulePaletteLight.toList(); /// Get current locale - Locale get locale => _settingsManager.locale; + Locale? get locale => _settingsManager.locale; - ScheduleViewModel({required AppIntl intl, DateTime initialSelectedDate}) + ScheduleViewModel({required AppIntl intl, DateTime? initialSelectedDate}) : _appIntl = intl, selectedDate = initialSelectedDate ?? DateTime.now(), focusedDate = ValueNotifier(initialSelectedDate ?? DateTime.now()); @@ -110,7 +110,7 @@ class ScheduleViewModel extends FutureViewModel> { List selectedDateCalendarEvents(DateTime date) { return _coursesActivities[DateTime(date.year, date.month, date.day)] ?.map((eventData) => calendarEventData(eventData)) - ?.toList() ?? + .toList() ?? []; } @@ -121,7 +121,7 @@ class ScheduleViewModel extends FutureViewModel> { final associatedCourses = courses?.where( (element) => element.acronym == eventData.courseGroup.split('-')[0]); final associatedCourse = - associatedCourses?.isNotEmpty == true ? associatedCourses.first : null; + associatedCourses?.isNotEmpty == true ? associatedCourses?.first : null; return CalendarEventData( title: "${eventData.courseGroup.split('-')[0]}\n$courseLocation\n${eventData.activityName}", @@ -137,7 +137,7 @@ class ScheduleViewModel extends FutureViewModel> { if (!courseColors.containsKey(courseName)) { courseColors[courseName] = schedulePaletteThemeLight.removeLast(); } - return courseColors[courseName]; + return courseColors[courseName] ?? Colors.red; } List selectedWeekCalendarEvents() { @@ -167,12 +167,12 @@ class ScheduleViewModel extends FutureViewModel> { } bool get showWeekEvents => - settings[PreferencesFlag.scheduleShowWeekEvents] as bool ?? false; + settings[PreferencesFlag.scheduleShowWeekEvents] as bool; bool isLoadingEvents = false; bool get calendarViewSetting => - settings[PreferencesFlag.scheduleListView] as bool ?? true; + settings[PreferencesFlag.scheduleListView] as bool; @override Future> futureToRun() => @@ -210,13 +210,12 @@ class ScheduleViewModel extends FutureViewModel> { setBusyForObject(isLoadingEvents, false); }); }); - return value; + return value ?? []; }); Future assignScheduleActivities( List listOfSchedules) async { - if (listOfSchedules == null || - listOfSchedules.isEmpty || + if (listOfSchedules.isEmpty || !listOfSchedules.any((element) => element.activityCode == ActivityCode.labGroupA || element.activityCode == ActivityCode.labGroupB)) return; @@ -230,7 +229,7 @@ class ScheduleViewModel extends FutureViewModel> { if (!scheduleActivitiesByCourse.containsKey(activity.courseAcronym)) { scheduleActivitiesByCourse[activity.courseAcronym] = [activity]; } else { - scheduleActivitiesByCourse[activity.courseAcronym].add(activity); + scheduleActivitiesByCourse[activity.courseAcronym]?.add(activity); } } } @@ -258,11 +257,10 @@ class ScheduleViewModel extends FutureViewModel> { Future loadSettingsScheduleActivities() async { for (final courseAcronym in scheduleActivitiesByCourse.keys) { - final String activityCodeToUse = await _settingsManager.getDynamicString( + final String? activityCodeToUse = await _settingsManager.getDynamicString( PreferencesFlag.scheduleLaboratoryGroup, courseAcronym); final scheduleActivityToSet = scheduleActivitiesByCourse[courseAcronym] - .firstWhere((element) => element.activityCode == activityCodeToUse, - orElse: () => null); + ?.firstWhere((element) => element.activityCode == activityCodeToUse); if (scheduleActivityToSet != null) { settingsScheduleActivities[courseAcronym] = scheduleActivityToSet.name; } else { @@ -281,7 +279,7 @@ class ScheduleViewModel extends FutureViewModel> { // Build the map if (_courseRepository.coursesActivities != null) { - for (final CourseActivity course in _courseRepository.coursesActivities) { + for (final CourseActivity course in _courseRepository.coursesActivities!) { final DateTime dateOnly = course.startDateTime.subtract(Duration( hours: course.startDateTime.hour, minutes: course.startDateTime.minute)); @@ -335,15 +333,11 @@ class ScheduleViewModel extends FutureViewModel> { coursesActivities; } - // Access the array using the same instance inside the map. This is only required - // since the version 3.0.0 of table_calendar with the eventLoaders argument. - DateTime dateInArray; - return _coursesActivities.keys.any((element) { - dateInArray = element; - return isSameDay(element, date); - }) - ? _coursesActivities[dateInArray] - : []; + List activities = []; + if (_coursesActivities.containsKey(date)) { + activities = _coursesActivities[date] ?? []; + } + return activities; } Future setCalendarFormat(CalendarFormat format) async { diff --git a/lib/core/viewmodels/security_viewmodel.dart b/lib/core/viewmodels/security_viewmodel.dart index d0c5c53f7..dcc01a45f 100644 --- a/lib/core/viewmodels/security_viewmodel.dart +++ b/lib/core/viewmodels/security_viewmodel.dart @@ -13,7 +13,7 @@ import 'package:notredame/core/constants/markers.dart'; import 'package:notredame/core/models/emergency_procedure.dart'; class SecurityViewModel extends BaseViewModel { - GoogleMapController controller; + GoogleMapController? controller; final List emergencyProcedureList; @@ -49,6 +49,6 @@ class SecurityViewModel extends BaseViewModel { /// Used to set the color of the map void setMapStyle(String mapStyle) { - controller.setMapStyle(mapStyle); + controller?.setMapStyle(mapStyle); } } diff --git a/lib/core/viewmodels/settings_viewmodel.dart b/lib/core/viewmodels/settings_viewmodel.dart index 187fc6701..94e5fb740 100644 --- a/lib/core/viewmodels/settings_viewmodel.dart +++ b/lib/core/viewmodels/settings_viewmodel.dart @@ -17,17 +17,19 @@ class SettingsViewModel extends FutureViewModel { final AppIntl _appIntl; /// Current locale - String _currentLocale; + String? _currentLocale; /// Current theme - ThemeMode _selectedTheme; + ThemeMode? _selectedTheme; - ThemeMode get selectedTheme => _selectedTheme; + ThemeMode? get selectedTheme => _selectedTheme; /// Set theme - set selectedTheme(ThemeMode value) { - _settingsManager.setThemeMode(value); - _selectedTheme = value; + set selectedTheme(ThemeMode? value) { + if(value != null) { + _settingsManager.setThemeMode(value); + _selectedTheme = value; + } } String get currentLocale { @@ -52,7 +54,7 @@ class SettingsViewModel extends FutureViewModel { Future futureToRun() async { setBusy(true); await _settingsManager.fetchLanguageAndThemeMode(); - _currentLocale = _settingsManager.locale.languageCode; + _currentLocale = _settingsManager.locale?.languageCode; _selectedTheme = _settingsManager.themeMode; setBusy(false); return true; diff --git a/lib/core/viewmodels/startup_viewmodel.dart b/lib/core/viewmodels/startup_viewmodel.dart index de5525d10..38497eca8 100644 --- a/lib/core/viewmodels/startup_viewmodel.dart +++ b/lib/core/viewmodels/startup_viewmodel.dart @@ -62,7 +62,7 @@ class StartUpViewModel extends BaseViewModel { ]; for (final PreferencesFlag flag in flagsToCheck) { - final Object object = + final Object? object = await _preferencesService.getPreferencesFlag(flag); if (object is String) { From 1cd67b1bab1515fb78b2ef46fee04a78630fcf7f Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 22 Dec 2023 22:28:06 -0500 Subject: [PATCH 10/62] Migrate utils to null safety --- lib/ui/utils/discovery_components.dart | 98 +++++++++++++------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/lib/ui/utils/discovery_components.dart b/lib/ui/utils/discovery_components.dart index 10196faee..5da5ecbbe 100644 --- a/lib/ui/utils/discovery_components.dart +++ b/lib/ui/utils/discovery_components.dart @@ -27,16 +27,16 @@ List discoveryComponents(BuildContext context) { maxHeight: MediaQuery.of(context).size.height * 0.6), child: Column( children: [ - _buildHeader(AppIntl.of(context).discovery_navbar_dashboard_title, + _buildHeader(AppIntl.of(context)!.discovery_navbar_dashboard_title, context), Expanded( child: ListView( padding: EdgeInsets.zero, children: [ Text( - AppIntl.of(context).discovery_navbar_dashboard_details), + AppIntl.of(context)!.discovery_navbar_dashboard_details), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset( 'assets/animations/discovery/fr/dashboard_swipe.gif') else @@ -50,9 +50,9 @@ List discoveryComponents(BuildContext context) { ), ), Discovery( - path: null, + path: '', featureId: DiscoveryIds.bottomBarDashboardRestore, - title: AppIntl.of(context).dashboard_restore_all_cards_title, + title: AppIntl.of(context)!.dashboard_restore_all_cards_title, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.4), @@ -64,10 +64,10 @@ List discoveryComponents(BuildContext context) { children: [ _buildSkipDiscoveryButton(context), Text( - AppIntl.of(context).discovery_page_dashboard_restore, + AppIntl.of(context)!.discovery_page_dashboard_restore, ), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset( 'assets/animations/discovery/fr/dashboard_restore.gif') else @@ -90,15 +90,15 @@ List discoveryComponents(BuildContext context) { child: Column( children: [ _buildHeader( - AppIntl.of(context).discovery_navbar_schedule_title, context), + AppIntl.of(context)!.discovery_navbar_schedule_title, context), Expanded( child: ListView( padding: EdgeInsets.zero, children: [ - Text(AppIntl.of(context).discovery_navbar_schedule_details, + Text(AppIntl.of(context)!.discovery_navbar_schedule_details, textAlign: TextAlign.justify), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset( 'assets/animations/discovery/fr/schedule_calendar.png') else @@ -121,15 +121,15 @@ List discoveryComponents(BuildContext context) { child: Column( children: [ _buildHeader( - AppIntl.of(context).discovery_navbar_student_title, context), + AppIntl.of(context)!.discovery_navbar_student_title, context), Expanded( child: ListView( padding: EdgeInsets.zero, children: [ - Text(AppIntl.of(context).discovery_navbar_student_details, + Text(AppIntl.of(context)!.discovery_navbar_student_details, textAlign: TextAlign.justify), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset( 'assets/animations/discovery/fr/grade_details.gif') else @@ -152,15 +152,15 @@ List discoveryComponents(BuildContext context) { child: Column( children: [ _buildHeader( - AppIntl.of(context).discovery_navbar_ets_title, context), + AppIntl.of(context)!.discovery_navbar_ets_title, context), Expanded( child: ListView( padding: EdgeInsets.zero, children: [ - Text(AppIntl.of(context).discovery_navbar_ets_details, + Text(AppIntl.of(context)!.discovery_navbar_ets_details, textAlign: TextAlign.justify), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset('assets/animations/discovery/fr/ets_link.gif') else Image.asset( @@ -182,15 +182,15 @@ List discoveryComponents(BuildContext context) { child: Column( children: [ _buildHeader( - AppIntl.of(context).discovery_navbar_more_title, context), + AppIntl.of(context)!.discovery_navbar_more_title, context), Expanded( child: ListView( padding: EdgeInsets.zero, children: [ - Text(AppIntl.of(context).discovery_navbar_more_details, + Text(AppIntl.of(context)!.discovery_navbar_more_details, textAlign: TextAlign.justify), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset('assets/animations/discovery/fr/more.jpg') else Image.asset('assets/animations/discovery/en/more.jpg'), @@ -204,9 +204,9 @@ List discoveryComponents(BuildContext context) { ]), GroupDiscovery(name: DiscoveryGroupIds.pageSchedule, discoveries: [ Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsScheduleSettings, - title: AppIntl.of(context).schedule_settings_title, + title: AppIntl.of(context)!.schedule_settings_title, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.6), @@ -217,10 +217,10 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_navbar_schedule_details, + Text(AppIntl.of(context)!.discovery_navbar_schedule_details, textAlign: TextAlign.justify), const Text('\n'), - if (AppIntl.of(context).localeName == "fr") + if (AppIntl.of(context)!.localeName == "fr") Image.asset( 'assets/animations/discovery/fr/schedule_settings.gif') else @@ -236,9 +236,9 @@ List discoveryComponents(BuildContext context) { ]), GroupDiscovery(name: DiscoveryGroupIds.pageStudent, discoveries: [ Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsStudentGradeButton, - title: AppIntl.of(context).grades_title, + title: AppIntl.of(context)!.grades_title, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.25), @@ -251,12 +251,12 @@ List discoveryComponents(BuildContext context) { _buildSkipDiscoveryButton(context), Text( AppIntl.of(context) - .discovery_page_student_grades_session, + !.discovery_page_student_grades_session, textAlign: TextAlign.justify), const Text('\n'), Text( AppIntl.of(context) - .discovery_page_student_grades_grade_button, + !.discovery_page_student_grades_grade_button, textAlign: TextAlign.justify), ], ), @@ -266,9 +266,9 @@ List discoveryComponents(BuildContext context) { ), ), Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsStudentProfile, - title: AppIntl.of(context).profile_title, + title: AppIntl.of(context)!.profile_title, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.2), @@ -279,7 +279,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_student_profile, + Text(AppIntl.of(context)!.discovery_page_student_profile, textAlign: TextAlign.justify), ], ), @@ -291,7 +291,7 @@ List discoveryComponents(BuildContext context) { ]), GroupDiscovery(name: DiscoveryGroupIds.pageGradeDetails, discoveries: [ Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsGradeDetailsEvaluations, title: "", details: ConstrainedBox( @@ -304,7 +304,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_grade_details, + Text(AppIntl.of(context)!.discovery_page_grade_details, textAlign: TextAlign.justify), ], ), @@ -316,9 +316,9 @@ List discoveryComponents(BuildContext context) { ]), GroupDiscovery(name: DiscoveryGroupIds.pageMore, discoveries: [ Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsMoreBugReport, - title: AppIntl.of(context).more_report_bug, + title: AppIntl.of(context)!.more_report_bug, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.2), @@ -329,7 +329,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_more_report_bug, + Text(AppIntl.of(context)!.discovery_page_more_report_bug, textAlign: TextAlign.justify), ], ), @@ -339,9 +339,9 @@ List discoveryComponents(BuildContext context) { ), ), Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsMoreContributors, - title: AppIntl.of(context).more_contributors, + title: AppIntl.of(context)!.more_contributors, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.2), @@ -352,7 +352,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_more_contributors, + Text(AppIntl.of(context)!.discovery_page_more_contributors, textAlign: TextAlign.justify), ], ), @@ -362,9 +362,9 @@ List discoveryComponents(BuildContext context) { ), ), Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsMoreFaq, - title: AppIntl.of(context).need_help, + title: AppIntl.of(context)!.need_help, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.2), @@ -375,7 +375,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_faq, + Text(AppIntl.of(context)!.discovery_page_faq, textAlign: TextAlign.justify), ], ), @@ -385,9 +385,9 @@ List discoveryComponents(BuildContext context) { ), ), Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsMoreSettings, - title: AppIntl.of(context).more_settings, + title: AppIntl.of(context)!.more_settings, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.2), @@ -398,7 +398,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_more_settings, + Text(AppIntl.of(context)!.discovery_page_more_settings, textAlign: TextAlign.justify), ], ), @@ -408,9 +408,9 @@ List discoveryComponents(BuildContext context) { ), ), Discovery( - path: null, + path: '', featureId: DiscoveryIds.detailsMoreThankYou, - title: AppIntl.of(context).title_ets_mobile, + title: AppIntl.of(context)!.title_ets_mobile, details: ConstrainedBox( constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.2), @@ -421,7 +421,7 @@ List discoveryComponents(BuildContext context) { padding: EdgeInsets.zero, children: [ _buildSkipDiscoveryButton(context), - Text(AppIntl.of(context).discovery_page_thankyou_message, + Text(AppIntl.of(context)!.discovery_page_thankyou_message, textAlign: TextAlign.justify), ], ), @@ -444,7 +444,7 @@ Padding _buildHeader(String title, BuildContext context) { style: Theme.of(context) .textTheme .headline6 - .copyWith(color: Colors.white)), + !.copyWith(color: Colors.white)), _buildSkipDiscoveryButton(context) ], ), @@ -456,7 +456,7 @@ Align _buildSkipDiscoveryButton(BuildContext context) { alignment: Alignment.topRight, child: TextButton( onPressed: () => dismissDiscovery(context), - child: Text(AppIntl.of(context).skip_discovery, + child: Text(AppIntl.of(context)!.skip_discovery, style: const TextStyle(color: AppTheme.etsLightRed)), ), ); From 9778d14cddc167512ca152667ba14ba56f209f2f Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 22 Dec 2023 23:47:44 -0500 Subject: [PATCH 11/62] Migrate views to null safety --- lib/core/utils/utils.dart | 2 +- lib/ui/widgets/base_scaffold.dart | 14 ++-- lib/ui/widgets/bottom_bar.dart | 12 +-- lib/ui/widgets/custom_feedback.dart | 10 +-- lib/ui/widgets/dismissible_card.dart | 7 +- lib/ui/widgets/grade_button.dart | 16 ++-- lib/ui/widgets/grade_circular_progress.dart | 22 +++--- lib/ui/widgets/grade_evaluation_tile.dart | 48 ++++++------ lib/ui/widgets/grade_not_available.dart | 10 +-- lib/ui/widgets/haptics_container.dart | 2 +- lib/ui/widgets/password_text_field.dart | 4 +- lib/ui/widgets/schedule_calendar_tile.dart | 34 ++++----- lib/ui/widgets/schedule_settings.dart | 82 +++++++++++---------- lib/ui/widgets/student_program.dart | 22 +++--- 14 files changed, 146 insertions(+), 139 deletions(-) diff --git a/lib/core/utils/utils.dart b/lib/core/utils/utils.dart index 2c12245db..9a4654a9e 100644 --- a/lib/core/utils/utils.dart +++ b/lib/core/utils/utils.dart @@ -19,7 +19,7 @@ mixin Utils { } } - static double getGradeInPercentage(double grade, double maxGrade) { + static double getGradeInPercentage(double? grade, double? maxGrade) { if (grade == null || maxGrade == null || grade == 0.0 || maxGrade == 0.0) { return 0.0; } diff --git a/lib/ui/widgets/base_scaffold.dart b/lib/ui/widgets/base_scaffold.dart index 90d585727..a004ebad0 100644 --- a/lib/ui/widgets/base_scaffold.dart +++ b/lib/ui/widgets/base_scaffold.dart @@ -19,13 +19,13 @@ import 'package:notredame/ui/widgets/bottom_bar.dart'; /// Basic Scaffold to avoid boilerplate code in the application. /// Contains a loader controlled by [_isLoading] class BaseScaffold extends StatefulWidget { - final AppBar appBar; + final AppBar? appBar; - final Widget body; + final Widget? body; - final FloatingActionButton fab; + final FloatingActionButton? fab; - final FloatingActionButtonLocation fabPosition; + final FloatingActionButtonLocation? fabPosition; final bool _showBottomBar; @@ -56,7 +56,7 @@ class _BaseScaffoldState extends State { final NetworkingService _networkingService = locator(); - StreamSubscription _subscription; + late StreamSubscription _subscription; @override void initState() { @@ -88,7 +88,7 @@ class _BaseScaffoldState extends State { top: false, child: Stack( children: [ - widget.body, + widget.body ?? const SizedBox(), if (widget._isLoading) buildLoading( isInteractionLimitedWhileLoading: @@ -116,7 +116,7 @@ class _BaseScaffoldState extends State { height: MediaQuery.of(context).size.height / 30, ), Text( - AppIntl.of(context).no_connectivity, + AppIntl.of(context)!.no_connectivity, textAlign: TextAlign.center, ), ], diff --git a/lib/ui/widgets/bottom_bar.dart b/lib/ui/widgets/bottom_bar.dart index 69ff87825..c4427fa94 100644 --- a/lib/ui/widgets/bottom_bar.dart +++ b/lib/ui/widgets/bottom_bar.dart @@ -34,7 +34,7 @@ class _BottomBarState extends State { @override Widget build(BuildContext context) { - _currentView = _defineIndex(ModalRoute.of(context).settings.name); + _currentView = _defineIndex(ModalRoute.of(context)!.settings.name!); return BottomNavigationBar( type: BottomNavigationBarType.fixed, elevation: 0, @@ -104,23 +104,23 @@ class _BottomBarState extends State { BottomNavigationBarItem( icon: _buildDiscoveryFeatureDescriptionWidget( context, RouterPaths.dashboard, Icons.dashboard), - label: AppIntl.of(context).title_dashboard), + label: AppIntl.of(context)!.title_dashboard), BottomNavigationBarItem( icon: _buildDiscoveryFeatureDescriptionWidget( context, RouterPaths.schedule, Icons.schedule), - label: AppIntl.of(context).title_schedule), + label: AppIntl.of(context)!.title_schedule), BottomNavigationBarItem( icon: _buildDiscoveryFeatureDescriptionWidget( context, RouterPaths.student, Icons.school), - label: AppIntl.of(context).title_student), + label: AppIntl.of(context)!.title_student), BottomNavigationBarItem( icon: _buildDiscoveryFeatureDescriptionWidget( context, RouterPaths.ets, Icons.account_balance), - label: AppIntl.of(context).title_ets), + label: AppIntl.of(context)!.title_ets), BottomNavigationBarItem( icon: _buildDiscoveryFeatureDescriptionWidget( context, RouterPaths.more, Icons.dehaze), - label: AppIntl.of(context).title_more), + label: AppIntl.of(context)!.title_more), ]; } diff --git a/lib/ui/widgets/custom_feedback.dart b/lib/ui/widgets/custom_feedback.dart index 4694cbd7a..e0ca50db0 100644 --- a/lib/ui/widgets/custom_feedback.dart +++ b/lib/ui/widgets/custom_feedback.dart @@ -13,13 +13,13 @@ import 'package:notredame/core/models/feedback.dart'; /// The submit button is disabled until the user provides the feedback type and a feedback text. class CustomFeedbackForm extends StatefulWidget { const CustomFeedbackForm({ - Key key, - this.onSubmit, + Key? key, + required this.onSubmit, this.scrollController, }) : super(key: key); final OnSubmit onSubmit; - final ScrollController scrollController; + final ScrollController? scrollController; @override _CustomFeedbackFormState createState() => _CustomFeedbackFormState(); @@ -70,9 +70,9 @@ class _CustomFeedbackFormState extends State { TextButton( // disable this button until the user has specified a feedback onPressed: _customFeedback.feedbackText != null && - _customFeedback.feedbackText.isNotEmpty + _customFeedback.feedbackText!.isNotEmpty ? () => widget.onSubmit( - _customFeedback.feedbackText, + _customFeedback.feedbackText!, extras: { 'email': _customFeedback.feedbackEmail, }, diff --git a/lib/ui/widgets/dismissible_card.dart b/lib/ui/widgets/dismissible_card.dart index 2c0390922..c312cced3 100644 --- a/lib/ui/widgets/dismissible_card.dart +++ b/lib/ui/widgets/dismissible_card.dart @@ -1,6 +1,9 @@ // Flutter imports: import 'package:flutter/material.dart'; +// Project imports: +import 'package:notredame/ui/utils/app_theme.dart'; + class DismissibleCard extends StatelessWidget { final Widget child; @@ -13,11 +16,11 @@ class DismissibleCard extends StatelessWidget { final bool isBusy; const DismissibleCard( - {Key key, + {Key? key, required this.onDismissed, required this.child, this.elevation = 1, - this.cardColor, + this.cardColor = AppTheme.appletsPurple, this.isBusy = false}) : super(key: key); diff --git a/lib/ui/widgets/grade_button.dart b/lib/ui/widgets/grade_button.dart index 4772f1884..5dcdcaf57 100644 --- a/lib/ui/widgets/grade_button.dart +++ b/lib/ui/widgets/grade_button.dart @@ -26,13 +26,13 @@ class GradeButton extends StatelessWidget { /// Settings manager final SettingsManager _settingsManager = locator(); - GradeButton(this.course, {this.showDiscovery}); + GradeButton(this.course, {this.showDiscovery = false}); @override Widget build(BuildContext context) => Card( child: InkWell( onTap: () async { - if (ModalRoute.of(context).settings.name == RouterPaths.dashboard || + if (ModalRoute.of(context)!.settings.name == RouterPaths.dashboard || await _settingsManager .getBool(PreferencesFlag.discoveryStudentGrade) == true) { @@ -51,12 +51,12 @@ class GradeButton extends StatelessWidget { /// will return [grades_not_available]. String gradeString(AppIntl intl) { if (course.grade != null) { - return course.grade; + return course.grade!; } else if (course.summary != null && - course.summary.markOutOf > 0 && - !(course.inReviewPeriod && !course.reviewCompleted)) { + course.summary!.markOutOf > 0 && + !(course.inReviewPeriod && !(course.reviewCompleted ?? false))) { return intl.grades_grade_in_percentage( - course.summary.currentMarkInPercent.round()); + course.summary!.currentMarkInPercent.round()); } return intl.grades_not_available; @@ -90,7 +90,7 @@ class GradeButton extends StatelessWidget { style: Theme.of(context) .textTheme .bodyText1 - .copyWith(color: Colors.white), + !.copyWith(color: Colors.white), ), ), ), @@ -102,7 +102,7 @@ class GradeButton extends StatelessWidget { ), Expanded( child: Center( - child: Text(gradeString(AppIntl.of(context)), + child: Text(gradeString(AppIntl.of(context)!), style: TextStyle( fontSize: 22, color: Theme.of(context).brightness == Brightness.light diff --git a/lib/ui/widgets/grade_circular_progress.dart b/lib/ui/widgets/grade_circular_progress.dart index 4511a3f0a..431045c94 100644 --- a/lib/ui/widgets/grade_circular_progress.dart +++ b/lib/ui/widgets/grade_circular_progress.dart @@ -10,14 +10,14 @@ import 'package:notredame/ui/utils/app_theme.dart'; class GradeCircularProgress extends StatefulWidget { final bool completed; - final String finalGrade; - final double studentGrade; - final double averageGrade; + final String? finalGrade; + final double? studentGrade; + final double? averageGrade; final double ratio; const GradeCircularProgress(this.ratio, - {Key key, - this.completed, + {Key? key, + this.completed = false, this.finalGrade, this.studentGrade, this.averageGrade}) @@ -29,8 +29,8 @@ class GradeCircularProgress extends StatefulWidget { class _GradeCircularProgressState extends State with TickerProviderStateMixin { - AnimationController _controller; - Animation animation; + late AnimationController _controller; + late Animation animation; @override void initState() { @@ -92,15 +92,15 @@ class _GradeCircularProgressState extends State String getGrade(BuildContext context) { if (widget.finalGrade != null) { - return widget.finalGrade; + return widget.finalGrade!; } if (widget.studentGrade != null) { return AppIntl.of(context) - .grades_grade_in_percentage(widget.studentGrade.round()); + !.grades_grade_in_percentage(widget.studentGrade!.round()); } - return AppIntl.of(context).grades_not_available; + return AppIntl.of(context)!.grades_not_available; } Color gradePercentageColor(double gradePercentage) { @@ -134,6 +134,6 @@ class _GradeCircularProgressState extends State } } - return Color.lerp(startColor, endColor, colorProportion); + return Color.lerp(startColor, endColor, colorProportion)!; } } diff --git a/lib/ui/widgets/grade_evaluation_tile.dart b/lib/ui/widgets/grade_evaluation_tile.dart index 41b53206c..00a603a5d 100644 --- a/lib/ui/widgets/grade_evaluation_tile.dart +++ b/lib/ui/widgets/grade_evaluation_tile.dart @@ -25,7 +25,7 @@ class GradeEvaluationTile extends StatefulWidget { final bool isFirstEvaluation; const GradeEvaluationTile(this.evaluation, - {Key key, this.completed, this.isFirstEvaluation}) + {Key? key, this.completed = false, this.isFirstEvaluation = false}) : super(key: key); @override @@ -35,8 +35,8 @@ class GradeEvaluationTile extends StatefulWidget { class _GradeEvaluationTileState extends State with TickerProviderStateMixin { bool showEvaluationDetails = false; - AnimationController controller; - Animation rotateAnimation; + late AnimationController controller; + late Animation rotateAnimation; @override void initState() { @@ -160,7 +160,7 @@ class _GradeEvaluationTileState extends State padding: const EdgeInsets.only(top: 10.0, bottom: 20.0), child: Text( AppIntl.of(context) - .grades_weight(widget.evaluation.weight), + !.grades_weight(widget.evaluation.weight), style: TextStyle( fontSize: 14, color: Utils.getColorByBrightness( @@ -174,7 +174,7 @@ class _GradeEvaluationTileState extends State padding: const EdgeInsets.only(top: 25.0, right: 10.0), child: AnimatedBuilder( animation: rotateAnimation, - builder: (BuildContext context, Widget child) { + builder: (BuildContext context, Widget? child) { return Transform.rotate( angle: rotateAnimation.value, child: const Icon( @@ -206,39 +206,39 @@ class _GradeEvaluationTileState extends State child: Column( children: [ _buildSummary( - AppIntl.of(context).grades_grade, - AppIntl.of(context).grades_grade_with_percentage( + AppIntl.of(context)!.grades_grade, + AppIntl.of(context)!.grades_grade_with_percentage( evaluation.mark ?? 0.0, - evaluation.correctedEvaluationOutOf ?? 0.0, + evaluation.correctedEvaluationOutOf, Utils.getGradeInPercentage(evaluation.mark, evaluation.correctedEvaluationOutOfFormatted), ), ), _buildSummary( - AppIntl.of(context).grades_average, - AppIntl.of(context).grades_grade_with_percentage( + AppIntl.of(context)!.grades_average, + AppIntl.of(context)!.grades_grade_with_percentage( evaluation.passMark ?? 0.0, - evaluation.correctedEvaluationOutOf ?? 0.0, + evaluation.correctedEvaluationOutOf, Utils.getGradeInPercentage(evaluation.passMark, evaluation.correctedEvaluationOutOfFormatted), ), ), _buildSummary( - AppIntl.of(context).grades_median, - AppIntl.of(context).grades_grade_with_percentage( + AppIntl.of(context)!.grades_median, + AppIntl.of(context)!.grades_grade_with_percentage( evaluation.median ?? 0.0, - evaluation.correctedEvaluationOutOf ?? 0.0, + evaluation.correctedEvaluationOutOf, Utils.getGradeInPercentage(evaluation.median, evaluation.correctedEvaluationOutOfFormatted), ), ), _buildSummary( - AppIntl.of(context).grades_standard_deviation, + AppIntl.of(context)!.grades_standard_deviation, validateResult( context, evaluation.standardDeviation.toString())), - _buildSummary(AppIntl.of(context).grades_percentile_rank, + _buildSummary(AppIntl.of(context)!.grades_percentile_rank, validateResult(context, evaluation.percentileRank.toString())), - _buildSummary(AppIntl.of(context).grades_target_date, + _buildSummary(AppIntl.of(context)!.grades_target_date, getDate(evaluation.targetDate, context)), ], ), @@ -246,13 +246,13 @@ class _GradeEvaluationTileState extends State ); } - String getDate(DateTime targetDate, BuildContext context) { + String getDate(DateTime? targetDate, BuildContext context) { if (targetDate != null) { - return DateFormat('d MMMM yyyy', AppIntl.of(context).localeName) + return DateFormat('d MMMM yyyy', AppIntl.of(context)!.localeName) .format(targetDate); } - return AppIntl.of(context).grades_not_available; + return AppIntl.of(context)!.grades_not_available; } Padding _buildSummary(String title, String grade) { @@ -262,7 +262,7 @@ class _GradeEvaluationTileState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: const TextStyle(fontSize: 14)), - Text(grade ?? '', style: const TextStyle(fontSize: 14)), + Text(grade, style: const TextStyle(fontSize: 14)), ], ), ); @@ -270,12 +270,12 @@ class _GradeEvaluationTileState extends State double getGradeInDecimal(double grade, double maxGrade) => grade / maxGrade; - String validateResult(BuildContext context, String result) { - if (result != "null") { + String validateResult(BuildContext context, String? result) { + if (result != null) { return result; } - return AppIntl.of(context).grades_not_available; + return AppIntl.of(context)!.grades_not_available; } DescribedFeatureOverlay _buildDiscoveryFeatureDescriptionWidget( diff --git a/lib/ui/widgets/grade_not_available.dart b/lib/ui/widgets/grade_not_available.dart index 8b6e1e4ab..7b030fc99 100644 --- a/lib/ui/widgets/grade_not_available.dart +++ b/lib/ui/widgets/grade_not_available.dart @@ -8,12 +8,12 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:notredame/ui/utils/app_theme.dart'; class GradeNotAvailable extends StatelessWidget { - final VoidCallback onPressed; + final VoidCallback? onPressed; final bool isEvaluationPeriod; const GradeNotAvailable( - {Key key, this.onPressed, this.isEvaluationPeriod = false}) + {Key? key, this.onPressed, this.isEvaluationPeriod = false}) : super(key: key); @override @@ -31,8 +31,8 @@ class GradeNotAvailable extends StatelessWidget { Text( isEvaluationPeriod ? AppIntl.of(context) - .grades_error_course_evaluations_not_completed - : AppIntl.of(context).grades_msg_no_grade, + !.grades_error_course_evaluations_not_completed + : AppIntl.of(context)!.grades_msg_no_grade, textAlign: TextAlign.center, softWrap: true, style: isEvaluationPeriod @@ -45,7 +45,7 @@ class GradeNotAvailable extends StatelessWidget { backgroundColor: AppTheme.etsLightRed, foregroundColor: Colors.white), onPressed: onPressed, - child: Text(AppIntl.of(context).retry)) + child: Text(AppIntl.of(context)!.retry)) ], ); } diff --git a/lib/ui/widgets/haptics_container.dart b/lib/ui/widgets/haptics_container.dart index c6fbba0fd..1eb47f3ec 100644 --- a/lib/ui/widgets/haptics_container.dart +++ b/lib/ui/widgets/haptics_container.dart @@ -11,7 +11,7 @@ import 'package:flutter/services.dart'; class HapticsContainer extends StatefulWidget { final Widget child; - const HapticsContainer({Key key, this.child}) : super(key: key); + const HapticsContainer({Key? key, required this.child}) : super(key: key); @override _HapticsContainerState createState() => _HapticsContainerState(); diff --git a/lib/ui/widgets/password_text_field.dart b/lib/ui/widgets/password_text_field.dart index 1fd9fe079..b8b2be6e9 100644 --- a/lib/ui/widgets/password_text_field.dart +++ b/lib/ui/widgets/password_text_field.dart @@ -8,7 +8,7 @@ class PasswordFormField extends StatefulWidget { final FormFieldValidator validator; final VoidCallback onEditionComplete; - const PasswordFormField({Key key, this.validator, this.onEditionComplete}) + const PasswordFormField({Key? key, required this.validator, required this.onEditionComplete}) : super(key: key); @override @@ -38,7 +38,7 @@ class _PasswordFormFieldState extends State { errorBorder: OutlineInputBorder( borderSide: BorderSide( color: errorTextColor, width: borderRadiusOnFocus)), - labelText: AppIntl.of(context).login_prompt_password, + labelText: AppIntl.of(context)!.login_prompt_password, labelStyle: const TextStyle(color: Colors.white54), errorStyle: TextStyle(color: errorTextColor), suffixIcon: IconButton( diff --git a/lib/ui/widgets/schedule_calendar_tile.dart b/lib/ui/widgets/schedule_calendar_tile.dart index 59ef8c6b0..387352f14 100644 --- a/lib/ui/widgets/schedule_calendar_tile.dart +++ b/lib/ui/widgets/schedule_calendar_tile.dart @@ -6,19 +6,19 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class ScheduleCalendarTile extends StatefulWidget { - final String title; - final String description; - final TextStyle titleStyle; - final int totalEvents; - final EdgeInsets padding; - final Color backgroundColor; - final BorderRadius borderRadius; - final DateTime start; - final DateTime end; + final String? title; + final String? description; + final TextStyle? titleStyle; + final int? totalEvents; + final EdgeInsets? padding; + final Color? backgroundColor; + final BorderRadius? borderRadius; + final DateTime? start; + final DateTime? end; final BuildContext buildContext; const ScheduleCalendarTile( - {Key key, + {Key? key, this.title, this.description, this.titleStyle, @@ -28,7 +28,7 @@ class ScheduleCalendarTile extends StatefulWidget { this.borderRadius, this.start, this.end, - this.buildContext}) + required this.buildContext}) : super(key: key); @override @@ -37,15 +37,15 @@ class ScheduleCalendarTile extends StatefulWidget { class _ScheduleCalendarTileState extends State { void _showTileInfo() { - final courseInfos = widget.description.split(";"); + final courseInfos = widget.description?.split(";") ?? []; final courseName = courseInfos[0].split("-")[0]; final courseLocation = courseInfos[1]; final courseType = courseInfos[2]; final teacherName = courseInfos[3]; final startTime = - "${widget.start.hour}:${widget.start.minute.toString().padLeft(2, '0')}"; + "${widget.start?.hour ?? '00'}:${widget.start?.minute.toString().padLeft(2, '0') ?? '00'}"; final endTime = - "${widget.end.hour}:${widget.end.add(const Duration(minutes: 1)).minute.toString().padLeft(2, '0')}"; + "${widget.end?.hour ?? '00'}:${widget.end?.add(const Duration(minutes: 1)).minute.toString().padLeft(2, '0') ?? '00'}"; showDialog( context: context, @@ -73,14 +73,14 @@ class _ScheduleCalendarTileState extends State { ), ), Text( - "${AppIntl.of(widget.buildContext).schedule_calendar_by} $teacherName", + "${AppIntl.of(widget.buildContext)!.schedule_calendar_by} $teacherName", style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w500, ), ), Text( - "${AppIntl.of(widget.buildContext).schedule_calendar_from_time} $startTime ${AppIntl.of(widget.buildContext).schedule_calendar_to_time} $endTime", + "${AppIntl.of(widget.buildContext)!.schedule_calendar_from_time} $startTime ${AppIntl.of(widget.buildContext)!.schedule_calendar_to_time} $endTime", style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w500, @@ -120,7 +120,7 @@ class _ScheduleCalendarTileState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ AutoSizeText( - widget.title, + widget.title ?? "", style: widget.titleStyle, maxLines: 3, ) diff --git a/lib/ui/widgets/schedule_settings.dart b/lib/ui/widgets/schedule_settings.dart index 9086edd89..c3c57a0ea 100644 --- a/lib/ui/widgets/schedule_settings.dart +++ b/lib/ui/widgets/schedule_settings.dart @@ -16,7 +16,7 @@ import 'package:notredame/ui/utils/app_theme.dart'; class ScheduleSettings extends StatefulWidget { final bool showHandle; - const ScheduleSettings({Key key, this.showHandle = true}) : super(key: key); + const ScheduleSettings({Key? key, this.showHandle = true}) : super(key: key); @override _ScheduleSettingsState createState() => _ScheduleSettingsState(); @@ -68,13 +68,13 @@ class _ScheduleSettingsState extends State { child: Center( child: Padding( padding: const EdgeInsets.fromLTRB(15, 20, 20, 20), - child: Text(AppIntl.of(context).schedule_settings_title, + child: Text(AppIntl.of(context)!.schedule_settings_title, style: Theme.of(context).textTheme.headline6)), ), ), Expanded( child: ListTileTheme( - selectedColor: Theme.of(context).textTheme.bodyText1.color, + selectedColor: Theme.of(context).textTheme.bodyText1!.color, child: ListView( key: const ValueKey("SettingsScrollingArea"), children: _buildSettings( @@ -119,7 +119,7 @@ class _ScheduleSettingsState extends State { padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15.0, bottom: 2.0), child: Text( - AppIntl.of(context).schedule_select_course_activity, + AppIntl.of(context)!.schedule_select_course_activity, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -134,7 +134,7 @@ class _ScheduleSettingsState extends State { tiles.add(Padding( padding: const EdgeInsets.fromLTRB(15.0, 8.0, 15.0, 8.0), child: Text( - '${model.scheduleActivitiesByCourse[courseActivitiesAcronym].first.courseAcronym} - ${model.scheduleActivitiesByCourse[courseActivitiesAcronym].first.courseTitle}', + '${model.scheduleActivitiesByCourse[courseActivitiesAcronym]?.first.courseAcronym ?? AppIntl.of(context)!.grades_not_available} - ${model.scheduleActivitiesByCourse[courseActivitiesAcronym]?.first.courseTitle ?? AppIntl.of(context)!.grades_not_available}}', style: const TextStyle( fontWeight: FontWeight.bold, ), @@ -146,20 +146,23 @@ class _ScheduleSettingsState extends State { selectedTileColor: selectedColor, onTap: () => model.selectScheduleActivity(courseActivitiesAcronym, null), - title: Text(AppIntl.of(context).course_activity_group_both), + title: Text(AppIntl.of(context)!.course_activity_group_both), )); - for (final course - in model.scheduleActivitiesByCourse[courseActivitiesAcronym]) { - tiles.add(ListTile( - selected: - model.selectedScheduleActivity[course.courseAcronym] == course, - selectedTileColor: selectedColor, - onTap: () => - model.selectScheduleActivity(course.courseAcronym, course), - title: Text(getActivityTitle(course.activityCode)), - )); + if(model.scheduleActivitiesByCourse[courseActivitiesAcronym] != null) { + for (final course + in model.scheduleActivitiesByCourse[courseActivitiesAcronym]!) { + tiles.add(ListTile( + selected: + model.selectedScheduleActivity[course.courseAcronym] == course, + selectedTileColor: selectedColor, + onTap: () => + model.selectScheduleActivity(course.courseAcronym, course), + title: Text(getActivityTitle(course.activityCode)), + )); + } } + if (model.scheduleActivitiesByCourse.values.length > 1) { tiles.add(const Divider(endIndent: 50, thickness: 1.5)); @@ -171,9 +174,9 @@ class _ScheduleSettingsState extends State { String getActivityTitle(String activityCode) { if (activityCode == ActivityCode.labGroupA) { - return AppIntl.of(context).course_activity_group_a; + return AppIntl.of(context)!.course_activity_group_a; } else if (activityCode == ActivityCode.labGroupB) { - return AppIntl.of(context).course_activity_group_b; + return AppIntl.of(context)!.course_activity_group_b; } return ""; @@ -189,7 +192,7 @@ class _ScheduleSettingsState extends State { activeColor: AppTheme.etsLightRed, ), title: Text( - AppIntl.of(context).schedule_settings_show_week_events_btn_pref), + AppIntl.of(context)!.schedule_settings_show_week_events_btn_pref), ), const Divider(thickness: 1) ]; @@ -201,7 +204,7 @@ class _ScheduleSettingsState extends State { padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15.0, bottom: 2.0), child: Text( - AppIntl.of(context).schedule_settings_show_weekend_day, + AppIntl.of(context)!.schedule_settings_show_weekend_day, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -215,7 +218,7 @@ class _ScheduleSettingsState extends State { selected: model.otherDayOfWeek == WeekDays.monday, selectedTileColor: selectedColor, onTap: () => setState(() => model.otherDayOfWeek = WeekDays.monday), - title: Text(AppIntl.of(context).schedule_settings_show_weekend_day_none), + title: Text(AppIntl.of(context)!.schedule_settings_show_weekend_day_none), )); for (final WeekDays day in model.otherDayPossible) { @@ -242,7 +245,7 @@ class _ScheduleSettingsState extends State { activeColor: AppTheme.etsLightRed, ), title: - Text(AppIntl.of(context).schedule_settings_show_today_btn_pref), + Text(AppIntl.of(context)!.schedule_settings_show_today_btn_pref), ), const Divider(thickness: 1) ]; @@ -256,7 +259,7 @@ class _ScheduleSettingsState extends State { onChanged: (value) => model.toggleCalendarView = value, activeColor: AppTheme.etsLightRed, ), - title: Text(AppIntl.of(context).schedule_settings_list_view), + title: Text(AppIntl.of(context)!.schedule_settings_list_view), ), const Divider(thickness: 1) ]; @@ -267,7 +270,7 @@ class _ScheduleSettingsState extends State { Padding( padding: const EdgeInsets.only(left: 15.0, right: 15.0, bottom: 2.0), child: Text( - AppIntl.of(context).schedule_settings_calendar_format_pref, + AppIntl.of(context)!.schedule_settings_calendar_format_pref, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -298,7 +301,7 @@ class _ScheduleSettingsState extends State { padding: const EdgeInsets.only( left: 15.0, right: 15.0, top: 15.0, bottom: 2.0), child: Text( - AppIntl.of(context).schedule_settings_starting_weekday_pref, + AppIntl.of(context)!.schedule_settings_starting_weekday_pref, style: TextStyle( color: Theme.of(context).colorScheme.secondary, fontWeight: FontWeight.bold, @@ -325,38 +328,39 @@ class _ScheduleSettingsState extends State { String getTextForFormat(BuildContext context, CalendarFormat format) { switch (format) { case CalendarFormat.month: - return AppIntl.of(context).schedule_settings_calendar_format_month; + return AppIntl.of(context)!.schedule_settings_calendar_format_month; case CalendarFormat.week: - return AppIntl.of(context).schedule_settings_calendar_format_week; + return AppIntl.of(context)!.schedule_settings_calendar_format_week; case CalendarFormat.twoWeeks: - return AppIntl.of(context).schedule_settings_calendar_format_2_weeks; + return AppIntl.of(context)!.schedule_settings_calendar_format_2_weeks; + default: + return AppIntl.of(context)!.schedule_settings_calendar_format_month; } - return AppIntl.of(context).schedule_settings_calendar_format_month; } String getTextForDay(BuildContext context, StartingDayOfWeek day) { - // ignore: missing_enum_constant_in_switch switch (day) { case StartingDayOfWeek.sunday: - return AppIntl.of(context).schedule_settings_starting_weekday_sunday; + return AppIntl.of(context)!.schedule_settings_starting_weekday_sunday; case StartingDayOfWeek.saturday: - return AppIntl.of(context).schedule_settings_starting_weekday_saturday; + return AppIntl.of(context)!.schedule_settings_starting_weekday_saturday; case StartingDayOfWeek.monday: - return AppIntl.of(context).schedule_settings_starting_weekday_monday; + return AppIntl.of(context)!.schedule_settings_starting_weekday_monday; + default: + return AppIntl.of(context)!.schedule_settings_starting_weekday_monday; } - return AppIntl.of(context).schedule_settings_starting_weekday_monday; } String getTextForWeekDay(BuildContext context, WeekDays day) { - // ignore: missing_enum_constant_in_switch switch (day) { case WeekDays.sunday: - return AppIntl.of(context).schedule_settings_starting_weekday_sunday; + return AppIntl.of(context)!.schedule_settings_starting_weekday_sunday; case WeekDays.saturday: - return AppIntl.of(context).schedule_settings_starting_weekday_saturday; + return AppIntl.of(context)!.schedule_settings_starting_weekday_saturday; case WeekDays.monday: - return AppIntl.of(context).schedule_settings_starting_weekday_monday; + return AppIntl.of(context)!.schedule_settings_starting_weekday_monday; + default: + return AppIntl.of(context)!.schedule_settings_starting_weekday_monday; } - return AppIntl.of(context).schedule_settings_starting_weekday_monday; } } diff --git a/lib/ui/widgets/student_program.dart b/lib/ui/widgets/student_program.dart index d9aefc2de..3e701fd6a 100644 --- a/lib/ui/widgets/student_program.dart +++ b/lib/ui/widgets/student_program.dart @@ -22,8 +22,8 @@ class StudentProgram extends StatefulWidget { class _StudentProgramState extends State with TickerProviderStateMixin { bool showProgramDetails = false; - AnimationController controller; - Animation rotateAnimation; + late AnimationController controller; + late Animation rotateAnimation; @override void initState() { @@ -51,14 +51,14 @@ class _StudentProgramState extends State final bool isLightMode = Theme.of(context).brightness == Brightness.light; final List dataTitles = [ - AppIntl.of(context).profile_code_program, - AppIntl.of(context).profile_average_program, - AppIntl.of(context).profile_number_accumulated_credits_program, - AppIntl.of(context).profile_number_registered_credits_program, - AppIntl.of(context).profile_number_completed_courses_program, - AppIntl.of(context).profile_number_failed_courses_program, - AppIntl.of(context).profile_number_equivalent_courses_program, - AppIntl.of(context).profile_status_program + AppIntl.of(context)!.profile_code_program, + AppIntl.of(context)!.profile_average_program, + AppIntl.of(context)!.profile_number_accumulated_credits_program, + AppIntl.of(context)!.profile_number_registered_credits_program, + AppIntl.of(context)!.profile_number_completed_courses_program, + AppIntl.of(context)!.profile_number_failed_courses_program, + AppIntl.of(context)!.profile_number_equivalent_courses_program, + AppIntl.of(context)!.profile_status_program ]; final List dataFetched = [ @@ -102,7 +102,7 @@ class _StudentProgramState extends State padding: const EdgeInsets.only(top: 5.0), child: AnimatedBuilder( animation: rotateAnimation, - builder: (BuildContext context, Widget child) { + builder: (BuildContext context, Widget? child) { return Transform.rotate( angle: rotateAnimation.value, child: const Icon( From 2f5473a9a54f5486664993696d832eefbab1b1b7 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sat, 23 Dec 2023 01:20:07 -0500 Subject: [PATCH 12/62] Migrate Views to null safety --- lib/core/viewmodels/login_viewmodel.dart | 8 +-- lib/ui/router.dart | 8 +-- lib/ui/views/about_view.dart | 18 ++--- lib/ui/views/choose_language_view.dart | 8 +-- lib/ui/views/contributors_view.dart | 10 +-- lib/ui/views/dashboard_view.dart | 59 +++++++++------- lib/ui/views/emergency_view.dart | 11 ++- lib/ui/views/faq_view.dart | 28 ++++---- lib/ui/views/feedback_view.dart | 56 +++++++-------- lib/ui/views/grade_details_view.dart | 90 ++++++++++++------------ lib/ui/views/grades_view.dart | 8 +-- lib/ui/views/login_view.dart | 18 ++--- lib/ui/views/more_view.dart | 42 +++++------ lib/ui/views/not_found_view.dart | 14 ++-- lib/ui/views/outage_view.dart | 14 ++-- lib/ui/views/profile_view.dart | 34 ++++----- lib/ui/views/quick_links_view.dart | 10 +-- lib/ui/views/schedule_view.dart | 26 +++---- lib/ui/views/security_view.dart | 20 +++--- lib/ui/views/settings_view.dart | 28 ++++---- lib/ui/views/student_view.dart | 6 +- lib/ui/widgets/dismissible_card.dart | 7 +- 22 files changed, 262 insertions(+), 261 deletions(-) diff --git a/lib/core/viewmodels/login_viewmodel.dart b/lib/core/viewmodels/login_viewmodel.dart index dacc6948b..9b0c7bb29 100644 --- a/lib/core/viewmodels/login_viewmodel.dart +++ b/lib/core/viewmodels/login_viewmodel.dart @@ -45,8 +45,8 @@ class LoginViewModel extends BaseViewModel { final PreferencesService _preferencesService = locator(); /// Validate the format of the universal code - String? validateUniversalCode(String value) { - if (value.isEmpty) { + String? validateUniversalCode(String? value) { + if (value == null || value.isEmpty) { _universalCode = ""; return _appIntl.login_error_field_required; } else if (!_universalCodeMatcher.hasMatch(value)) { @@ -58,8 +58,8 @@ class LoginViewModel extends BaseViewModel { } /// Validate there is a password typed - String? validatePassword(String value) { - if (value.isEmpty) { + String? validatePassword(String? value) { + if (value == null || value.isEmpty) { _password = ""; return _appIntl.login_error_field_required; } diff --git a/lib/ui/router.dart b/lib/ui/router.dart index 8c857bddc..1ea109b1b 100644 --- a/lib/ui/router.dart +++ b/lib/ui/router.dart @@ -45,9 +45,9 @@ Route generateRoute(RouteSettings routeSettings) { return MaterialPageRoute( settings: RouteSettings(name: routeSettings.name), builder: (_) => - FaqView(backgroundColor: routeSettings.arguments as Color)); + FaqView(backgroundColor: routeSettings.arguments! as Color)); case RouterPaths.dashboard: - final code = (routeSettings.arguments as UpdateCode) ?? UpdateCode.none; + final code = (routeSettings.arguments as UpdateCode?) ?? UpdateCode.none; return PageRouteBuilder( settings: RouteSettings( name: routeSettings.name, arguments: routeSettings.arguments), @@ -78,7 +78,7 @@ Route generateRoute(RouteSettings routeSettings) { }, settings: RouteSettings(name: routeSettings.name), pageBuilder: (_, __, ___) => - GradesDetailsView(course: routeSettings.arguments as Course)); + GradesDetailsView(course: routeSettings.arguments! as Course)); case RouterPaths.ets: return PageRouteBuilder( settings: RouteSettings(name: routeSettings.name), @@ -86,7 +86,7 @@ Route generateRoute(RouteSettings routeSettings) { case RouterPaths.webView: return PageRouteBuilder( pageBuilder: (_, __, ___) => - LinkWebView(routeSettings.arguments as QuickLink)); + LinkWebView(routeSettings.arguments! as QuickLink)); case RouterPaths.security: return PageRouteBuilder( settings: RouteSettings(name: routeSettings.name), diff --git a/lib/ui/views/about_view.dart b/lib/ui/views/about_view.dart index 9cb3769cb..1699400a6 100644 --- a/lib/ui/views/about_view.dart +++ b/lib/ui/views/about_view.dart @@ -16,7 +16,7 @@ class AboutView extends StatefulWidget { } class _AboutViewState extends State with TickerProviderStateMixin { - AnimationController _controller; + late AnimationController _controller; bool _completed = false; bool _easterEggTrigger = false; @@ -54,7 +54,7 @@ class _AboutViewState extends State with TickerProviderStateMixin { appBar: AppBar( foregroundColor: Colors.white, title: Text( - AppIntl.of(context).more_about_applets_title, + AppIntl.of(context)!.more_about_applets_title, ), elevation: 0, backgroundColor: Colors.transparent, @@ -112,7 +112,7 @@ class _AboutViewState extends State with TickerProviderStateMixin { Padding( padding: const EdgeInsets.all(16.0), child: Text( - AppIntl.of(context).more_applets_about_details, + AppIntl.of(context)!.more_applets_about_details, style: const TextStyle(color: Colors.white), ), ), @@ -127,42 +127,42 @@ class _AboutViewState extends State with TickerProviderStateMixin { color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubWebsite, AppIntl.of(context))), + Urls.clubWebsite, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.github, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubGithub, AppIntl.of(context))), + Urls.clubGithub, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.facebook, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubFacebook, AppIntl.of(context))), + Urls.clubFacebook, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.twitter, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubTwitter, AppIntl.of(context))), + Urls.clubTwitter, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.youtube, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubYoutube, AppIntl.of(context))), + Urls.clubYoutube, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.discord, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubDiscord, AppIntl.of(context))), + Urls.clubDiscord, AppIntl.of(context)!)), ], ), ), diff --git a/lib/ui/views/choose_language_view.dart b/lib/ui/views/choose_language_view.dart index 98d77759e..40aa840fc 100644 --- a/lib/ui/views/choose_language_view.dart +++ b/lib/ui/views/choose_language_view.dart @@ -25,7 +25,7 @@ class _ChooseLanguageViewState extends State { itemBuilder: (BuildContext context, int index) { return Card( color: Utils.getColorByBrightness( - context, Colors.white, Colors.grey[900]), + context, Colors.white, Colors.grey[900]!), child: Column(mainAxisSize: MainAxisSize.min, children: [ ListTile( title: Text(model.languages[index]), @@ -44,7 +44,7 @@ class _ChooseLanguageViewState extends State { Widget build(BuildContext context) { return ViewModelBuilder.reactive( viewModelBuilder: () => - ChooseLanguageViewModel(intl: AppIntl.of(context)), + ChooseLanguageViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) => Scaffold( backgroundColor: Utils.getColorByBrightness( context, AppTheme.etsLightRed, AppTheme.primaryDark), @@ -63,7 +63,7 @@ class _ChooseLanguageViewState extends State { child: Align( alignment: Alignment.centerLeft, child: Text( - AppIntl.of(context).choose_language_title, + AppIntl.of(context)!.choose_language_title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, @@ -77,7 +77,7 @@ class _ChooseLanguageViewState extends State { child: Align( alignment: Alignment.centerLeft, child: Text( - AppIntl.of(context).choose_language_subtitle, + AppIntl.of(context)!.choose_language_subtitle, style: const TextStyle( fontSize: 16, color: Colors.white), ), diff --git a/lib/ui/views/contributors_view.dart b/lib/ui/views/contributors_view.dart index a54d6ce45..e93d26d38 100644 --- a/lib/ui/views/contributors_view.dart +++ b/lib/ui/views/contributors_view.dart @@ -20,7 +20,7 @@ class ContributorsView extends StatelessWidget { builder: (context, model, child) { return BaseScaffold( appBar: AppBar( - title: Text(AppIntl.of(context).more_contributors), + title: Text(AppIntl.of(context)!.more_contributors), ), showBottomBar: false, body: FutureBuilder>( @@ -30,14 +30,14 @@ class ContributorsView extends StatelessWidget { return buildLoading(); } return ListView.builder( - itemCount: snapshot.data.length, + itemCount: snapshot.data!.length, itemBuilder: (context, index) => ListTile( - title: Text(snapshot.data[index].login), + title: Text(snapshot.data![index].login ?? ''), leading: CircleAvatar( backgroundImage: - NetworkImage(snapshot.data[index].avatarUrl)), + NetworkImage(snapshot.data![index].avatarUrl ?? '')), onTap: () => Utils.launchURL( - snapshot.data[index].htmlUrl, AppIntl.of(context)), + snapshot.data![index].htmlUrl ?? '', AppIntl.of(context)!), ), ); }, diff --git a/lib/ui/views/dashboard_view.dart b/lib/ui/views/dashboard_view.dart index 75a616224..6ff34fbc7 100644 --- a/lib/ui/views/dashboard_view.dart +++ b/lib/ui/views/dashboard_view.dart @@ -33,7 +33,7 @@ import 'package:notredame/ui/widgets/haptics_container.dart'; class DashboardView extends StatefulWidget { final UpdateCode updateCode; - const DashboardView({Key key, this.updateCode}) : super(key: key); + const DashboardView({Key? key, required this.updateCode}) : super(key: key); @override _DashboardViewState createState() => _DashboardViewState(); @@ -41,7 +41,7 @@ class DashboardView extends StatefulWidget { class _DashboardViewState extends State with TickerProviderStateMixin { - Text progressBarText; + Text? progressBarText; final NavigationService _navigationService = locator(); final AnalyticsService _analyticsService = locator(); static const String tag = "DashboardView"; @@ -59,12 +59,12 @@ class _DashboardViewState extends State @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - viewModelBuilder: () => DashboardViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => DashboardViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) { return BaseScaffold( isInteractionLimitedWhileLoading: false, appBar: AppBar( - title: Text(AppIntl.of(context).title_dashboard), + title: Text(AppIntl.of(context)!.title_dashboard), centerTitle: false, automaticallyImplyLeading: false, actions: [ @@ -98,7 +98,7 @@ class _DashboardViewState extends State // always try to build broadcast cart so the user doesn't miss out on // important info if they dismissed it previously - for (final PreferencesFlag element in model.cardsToDisplay) { + for (final PreferencesFlag element in model.cardsToDisplay ?? []) { switch (element) { case PreferencesFlag.broadcastCard: if (model.remoteConfigService.dashboardMessageActive) { @@ -139,7 +139,7 @@ class _DashboardViewState extends State alignment: Alignment.centerLeft, child: Container( padding: const EdgeInsets.fromLTRB(17, 15, 0, 0), - child: Text(AppIntl.of(context).card_applets_title, + child: Text(AppIntl.of(context)!.card_applets_title, style: Theme.of(context).primaryTextTheme.headline6), )), Column( @@ -147,7 +147,7 @@ class _DashboardViewState extends State children: [ Container( padding: const EdgeInsets.fromLTRB(17, 10, 15, 10), - child: Text(AppIntl.of(context).card_applets_text, + child: Text(AppIntl.of(context)!.card_applets_text, style: Theme.of(context).primaryTextTheme.bodyText2), ), Container( @@ -158,7 +158,7 @@ class _DashboardViewState extends State IconButton( onPressed: () { _analyticsService.logEvent(tag, "Facebook clicked"); - Utils.launchURL(Urls.clubFacebook, AppIntl.of(context)); + Utils.launchURL(Urls.clubFacebook, AppIntl.of(context)!); }, icon: const FaIcon( FontAwesomeIcons.facebook, @@ -169,7 +169,7 @@ class _DashboardViewState extends State onPressed: () { _analyticsService.logEvent(tag, "Instagram clicked"); Utils.launchURL( - Urls.clubInstagram, AppIntl.of(context)); + Urls.clubInstagram, AppIntl.of(context)!); }, icon: const FaIcon( FontAwesomeIcons.instagram, @@ -179,7 +179,7 @@ class _DashboardViewState extends State IconButton( onPressed: () { _analyticsService.logEvent(tag, "Github clicked"); - Utils.launchURL(Urls.clubGithub, AppIntl.of(context)); + Utils.launchURL(Urls.clubGithub, AppIntl.of(context)!); }, icon: const FaIcon( FontAwesomeIcons.github, @@ -189,7 +189,7 @@ class _DashboardViewState extends State IconButton( onPressed: () { _analyticsService.logEvent(tag, "Email clicked"); - Utils.launchURL(Urls.clubEmail, AppIntl.of(context)); + Utils.launchURL(Urls.clubEmail, AppIntl.of(context)!); }, icon: const FaIcon( FontAwesomeIcons.envelope, @@ -199,7 +199,7 @@ class _DashboardViewState extends State IconButton( onPressed: () { _analyticsService.logEvent(tag, "Discord clicked"); - Utils.launchURL(Urls.clubDiscord, AppIntl.of(context)); + Utils.launchURL(Urls.clubDiscord, AppIntl.of(context)!); }, icon: const FaIcon( FontAwesomeIcons.discord, @@ -227,7 +227,7 @@ class _DashboardViewState extends State alignment: Alignment.centerLeft, child: Container( padding: const EdgeInsets.fromLTRB(17, 15, 0, 0), - child: Text(AppIntl.of(context).progress_bar_title, + child: Text(AppIntl.of(context)!.progress_bar_title, style: Theme.of(context).textTheme.headline6), )), if (model.progress >= 0.0) @@ -263,7 +263,7 @@ class _DashboardViewState extends State child: Center( child: progressBarText ?? Text( - AppIntl.of(context).progress_bar_message( + AppIntl.of(context)!.progress_bar_message( model.sessionDays[0], model.sessionDays[1]), style: const TextStyle(color: Colors.white), ), @@ -275,7 +275,7 @@ class _DashboardViewState extends State Container( padding: const EdgeInsets.all(16), child: Center( - child: Text(AppIntl.of(context).session_without), + child: Text(AppIntl.of(context)!.session_without), ), ), ]), @@ -290,18 +290,18 @@ class _DashboardViewState extends State ProgressBarText.daysElapsedWithTotalDays) { progressBarText = Text( AppIntl.of(context) - .progress_bar_message(model.sessionDays[0], model.sessionDays[1]), + !.progress_bar_message(model.sessionDays[0], model.sessionDays[1]), style: const TextStyle(color: Colors.white), ); } else if (model.currentProgressBarText == ProgressBarText.percentage) { progressBarText = Text( - AppIntl.of(context).progress_bar_message_percentage( + AppIntl.of(context)!.progress_bar_message_percentage( ((model.sessionDays[0] / model.sessionDays[1]) * 100).round()), style: const TextStyle(color: Colors.white), ); } else { progressBarText = Text( - AppIntl.of(context).progress_bar_message_remaining_days( + AppIntl.of(context)!.progress_bar_message_remaining_days( model.sessionDays[1] - model.sessionDays[0]), style: const TextStyle(color: Colors.white), ); @@ -309,9 +309,9 @@ class _DashboardViewState extends State } Widget _buildScheduleCard(DashboardViewModel model, PreferencesFlag flag) { - var title = AppIntl.of(context).title_schedule; + var title = AppIntl.of(context)!.title_schedule; if (model.todayDateEvents.isEmpty && model.tomorrowDateEvents.isNotEmpty) { - title = title + AppIntl.of(context).card_schedule_tomorrow; + title = title + AppIntl.of(context)!.card_schedule_tomorrow; } return DismissibleCard( isBusy: model.busy(model.todayDateEvents) || @@ -339,7 +339,7 @@ class _DashboardViewState extends State SizedBox( height: 100, child: Center( - child: Text(AppIntl.of(context).schedule_no_event))) + child: Text(AppIntl.of(context)!.schedule_no_event))) else _buildEventList(model.tomorrowDateEvents) else @@ -381,7 +381,7 @@ class _DashboardViewState extends State child: GestureDetector( onTap: () => _navigationService .pushNamedAndRemoveUntil(RouterPaths.student), - child: Text(AppIntl.of(context).grades_title, + child: Text(AppIntl.of(context)!.grades_title, style: Theme.of(context).textTheme.headline6), ), ), @@ -391,7 +391,7 @@ class _DashboardViewState extends State height: 100, child: Center( child: Text(AppIntl.of(context) - .grades_msg_no_grades + !.grades_msg_no_grades .split("\n") .first)), ) @@ -401,7 +401,7 @@ class _DashboardViewState extends State child: Wrap( children: model.courses .map((course) => - GradeButton(course, showDiscovery: false)) + GradeButton(course)) .toList(), ), ) @@ -442,7 +442,7 @@ class _DashboardViewState extends State ], ), // main text - AutoSizeText(model.broadcastMessage ?? "", + AutoSizeText(model.broadcastMessage, style: Theme.of(context).primaryTextTheme.bodyText2) ]), )); @@ -491,8 +491,13 @@ class _DashboardViewState extends State newIndex -= 1; } - final PreferencesFlag elementMoved = model.cards.keys - .firstWhere((element) => model.cards[element] == oldIndex); + // Should not happen becase dismiss card will not be called if the card is null. + if(model.cards == null) { + throw Exception("Cards is null"); + } + + final PreferencesFlag elementMoved = model.cards!.keys + .firstWhere((element) => model.cards![element] == oldIndex); model.setOrder(elementMoved, newIndex); } diff --git a/lib/ui/views/emergency_view.dart b/lib/ui/views/emergency_view.dart index bfa797267..005840382 100644 --- a/lib/ui/views/emergency_view.dart +++ b/lib/ui/views/emergency_view.dart @@ -25,7 +25,7 @@ class _EmergencyViewState extends State { @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => EmergencyViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => EmergencyViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) => Scaffold( appBar: AppBar(title: Text(widget.title)), floatingActionButtonLocation: @@ -33,15 +33,15 @@ class _EmergencyViewState extends State { floatingActionButton: FloatingActionButton.extended( onPressed: () { Utils.launchURL( - 'tel:${AppIntl.of(context).security_emergency_number}', - AppIntl.of(context)) + 'tel:${AppIntl.of(context)!.security_emergency_number}', + AppIntl.of(context)!) .catchError((error) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(error.toString()))); }); }, label: Text( - AppIntl.of(context).security_reach_security, + AppIntl.of(context)!.security_reach_security, style: const TextStyle(color: Colors.white, fontSize: 20), ), icon: const Icon(Icons.phone, size: 30, color: Colors.white), @@ -49,9 +49,8 @@ class _EmergencyViewState extends State { ), body: WebView( onWebViewCreated: (WebViewController webViewController) async { - model.webViewController = webViewController; await model.loadHtmlFromAssets( - widget.description, Theme.of(context).brightness); + widget.description, Theme.of(context).brightness, webViewController); }, ), ), diff --git a/lib/ui/views/faq_view.dart b/lib/ui/views/faq_view.dart index 632974d4e..988971b9c 100644 --- a/lib/ui/views/faq_view.dart +++ b/lib/ui/views/faq_view.dart @@ -14,7 +14,7 @@ import 'package:notredame/core/viewmodels/faq_viewmodel.dart'; class FaqView extends StatefulWidget { final Color backgroundColor; - const FaqView({this.backgroundColor}); + const FaqView({required this.backgroundColor}); @override State createState() => _FaqViewState(); @@ -33,7 +33,7 @@ class _FaqViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ getTitle(), - getSubtitle(AppIntl.of(context).questions_and_answers), + getSubtitle(AppIntl.of(context)!.questions_and_answers), Padding( padding: const EdgeInsets.only(left: 15.0, right: 15.0), child: CarouselSlider( @@ -58,8 +58,8 @@ class _FaqViewState extends State { const BorderRadius.all(Radius.circular(8.0)), ), child: getQuestionCard( - question.title[model.locale.languageCode], - question.description[model.locale.languageCode], + question.title[model.locale?.languageCode] ?? '', + question.description[model.locale?.languageCode] ?? '', ), ); }, @@ -67,7 +67,7 @@ class _FaqViewState extends State { }).toList(), ), ), - getSubtitle(AppIntl.of(context).actions), + getSubtitle(AppIntl.of(context)!.actions), Expanded( child: ListView.builder( padding: const EdgeInsets.only(top: 1.0), @@ -76,8 +76,8 @@ class _FaqViewState extends State { final action = faq.actions[index]; return getActionCard( - action.title[model.locale.languageCode], - action.description[model.locale.languageCode], + action.title[model.locale?.languageCode] ?? '', + action.description[model.locale?.languageCode] ?? '', action.type, action.link, action.iconName, @@ -119,9 +119,9 @@ class _FaqViewState extends State { const SizedBox(width: 8.0), Expanded( child: Text( - AppIntl.of(context).need_help, + AppIntl.of(context)!.need_help, textAlign: TextAlign.center, - style: Theme.of(context).textTheme.headline5.copyWith( + style: Theme.of(context).textTheme.headline5!.copyWith( color: widget.backgroundColor == Colors.white ? Colors.black : Colors.white, @@ -138,7 +138,7 @@ class _FaqViewState extends State { padding: const EdgeInsets.only(left: 18.0, top: 18.0, bottom: 10.0), child: Text( subtitle, - style: Theme.of(context).textTheme.headline5.copyWith( + style: Theme.of(context).textTheme.headline5!.copyWith( color: widget.backgroundColor == Colors.white ? Colors.black : Colors.white, @@ -159,7 +159,7 @@ class _FaqViewState extends State { Text( title, textScaleFactor: 1.0, - style: Theme.of(context).textTheme.bodyText2.copyWith( + style: Theme.of(context).textTheme.bodyText2!.copyWith( fontSize: 20, color: Theme.of(context).brightness == Brightness.light ? Colors.black @@ -171,7 +171,7 @@ class _FaqViewState extends State { Text( description, textScaleFactor: 1.0, - style: Theme.of(context).textTheme.bodyText2.copyWith( + style: Theme.of(context).textTheme.bodyText2!.copyWith( fontSize: 16, color: Theme.of(context).brightness == Brightness.light ? Colors.black @@ -246,7 +246,7 @@ class _FaqViewState extends State { children: [ Text( title, - style: Theme.of(context).textTheme.bodyText2.copyWith( + style: Theme.of(context).textTheme.bodyText2!.copyWith( fontSize: 18, color: Theme.of(context).brightness == Brightness.light ? Colors.black @@ -257,7 +257,7 @@ class _FaqViewState extends State { const SizedBox(height: 10.0), Text( description, - style: Theme.of(context).textTheme.bodyText2.copyWith( + style: Theme.of(context).textTheme.bodyText2!.copyWith( fontSize: 16, color: Theme.of(context).brightness == Brightness.light ? Colors.black diff --git a/lib/ui/views/feedback_view.dart b/lib/ui/views/feedback_view.dart index 2ce12be95..a52ab9e16 100644 --- a/lib/ui/views/feedback_view.dart +++ b/lib/ui/views/feedback_view.dart @@ -22,13 +22,13 @@ class _FeedbackViewState extends State { @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => FeedbackViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => FeedbackViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) { final bool isLightMode = Theme.of(context).brightness == Brightness.light; return Scaffold( appBar: AppBar( - title: Text(AppIntl.of(context).more_report_bug), + title: Text(AppIntl.of(context)!.more_report_bug), ), body: ListView( children: [ @@ -52,8 +52,8 @@ class _FeedbackViewState extends State { )), child: getCardInfo( context, - AppIntl.of(context).more_report_bug_bug, - AppIntl.of(context).more_report_bug_bug_subtitle, + AppIntl.of(context)!.more_report_bug_bug, + AppIntl.of(context)!.more_report_bug_bug_subtitle, Icons.bug_report, const Color.fromRGBO(252, 196, 238, 1), const Color.fromRGBO(153, 78, 174, 1), @@ -80,8 +80,8 @@ class _FeedbackViewState extends State { )), child: getCardInfo( context, - AppIntl.of(context).more_report_bug_feature, - AppIntl.of(context).more_report_bug_feature_subtitle, + AppIntl.of(context)!.more_report_bug_feature, + AppIntl.of(context)!.more_report_bug_feature_subtitle, Icons.design_services, const Color.fromRGBO(63, 219, 251, 1), const Color.fromRGBO(14, 127, 188, 1), @@ -91,8 +91,8 @@ class _FeedbackViewState extends State { const SizedBox(height: 25), Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: Text(AppIntl.of(context).my_tickets, - style: Theme.of(context).textTheme.headline5.copyWith( + child: Text(AppIntl.of(context)!.my_tickets, + style: Theme.of(context).textTheme.headline5!.copyWith( color: isLightMode ? Colors.black87 : Colors.white))), const Divider( @@ -112,7 +112,7 @@ class _FeedbackViewState extends State { return GestureDetector( onTap: () => { Utils.launchURL(model.myIssues[index].htmlUrl, - AppIntl.of(context)) + AppIntl.of(context)!) }, child: Container( margin: const EdgeInsets.only( @@ -156,9 +156,9 @@ class _FeedbackViewState extends State { createListTag( model.myIssues[index].isOpen ? AppIntl.of(context) - .ticket_status_open + !.ticket_status_open : AppIntl.of(context) - .ticket_status_closed, + !.ticket_status_closed, color: model.myIssues[index].state == 'open' ? Colors.green @@ -186,12 +186,12 @@ class _FeedbackViewState extends State { ? buildLoading( isInteractionLimitedWhileLoading: false) : Text( - AppIntl.of(context).no_ticket, + AppIntl.of(context)!.no_ticket, overflow: TextOverflow.ellipsis, style: Theme.of(context) .textTheme .headline6 - .copyWith( + !.copyWith( color: isLightMode ? const Color.fromARGB( 168, 0, 0, 0) @@ -206,8 +206,8 @@ class _FeedbackViewState extends State { const SizedBox(height: 25), Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: Text(AppIntl.of(context).more_report_tips, - style: Theme.of(context).textTheme.headline5.copyWith( + child: Text(AppIntl.of(context)!.more_report_tips, + style: Theme.of(context).textTheme.headline5!.copyWith( color: isLightMode ? Colors.black87 : Colors.white))), const Divider( @@ -221,17 +221,17 @@ class _FeedbackViewState extends State { text: TextSpan( children: [ TextSpan( - text: AppIntl.of(context).more_report_bug_step1, + text: AppIntl.of(context)!.more_report_bug_step1, style: Theme.of(context) .textTheme .bodyText2 - .copyWith(fontSize: 18)), + !.copyWith(fontSize: 18)), TextSpan( - text: AppIntl.of(context).more_report_bug_step2, + text: AppIntl.of(context)!.more_report_bug_step2, style: Theme.of(context) .textTheme .bodyText2 - .copyWith( + !.copyWith( fontSize: 18, color: Theme.of(context).brightness == Brightness.light @@ -239,17 +239,17 @@ class _FeedbackViewState extends State { : const Color.fromRGBO( 63, 219, 251, 1))), TextSpan( - text: AppIntl.of(context).more_report_bug_step3, + text: AppIntl.of(context)!.more_report_bug_step3, style: Theme.of(context) .textTheme .bodyText2 - .copyWith(fontSize: 18)), + !.copyWith(fontSize: 18)), TextSpan( - text: AppIntl.of(context).more_report_bug_step4, + text: AppIntl.of(context)!.more_report_bug_step4, style: Theme.of(context) .textTheme .bodyText2 - .copyWith( + !.copyWith( fontSize: 18, color: Theme.of(context).brightness == Brightness.light @@ -257,11 +257,11 @@ class _FeedbackViewState extends State { : const Color.fromRGBO( 63, 219, 251, 1))), TextSpan( - text: AppIntl.of(context).more_report_bug_step5, + text: AppIntl.of(context)!.more_report_bug_step5, style: Theme.of(context) .textTheme .bodyText2 - .copyWith(fontSize: 18)), + !.copyWith(fontSize: 18)), ], ), ), @@ -303,7 +303,7 @@ class _FeedbackViewState extends State { style: Theme.of(context) .textTheme .bodyText2 - .copyWith(fontSize: 19), + !.copyWith(fontSize: 19), textAlign: TextAlign.left, ), Text( @@ -311,7 +311,7 @@ class _FeedbackViewState extends State { style: Theme.of(context) .textTheme .bodyText2 - .copyWith(fontSize: 16), + !.copyWith(fontSize: 16), textAlign: TextAlign.left, ) ], @@ -322,7 +322,7 @@ class _FeedbackViewState extends State { ); } - Widget createListTag(String text, {Color textColor, Color color}) { + Widget createListTag(String text, {Color? textColor, Color? color}) { return Container( decoration: BoxDecoration( // border radius diff --git a/lib/ui/views/grade_details_view.dart b/lib/ui/views/grade_details_view.dart index 6eed4b880..bf0fad427 100644 --- a/lib/ui/views/grade_details_view.dart +++ b/lib/ui/views/grade_details_view.dart @@ -19,7 +19,7 @@ import 'package:notredame/ui/widgets/grade_not_available.dart'; class GradesDetailsView extends StatefulWidget { final Course course; - const GradesDetailsView({this.course}); + const GradesDetailsView({required this.course}); @override _GradesDetailsViewState createState() => _GradesDetailsViewState(); @@ -27,7 +27,7 @@ class GradesDetailsView extends StatefulWidget { class _GradesDetailsViewState extends State with TickerProviderStateMixin { - AnimationController _controller; + late AnimationController _controller; bool _completed = false; @override @@ -53,7 +53,7 @@ class _GradesDetailsViewState extends State Widget build(BuildContext context) => ViewModelBuilder.reactive( viewModelBuilder: () => GradesDetailsViewModel( - course: widget.course, intl: AppIntl.of(context)), + course: widget.course, intl: AppIntl.of(context)!), builder: (context, model, child) => BaseScaffold( showBottomBar: false, body: Material( @@ -77,10 +77,10 @@ class _GradesDetailsViewState extends State tag: 'course_acronym_${model.course.acronym}_${model.course.session}', child: Text( - model.course.acronym ?? "", + model.course.acronym, softWrap: false, overflow: TextOverflow.visible, - style: Theme.of(context).textTheme.bodyText1.copyWith( + style: Theme.of(context).textTheme.bodyText1!.copyWith( color: Colors.white, fontSize: 25, fontWeight: FontWeight.bold), @@ -103,14 +103,14 @@ class _GradesDetailsViewState extends State child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildClassInfo(model.course.title ?? ""), + _buildClassInfo(model.course.title), if (model.course.teacherName != null) _buildClassInfo(AppIntl.of(context) - .grades_teacher(model.course.teacherName)), + !.grades_teacher(model.course.teacherName!)), _buildClassInfo(AppIntl.of(context) - .grades_group_number(model.course.group ?? "")), - _buildClassInfo(AppIntl.of(context).credits_number( - model.course.numberOfCredits ?? "")), + !.grades_group_number(model.course.group)), + _buildClassInfo(AppIntl.of(context)!.credits_number( + model.course.numberOfCredits)), ], ), ), @@ -129,7 +129,7 @@ class _GradesDetailsViewState extends State Widget _buildGradeEvaluations(GradesDetailsViewModel model) { if (model.isBusy) { return const Center(child: CircularProgressIndicator()); - } else if (model.course.inReviewPeriod && !model.course.reviewCompleted) { + } else if (model.course.inReviewPeriod && !(model.course.reviewCompleted ?? false)) { return Center( child: GradeNotAvailable( key: const Key("EvaluationNotCompleted"), @@ -158,12 +158,12 @@ class _GradesDetailsViewState extends State key: const Key("GradeCircularProgress_summary"), finalGrade: model.course.grade, studentGrade: Utils.getGradeInPercentage( - model.course.summary.currentMark, - model.course.summary.markOutOf, + model.course.summary?.currentMark, + model.course.summary?.markOutOf, ), averageGrade: Utils.getGradeInPercentage( - model.course.summary.passMark, - model.course.summary.markOutOf, + model.course.summary?.passMark, + model.course.summary?.markOutOf, ), ), ), @@ -173,18 +173,18 @@ class _GradesDetailsViewState extends State crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildGradesSummary( - model.course.summary.currentMark, - model.course.summary.markOutOf, - AppIntl.of(context).grades_current_rating, + model.course.summary?.currentMark, + model.course.summary?.markOutOf, + AppIntl.of(context)!.grades_current_rating, Colors.green, context, ), Padding( padding: const EdgeInsets.only(top: 15.0), child: _buildGradesSummary( - model.course.summary.passMark ?? 0.0, - model.course.summary.markOutOf, - AppIntl.of(context).grades_average, + model.course.summary?.passMark, + model.course.summary?.markOutOf, + AppIntl.of(context)!.grades_average, Colors.red, context, ), @@ -202,48 +202,48 @@ class _GradesDetailsViewState extends State Expanded( flex: 3, child: _buildCourseGradeSummary( - AppIntl.of(context).grades_median, + AppIntl.of(context)!.grades_median, validateGrade( context, - model.course.summary.median.toString(), - AppIntl.of(context).grades_grade_in_percentage( + model.course.summary?.median.toString(), + AppIntl.of(context)!.grades_grade_in_percentage( Utils.getGradeInPercentage( - model.course.summary.median, - model.course.summary.markOutOf)), + model.course.summary?.median, + model.course.summary?.markOutOf)), ), ), ), Expanded( flex: 3, child: _buildCourseGradeSummary( - AppIntl.of(context).grades_standard_deviation, + AppIntl.of(context)!.grades_standard_deviation, validateGrade( context, - model.course.summary.standardDeviation.toString(), - model.course.summary.standardDeviation.toString(), + model.course.summary?.standardDeviation.toString(), + model.course.summary?.standardDeviation.toString(), ), ), ), Expanded( flex: 3, child: _buildCourseGradeSummary( - AppIntl.of(context).grades_percentile_rank, + AppIntl.of(context)!.grades_percentile_rank, validateGrade( context, - model.course.summary.percentileRank.toString(), - model.course.summary.percentileRank.toString(), + model.course.summary?.percentileRank.toString(), + model.course.summary?.percentileRank.toString(), ), ), ), ]), Column(children: [ - for (var evaluation in model.course.summary.evaluations) + for (CourseEvaluation evaluation in model.course.summary?.evaluations ?? []) GradeEvaluationTile( evaluation, completed: _completed, key: Key("GradeEvaluationTile_${evaluation.title}"), isFirstEvaluation: - evaluation == model.course.summary.evaluations.first, + evaluation == model.course.summary?.evaluations.first, ), ]), ], @@ -268,14 +268,14 @@ class _GradesDetailsViewState extends State style: Theme.of(context) .textTheme .bodyText1 - .copyWith(color: Colors.white, fontSize: 16), + !.copyWith(color: Colors.white, fontSize: 16), overflow: TextOverflow.ellipsis, ), ), ); /// Build the student grade or the average grade with their title - Column _buildGradesSummary(double currentGrade, double maxGrade, + Column _buildGradesSummary(double? currentGrade, double? maxGrade, String recipient, Color color, BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -283,34 +283,34 @@ class _GradesDetailsViewState extends State FittedBox( fit: BoxFit.fitWidth, child: Text( - AppIntl.of(context).grades_grade_with_percentage( - currentGrade, - maxGrade, + AppIntl.of(context)!.grades_grade_with_percentage( + currentGrade ?? 0.0, + maxGrade ?? 0.0, Utils.getGradeInPercentage( currentGrade, maxGrade, ), ), style: - Theme.of(context).textTheme.headline6.copyWith(color: color)), + Theme.of(context).textTheme.headline6!.copyWith(color: color)), ), Text(recipient, style: - Theme.of(context).textTheme.bodyText1.copyWith(color: color)), + Theme.of(context).textTheme.bodyText1!.copyWith(color: color)), ], ); } - String validateGrade(BuildContext context, String grade, String text) { - if (grade == "null" || grade == null) { - return AppIntl.of(context).grades_not_available; + String validateGrade(BuildContext context, String? grade, String? text) { + if (grade == "null" || grade == null || text == "null" || text == null) { + return AppIntl.of(context)!.grades_not_available; } return text; } /// Build the card of the Medidian, Standart deviation or Percentile Rank - SizedBox _buildCourseGradeSummary(String title, String number) { + SizedBox _buildCourseGradeSummary(String? title, String number) { return SizedBox( height: 110, width: MediaQuery.of(context).size.width / 3.1, diff --git a/lib/ui/views/grades_view.dart b/lib/ui/views/grades_view.dart index e1d6730d6..983c59408 100644 --- a/lib/ui/views/grades_view.dart +++ b/lib/ui/views/grades_view.dart @@ -38,7 +38,7 @@ class _GradesViewState extends State { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - viewModelBuilder: () => GradesViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => GradesViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) { return RefreshIndicator( onRefresh: () => model.refresh(), @@ -49,7 +49,7 @@ class _GradesViewState extends State { ListView(), if (model.coursesBySession.isEmpty) Center( - child: Text(AppIntl.of(context).grades_msg_no_grades, + child: Text(AppIntl.of(context)!.grades_msg_no_grades, textAlign: TextAlign.center, style: Theme.of(context).textTheme.headline6)) else @@ -69,9 +69,9 @@ class _GradesViewState extends State { child: _buildSessionCourses( index, _sessionName(model.sessionOrder[index], - AppIntl.of(context)), + AppIntl.of(context)!), model.coursesBySession[ - model.sessionOrder[index]], + model.sessionOrder[index]]!, model), ), ), diff --git a/lib/ui/views/login_view.dart b/lib/ui/views/login_view.dart index c9ca7424b..9bf6c5075 100644 --- a/lib/ui/views/login_view.dart +++ b/lib/ui/views/login_view.dart @@ -42,7 +42,7 @@ class _LoginViewState extends State { @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => LoginViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => LoginViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) => Scaffold( backgroundColor: Utils.getColorByBrightness( context, AppTheme.etsLightRed, AppTheme.primaryDark), @@ -57,7 +57,7 @@ class _LoginViewState extends State { key: formKey, onChanged: () { setState(() { - formKey.currentState.validate(); + formKey.currentState?.validate(); }); }, child: AutofillGroup( @@ -104,7 +104,7 @@ class _LoginViewState extends State { color: errorTextColor, width: borderRadiusOnFocus)), labelText: AppIntl.of(context) - .login_prompt_universal_code, + !.login_prompt_universal_code, labelStyle: const TextStyle(color: Colors.white54), errorStyle: TextStyle(color: errorTextColor), @@ -112,7 +112,7 @@ class _LoginViewState extends State { key: tooltipkey, triggerMode: TooltipTriggerMode.manual, message: AppIntl.of(context) - .universal_code_example, + !.universal_code_example, preferBelow: true, child: IconButton( icon: const Icon(Icons.help, @@ -144,7 +144,7 @@ class _LoginViewState extends State { padding: const EdgeInsets.only(top: 4), child: InkWell( child: Text( - AppIntl.of(context).forgot_password, + AppIntl.of(context)!.forgot_password, style: const TextStyle( decoration: TextDecoration.underline, color: Colors.white), @@ -174,7 +174,7 @@ class _LoginViewState extends State { Fluttertoast.showToast( msg: error); } - formKey.currentState.reset(); + formKey.currentState?.reset(); }); }, style: ButtonStyle( @@ -187,7 +187,7 @@ class _LoginViewState extends State { vertical: 16)), ), child: Text( - AppIntl.of(context).login_action_sign_in, + AppIntl.of(context)!.login_action_sign_in, style: TextStyle( color: model.canSubmit ? submitTextColor @@ -201,7 +201,7 @@ class _LoginViewState extends State { padding: const EdgeInsets.only(top: 24), child: InkWell( child: Text( - AppIntl.of(context).need_help, + AppIntl.of(context)!.need_help, style: const TextStyle( decoration: TextDecoration.underline, color: Colors.white), @@ -228,7 +228,7 @@ class _LoginViewState extends State { spacing: -20, children: [ Text( - AppIntl.of(context).login_applets_logo, + AppIntl.of(context)!.login_applets_logo, style: const TextStyle(color: Colors.white), ), Image.asset( diff --git a/lib/ui/views/more_view.dart b/lib/ui/views/more_view.dart index 04b5e1d35..6fea01ad1 100644 --- a/lib/ui/views/more_view.dart +++ b/lib/ui/views/more_view.dart @@ -48,21 +48,21 @@ class _MoreViewState extends State { /// License text box List aboutBoxChildren(BuildContext context) { - final textStyle = Theme.of(context).textTheme.bodyText2; + final textStyle = Theme.of(context).textTheme.bodyText2!; return [ const SizedBox(height: 24), RichText( text: TextSpan( children: [ TextSpan( - style: textStyle, text: AppIntl.of(context).flutter_license), + style: textStyle, text: AppIntl.of(context)!.flutter_license), TextSpan( style: textStyle.copyWith(color: Colors.blue), - text: AppIntl.of(context).flutter_website, + text: AppIntl.of(context)!.flutter_website, recognizer: TapGestureRecognizer() ..onTap = () => Utils.launchURL( - AppIntl.of(context).flutter_website, - AppIntl.of(context))), + AppIntl.of(context)!.flutter_website, + AppIntl.of(context)!)), TextSpan(style: textStyle, text: '.'), ], ), @@ -73,17 +73,17 @@ class _MoreViewState extends State { @override Widget build(BuildContext context) { return ViewModelBuilder.reactive( - viewModelBuilder: () => MoreViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => MoreViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) { return BaseScaffold( appBar: AppBar( - title: Text(AppIntl.of(context).title_more), + title: Text(AppIntl.of(context)!.title_more), automaticallyImplyLeading: false, ), body: ListView( children: [ ListTile( - title: Text(AppIntl.of(context).more_about_applets_title), + title: Text(AppIntl.of(context)!.more_about_applets_title), leading: _buildDiscoveryFeatureDescriptionWidget( context, Hero( @@ -101,7 +101,7 @@ class _MoreViewState extends State { model.navigationService.pushNamed(RouterPaths.about); }), ListTile( - title: Text(AppIntl.of(context).more_report_bug), + title: Text(AppIntl.of(context)!.more_report_bug), leading: _buildDiscoveryFeatureDescriptionWidget( context, getProperIconAccordingToTheme(Icons.bug_report), @@ -112,14 +112,14 @@ class _MoreViewState extends State { model.navigationService.pushNamed(RouterPaths.feedback); }), ListTile( - title: Text(AppIntl.of(context).in_app_review_title), + title: Text(AppIntl.of(context)!.in_app_review_title), leading: const Icon(Icons.rate_review), onTap: () { _analyticsService.logEvent(tag, "Rate us clicked"); MoreViewModel.launchInAppReview(); }), ListTile( - title: Text(AppIntl.of(context).more_contributors), + title: Text(AppIntl.of(context)!.more_contributors), leading: _buildDiscoveryFeatureDescriptionWidget( context, getProperIconAccordingToTheme(Icons.people_outline), @@ -131,7 +131,7 @@ class _MoreViewState extends State { .pushNamed(RouterPaths.contributors); }), ListTile( - title: Text(AppIntl.of(context).more_open_source_licenses), + title: Text(AppIntl.of(context)!.more_open_source_licenses), leading: const Icon(Icons.code), onTap: () { _analyticsService.logEvent(tag, "Rate us clicked"); @@ -145,7 +145,7 @@ class _MoreViewState extends State { 'assets/images/favicon_applets.png')), ), applicationName: - AppIntl.of(context).more_open_source_licenses, + AppIntl.of(context)!.more_open_source_licenses, applicationVersion: model.appVersion, applicationLegalese: '\u{a9} ${DateTime.now().year} App|ETS', @@ -156,7 +156,7 @@ class _MoreViewState extends State { }), if (model.privacyPolicyToggle) ListTile( - title: Text(AppIntl.of(context).privacy_policy), + title: Text(AppIntl.of(context)!.privacy_policy), leading: const Icon(Icons.privacy_tip), onTap: () { _analyticsService.logEvent( @@ -164,7 +164,7 @@ class _MoreViewState extends State { MoreViewModel.launchPrivacyPolicy(); }), ListTile( - title: Text(AppIntl.of(context).need_help), + title: Text(AppIntl.of(context)!.need_help), leading: _buildDiscoveryFeatureDescriptionWidget( context, getProperIconAccordingToTheme(Icons.question_answer), @@ -177,7 +177,7 @@ class _MoreViewState extends State { context, Colors.white, AppTheme.primaryDark)); }), ListTile( - title: Text(AppIntl.of(context).settings_title), + title: Text(AppIntl.of(context)!.settings_title), leading: _buildDiscoveryFeatureDescriptionWidget( context, getProperIconAccordingToTheme(Icons.settings), @@ -188,17 +188,17 @@ class _MoreViewState extends State { model.navigationService.pushNamed(RouterPaths.settings); }), ListTile( - title: Text(AppIntl.of(context).more_log_out), + title: Text(AppIntl.of(context)!.more_log_out), leading: const Icon(Icons.logout), onTap: () => Navigator.of(context).push( PageRouteBuilder( pageBuilder: (context, _, __) => AlertDialog( title: Text( - AppIntl.of(context).more_log_out, + AppIntl.of(context)!.more_log_out, style: const TextStyle(color: Colors.red), ), content: Text(AppIntl.of(context) - .more_prompt_log_out_confirmation), + !.more_prompt_log_out_confirmation), actions: [ TextButton( onPressed: () async { @@ -206,10 +206,10 @@ class _MoreViewState extends State { tag, "Log out clicked"); model.logout(); }, - child: Text(AppIntl.of(context).yes)), + child: Text(AppIntl.of(context)!.yes)), TextButton( onPressed: () => Navigator.of(context).pop(), - child: Text(AppIntl.of(context).no)) + child: Text(AppIntl.of(context)!.no)) ], ), opaque: false, diff --git a/lib/ui/views/not_found_view.dart b/lib/ui/views/not_found_view.dart index 111f7ddd4..85230cf5e 100644 --- a/lib/ui/views/not_found_view.dart +++ b/lib/ui/views/not_found_view.dart @@ -11,7 +11,7 @@ import 'package:notredame/core/viewmodels/not_found_viewmodel.dart'; import 'package:notredame/ui/utils/app_theme.dart'; class NotFoundView extends StatefulWidget { - final String pageName; + final String? pageName; const NotFoundView({this.pageName}); @@ -20,13 +20,13 @@ class NotFoundView extends StatefulWidget { } class _NotFoundState extends State { - NotFoundViewModel viewModel; + late NotFoundViewModel viewModel; _NotFoundState(); @override void initState() { - viewModel = NotFoundViewModel(pageName: widget.pageName); + viewModel = NotFoundViewModel(pageName: widget.pageName ?? ''); viewModel .loadRiveAnimation() .then((_) => setState(() => viewModel.startRiveAnimation())); @@ -40,7 +40,7 @@ class _NotFoundState extends State { width: 100, height: 80, child: Rive( - artboard: viewModel.artboard, + artboard: viewModel.artboard!, fit: BoxFit.fitWidth, )) : Container(); @@ -68,7 +68,7 @@ class _NotFoundState extends State { bottom: 80, ), child: Text( - AppIntl.of(context).not_found_title, + AppIntl.of(context)!.not_found_title, style: const TextStyle( fontSize: 25, fontWeight: FontWeight.bold), ), @@ -79,7 +79,7 @@ class _NotFoundState extends State { ), child: Text( AppIntl.of(context) - .not_found_message(model.notFoundPageName), + !.not_found_message(model.notFoundPageName), textAlign: TextAlign.center, style: const TextStyle( fontSize: 15, @@ -94,7 +94,7 @@ class _NotFoundState extends State { onPressed: () { model.navigateToDashboard(); }, - child: Text(AppIntl.of(context).go_to_dashboard), + child: Text(AppIntl.of(context)!.go_to_dashboard), ), ), ], diff --git a/lib/ui/views/outage_view.dart b/lib/ui/views/outage_view.dart index cf21081a0..3e74df47b 100644 --- a/lib/ui/views/outage_view.dart +++ b/lib/ui/views/outage_view.dart @@ -46,7 +46,7 @@ class OutageView extends StatelessWidget { ), SizedBox(height: model.getTextPlacement(context)), Text( - AppIntl.of(context).service_outage, + AppIntl.of(context)!.service_outage, textAlign: TextAlign.center, style: const TextStyle(fontSize: 18, color: Colors.white), @@ -57,7 +57,7 @@ class OutageView extends StatelessWidget { model.tapRefreshButton(context); }, child: Text( - AppIntl.of(context).service_outage_refresh, + AppIntl.of(context)!.service_outage_refresh, style: const TextStyle(fontSize: 17), ), ), @@ -68,7 +68,7 @@ class OutageView extends StatelessWidget { SizedBox( height: model.getContactTextPlacement(context), child: Text( - AppIntl.of(context).service_outage_contact, + AppIntl.of(context)!.service_outage_contact, textAlign: TextAlign.center, style: const TextStyle(color: Colors.white), ), @@ -83,28 +83,28 @@ class OutageView extends StatelessWidget { color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubWebsite, AppIntl.of(context))), + Urls.clubWebsite, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.github, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubGithub, AppIntl.of(context))), + Urls.clubGithub, AppIntl.of(context)!)), IconButton( icon: const FaIcon( Icons.mail_outline, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubEmail, AppIntl.of(context))), + Urls.clubEmail, AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.discord, color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubDiscord, AppIntl.of(context))), + Urls.clubDiscord, AppIntl.of(context)!)), ], ), ], diff --git a/lib/ui/views/profile_view.dart b/lib/ui/views/profile_view.dart index 2d3f2088f..b58ce7c00 100644 --- a/lib/ui/views/profile_view.dart +++ b/lib/ui/views/profile_view.dart @@ -34,7 +34,7 @@ class _ProfileViewState extends State { @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => ProfileViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => ProfileViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) { return RefreshIndicator( onRefresh: () => model.refresh(), @@ -112,7 +112,7 @@ Widget buildPage(BuildContext context, ProfileViewModel model) => Column( Padding( padding: const EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0), child: Text( - AppIntl.of(context).profile_other_programs, + AppIntl.of(context)!.profile_other_programs, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, @@ -180,7 +180,7 @@ Card getMyInfosCard(ProfileViewModel model, BuildContext context) { ClipboardData(text: model.profileStudent.permanentCode)); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(AppIntl.of(context) - .profile_permanent_code_copied_to_clipboard), + !.profile_permanent_code_copied_to_clipboard), )); }, child: Column( @@ -189,7 +189,7 @@ Card getMyInfosCard(ProfileViewModel model, BuildContext context) { Padding( padding: const EdgeInsets.only(bottom: 3.0), child: Text( - AppIntl.of(context).profile_permanent_code, + AppIntl.of(context)!.profile_permanent_code, style: const TextStyle( fontSize: 16, ), @@ -209,7 +209,7 @@ Card getMyInfosCard(ProfileViewModel model, BuildContext context) { Clipboard.setData(ClipboardData(text: model.universalAccessCode)); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(AppIntl.of(context) - .profile_universal_code_copied_to_clipboard), + !.profile_universal_code_copied_to_clipboard), )); }, child: Column( @@ -218,7 +218,7 @@ Card getMyInfosCard(ProfileViewModel model, BuildContext context) { Padding( padding: const EdgeInsets.only(top: 16.0, bottom: 3.0), child: Text( - AppIntl.of(context).login_prompt_universal_code, + AppIntl.of(context)!.login_prompt_universal_code, style: const TextStyle(fontSize: 16), ), ), @@ -255,7 +255,7 @@ Card getMyBalanceCard(ProfileViewModel model, BuildContext context) { Padding( padding: const EdgeInsets.only(top: 16.0, left: 16.0, bottom: 3.0), child: Text( - AppIntl.of(context).profile_balance, + AppIntl.of(context)!.profile_balance, style: const TextStyle( fontSize: 16, ), @@ -284,7 +284,7 @@ Card getProgramCompletion(ProfileViewModel model, BuildContext context) { Padding( padding: const EdgeInsets.all(16.0), child: Text( - AppIntl.of(context).profile_program_completion, + AppIntl.of(context)!.profile_program_completion, style: const TextStyle( fontSize: 16, ), @@ -313,7 +313,7 @@ CircularPercentIndicator getLoadingIndicator( center: Text( percentage != 0 ? '$percentage%' - : AppIntl.of(context).profile_program_completion_not_available, + : AppIntl.of(context)!.profile_program_completion_not_available, style: const TextStyle(fontSize: 20), ), progressColor: Colors.green, @@ -325,14 +325,14 @@ Column getCurrentProgramTile(List programList, BuildContext context) { final program = programList.last; final List dataTitles = [ - AppIntl.of(context).profile_code_program, - AppIntl.of(context).profile_average_program, - AppIntl.of(context).profile_number_accumulated_credits_program, - AppIntl.of(context).profile_number_registered_credits_program, - AppIntl.of(context).profile_number_completed_courses_program, - AppIntl.of(context).profile_number_failed_courses_program, - AppIntl.of(context).profile_number_equivalent_courses_program, - AppIntl.of(context).profile_status_program + AppIntl.of(context)!.profile_code_program, + AppIntl.of(context)!.profile_average_program, + AppIntl.of(context)!.profile_number_accumulated_credits_program, + AppIntl.of(context)!.profile_number_registered_credits_program, + AppIntl.of(context)!.profile_number_completed_courses_program, + AppIntl.of(context)!.profile_number_failed_courses_program, + AppIntl.of(context)!.profile_number_equivalent_courses_program, + AppIntl.of(context)!.profile_status_program ]; final List dataFetched = [ diff --git a/lib/ui/views/quick_links_view.dart b/lib/ui/views/quick_links_view.dart index c85182c05..f75541930 100644 --- a/lib/ui/views/quick_links_view.dart +++ b/lib/ui/views/quick_links_view.dart @@ -24,8 +24,8 @@ class _QuickLinksViewState extends State bool _editMode = false; // Animation Controller for Shake Animation - AnimationController _controller; - Animation _animation; + late AnimationController _controller; + late Animation _animation; @override void initState() { @@ -42,7 +42,7 @@ class _QuickLinksViewState extends State @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => QuickLinksViewModel(AppIntl.of(context)), + viewModelBuilder: () => QuickLinksViewModel(AppIntl.of(context)!), builder: (context, model, child) => BaseScaffold( isLoading: model.isBusy, appBar: _buildAppBar(context, model), @@ -52,7 +52,7 @@ class _QuickLinksViewState extends State AppBar _buildAppBar(BuildContext context, QuickLinksViewModel model) { return AppBar( - title: Text(AppIntl.of(context).title_ets), + title: Text(AppIntl.of(context)!.title_ets), automaticallyImplyLeading: false, actions: const [], ); @@ -152,7 +152,7 @@ class _QuickLinksViewState extends State }, child: AnimatedBuilder( animation: _animation, - builder: (BuildContext context, Widget child) { + builder: (BuildContext context, Widget? child) { return Transform.rotate( angle: _editMode ? _animation.value : 0, child: child, diff --git a/lib/ui/views/schedule_view.dart b/lib/ui/views/schedule_view.dart index 5d4d740c6..c8c35b7c8 100644 --- a/lib/ui/views/schedule_view.dart +++ b/lib/ui/views/schedule_view.dart @@ -27,9 +27,9 @@ import 'package:notredame/ui/widgets/schedule_settings.dart'; class ScheduleView extends StatefulWidget { @visibleForTesting - final DateTime initialDay; + final DateTime? initialDay; - const ScheduleView({Key key, this.initialDay}) : super(key: key); + const ScheduleView({Key? key, this.initialDay}) : super(key: key); @override _ScheduleViewState createState() => _ScheduleViewState(); @@ -48,7 +48,7 @@ class _ScheduleViewState extends State static const Color _defaultColor = Color(0xff76859B); static final List weekTitles = ["L", "M", "M", "J", "V", "S", "D"]; - AnimationController _animationController; + late AnimationController _animationController; @override void initState() { @@ -75,7 +75,7 @@ class _ScheduleViewState extends State Widget build(BuildContext context) => ViewModelBuilder.reactive( viewModelBuilder: () => ScheduleViewModel( - intl: AppIntl.of(context), initialSelectedDate: widget.initialDay), + intl: AppIntl.of(context)!, initialSelectedDate: widget.initialDay), onModelReady: (model) { if (model.settings.isEmpty) { model.loadSettings(); @@ -85,7 +85,7 @@ class _ScheduleViewState extends State isLoading: model.busy(model.isLoadingEvents), isInteractionLimitedWhileLoading: false, appBar: AppBar( - title: Text(AppIntl.of(context).title_schedule), + title: Text(AppIntl.of(context)!.title_schedule), centerTitle: false, automaticallyImplyLeading: false, actions: _buildActionButtons(model), @@ -144,7 +144,7 @@ class _ScheduleViewState extends State Padding( padding: const EdgeInsets.symmetric(vertical: 64.0), child: - Center(child: Text(AppIntl.of(context).schedule_no_event)), + Center(child: Text(AppIntl.of(context)!.schedule_no_event)), ) else if (!model.showWeekEvents) _buildEventList(model.selectedDateEvents(model.selectedDate)), @@ -236,10 +236,10 @@ class _ScheduleViewState extends State return weekTitles[p0]; }, headerStringBuilder: (date, {secondaryDate}) { - final from = AppIntl.of(context).schedule_calendar_from; - final to = AppIntl.of(context).schedule_calendar_to; - final locale = AppIntl.of(context).localeName; - return '$from ${date.day} ${DateFormat.MMMM(locale).format(date)} $to ${secondaryDate.day} ${DateFormat.MMMM(locale).format(secondaryDate)}'; + final from = AppIntl.of(context)!.schedule_calendar_from; + final to = AppIntl.of(context)!.schedule_calendar_to; + final locale = AppIntl.of(context)!.localeName; + return '$from ${date.day} ${DateFormat.MMMM(locale).format(date)} $to ${secondaryDate?.day ?? '00'} ${DateFormat.MMMM(locale).format(secondaryDate ?? date)}'; }, eventTileBuilder: (date, events, boundary, startDuration, endDuration) => @@ -282,7 +282,7 @@ class _ScheduleViewState extends State return weekTitles[p0]; }, headerStringBuilder: (date, {secondaryDate}) { - final locale = AppIntl.of(context).localeName; + final locale = AppIntl.of(context)!.localeName; return '${DateFormat.MMMM(locale).format(date).characters.first.toUpperCase()}${DateFormat.MMMM(locale).format(date).substring(1)} ${date.year}'; }, startDay: calendar_view.WeekDays.sunday, @@ -361,7 +361,7 @@ class _ScheduleViewState extends State } /// Build the square with the number of [events] for the [date] - Widget _buildEventsMarker( + Widget? _buildEventsMarker( ScheduleViewModel model, DateTime date, List events) { if (events.isNotEmpty) { return Positioned( @@ -400,7 +400,7 @@ class _ScheduleViewState extends State startingDayOfWeek: model.settings[PreferencesFlag.scheduleStartWeekday] as StartingDayOfWeek, - locale: model.locale.toLanguageTag(), + locale: model.locale?.toLanguageTag(), selectedDayPredicate: (day) { return isSameDay(model.selectedDate, day); }, diff --git a/lib/ui/views/security_view.dart b/lib/ui/views/security_view.dart index 806fdd7e5..05241a681 100644 --- a/lib/ui/views/security_view.dart +++ b/lib/ui/views/security_view.dart @@ -26,10 +26,10 @@ class _SecurityViewState extends State { @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => SecurityViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => SecurityViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) => Scaffold( appBar: AppBar( - title: Text(AppIntl.of(context).ets_security_title), + title: Text(AppIntl.of(context)!.ets_security_title), ), body: SingleChildScrollView( child: Column( @@ -55,7 +55,7 @@ class _SecurityViewState extends State { Padding( padding: const EdgeInsets.all(8.0), child: Text( - AppIntl.of(context).security_reach_security, + AppIntl.of(context)!.security_reach_security, style: const TextStyle( color: AppTheme.etsLightRed, fontSize: 24), ), @@ -64,17 +64,17 @@ class _SecurityViewState extends State { child: InkWell( splashColor: Colors.red.withAlpha(50), onTap: () => Utils.launchURL( - 'tel:${AppIntl.of(context).security_emergency_number}', - AppIntl.of(context)) + 'tel:${AppIntl.of(context)!.security_emergency_number}', + AppIntl.of(context)!) .catchError((error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(error.toString()))); }), child: ListTile( leading: const Icon(Icons.phone, size: 30), - title: Text(AppIntl.of(context).security_emergency_call), + title: Text(AppIntl.of(context)!.security_emergency_call), subtitle: - Text(AppIntl.of(context).security_emergency_number), + Text(AppIntl.of(context)!.security_emergency_number), ), ), ), @@ -84,15 +84,15 @@ class _SecurityViewState extends State { child: ListTile( leading: const Icon(Icons.phone, size: 30), title: Text( - AppIntl.of(context).security_emergency_intern_call), + AppIntl.of(context)!.security_emergency_intern_call), subtitle: Text( - AppIntl.of(context).security_emergency_intern_number), + AppIntl.of(context)!.security_emergency_intern_number), ), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( - AppIntl.of(context).security_emergency_procedures, + AppIntl.of(context)!.security_emergency_procedures, style: const TextStyle( color: AppTheme.etsLightRed, fontSize: 24), ), diff --git a/lib/ui/views/settings_view.dart b/lib/ui/views/settings_view.dart index d19d1a31c..7dd0f6122 100644 --- a/lib/ui/views/settings_view.dart +++ b/lib/ui/views/settings_view.dart @@ -19,16 +19,16 @@ class _SettingsViewState extends State { @override Widget build(BuildContext context) => ViewModelBuilder.reactive( - viewModelBuilder: () => SettingsViewModel(intl: AppIntl.of(context)), + viewModelBuilder: () => SettingsViewModel(intl: AppIntl.of(context)!), builder: (context, model, child) => BaseScaffold( appBar: AppBar( - title: Text(AppIntl.of(context).settings_title), + title: Text(AppIntl.of(context)!.settings_title), ), body: ListView( children: [ ListTile( title: Text( - AppIntl.of(context).settings_display_pref_category, + AppIntl.of(context)!.settings_display_pref_category, style: const TextStyle(color: AppTheme.etsLightRed), ), ), @@ -46,21 +46,21 @@ class _SettingsViewState extends State { PopupMenuItem( value: ThemeMode.light, child: ListTile( - title: Text(AppIntl.of(context).light_theme), + title: Text(AppIntl.of(context)!.light_theme), leading: const Icon(Icons.wb_sunny), ), ), PopupMenuItem( value: ThemeMode.dark, child: ListTile( - title: Text(AppIntl.of(context).dark_theme), + title: Text(AppIntl.of(context)!.dark_theme), leading: const Icon(Icons.nightlight_round), ), ), PopupMenuItem( value: ThemeMode.system, child: ListTile( - title: Text(AppIntl.of(context).system_theme), + title: Text(AppIntl.of(context)!.system_theme), leading: const Icon(Icons.brightness_auto), ), ), @@ -71,12 +71,12 @@ class _SettingsViewState extends State { : model.selectedTheme == ThemeMode.dark ? Icons.nightlight_round : Icons.brightness_auto), - title: Text(AppIntl.of(context).settings_dark_theme_pref), + title: Text(AppIntl.of(context)!.settings_dark_theme_pref), subtitle: Text(model.selectedTheme == ThemeMode.light - ? AppIntl.of(context).light_theme + ? AppIntl.of(context)!.light_theme : model.selectedTheme == ThemeMode.dark - ? AppIntl.of(context).dark_theme - : AppIntl.of(context).system_theme), + ? AppIntl.of(context)!.dark_theme + : AppIntl.of(context)!.system_theme), trailing: const Icon(Icons.arrow_drop_down), ), ), @@ -87,7 +87,7 @@ class _SettingsViewState extends State { ), ListTile( title: Text( - AppIntl.of(context).settings_miscellaneous_category, + AppIntl.of(context)!.settings_miscellaneous_category, style: const TextStyle(color: AppTheme.etsLightRed), ), ), @@ -103,16 +103,16 @@ class _SettingsViewState extends State { itemBuilder: (BuildContext context) => >[ PopupMenuItem( value: AppIntl.supportedLocales.first.languageCode, - child: Text(AppIntl.of(context).settings_english), + child: Text(AppIntl.of(context)!.settings_english), ), PopupMenuItem( value: AppIntl.supportedLocales.last.languageCode, - child: Text(AppIntl.of(context).settings_french), + child: Text(AppIntl.of(context)!.settings_french), ), ], child: ListTile( leading: const Icon(Icons.language), - title: Text(AppIntl.of(context).settings_language_pref), + title: Text(AppIntl.of(context)!.settings_language_pref), subtitle: Text(model.currentLocale), trailing: const Icon(Icons.arrow_drop_down), ), diff --git a/lib/ui/views/student_view.dart b/lib/ui/views/student_view.dart index 75cfe9533..2f3e6e73e 100644 --- a/lib/ui/views/student_view.dart +++ b/lib/ui/views/student_view.dart @@ -24,8 +24,8 @@ class _StudentViewState extends State { @override Widget build(BuildContext context) { final List tabs = [ - AppIntl.of(context).grades_title, - AppIntl.of(context).profile_title + AppIntl.of(context)!.grades_title, + AppIntl.of(context)!.profile_title ]; return BaseScaffold( @@ -41,7 +41,7 @@ class _StudentViewState extends State { automaticallyImplyLeading: false, pinned: true, floating: true, - title: Text(AppIntl.of(context).title_student), + title: Text(AppIntl.of(context)!.title_student), forceElevated: innerBoxIsScrolled, bottom: TabBar( indicatorColor: diff --git a/lib/ui/widgets/dismissible_card.dart b/lib/ui/widgets/dismissible_card.dart index c312cced3..acd0621ab 100644 --- a/lib/ui/widgets/dismissible_card.dart +++ b/lib/ui/widgets/dismissible_card.dart @@ -1,15 +1,12 @@ // Flutter imports: import 'package:flutter/material.dart'; -// Project imports: -import 'package:notredame/ui/utils/app_theme.dart'; - class DismissibleCard extends StatelessWidget { final Widget child; final Function(DismissDirection) onDismissed; - final Color cardColor; + final Color? cardColor; final double elevation; @@ -20,7 +17,7 @@ class DismissibleCard extends StatelessWidget { required this.onDismissed, required this.child, this.elevation = 1, - this.cardColor = AppTheme.appletsPurple, + this.cardColor, this.isBusy = false}) : super(key: key); From e2a44bc41e84a34c634facfb1246c864a7e598b1 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 10:55:47 -0500 Subject: [PATCH 13/62] Migrate mocks to null safety --- .gitignore | 1 + pubspec.lock | 107 +++++++++++++++++- pubspec.yaml | 3 +- test/mock/managers/cache_manager_mock.dart | 8 +- .../mock/managers/course_repository_mock.dart | 28 +++-- .../managers/quick_links_repository_mock.dart | 6 +- test/mock/managers/settings_manager_mock.dart | 9 +- test/mock/managers/user_repository_mock.dart | 19 ++-- .../mock/services/analytics_service_mock.dart | 7 +- .../services/app_widget_service_mock.dart | 7 +- .../services/flutter_secure_storage_mock.dart | 9 +- test/mock/services/github_api_mock.dart | 6 +- test/mock/services/home_widget_mock.dart | 13 ++- test/mock/services/http_client_mock.dart | 26 ----- .../services/in_app_review_service_mock.dart | 6 +- .../services/internal_info_service_mock.dart | 8 +- .../services/launch_url_service_mock.dart | 6 +- .../services/navigation_service_mock.dart | 7 +- .../services/networking_service_mock.dart | 6 +- .../services/preferences_service_mock.dart | 10 +- .../services/remote_config_service_mock.dart | 6 +- .../services/rive_animation_service_mock.dart | 6 +- .../services/siren_flutter_service_mock.dart | 9 +- test/mock/viewmodels/login_viewmodel.dart | 7 -- 24 files changed, 231 insertions(+), 89 deletions(-) delete mode 100644 test/mock/services/http_client_mock.dart delete mode 100644 test/mock/viewmodels/login_viewmodel.dart diff --git a/.gitignore b/.gitignore index 2875a4e37..a12547a23 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ app_untranslated_messages.yaml # Flutter test test/**/failures/ +test/mock/**/*.mocks.dart # Certificates and secrets assets/certificates/ diff --git a/pubspec.lock b/pubspec.lock index 17314b6a4..f124c63bd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -64,6 +64,41 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.3.1" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.3" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.7" built_collection: dependency: transitive description: @@ -534,6 +569,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "10.2.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" get_it: dependency: "direct main" description: @@ -625,6 +667,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -667,6 +716,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.17.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" js: dependency: transitive description: @@ -737,13 +793,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" mockito: dependency: "direct dev" description: name: mockito url: "https://pub.dartlang.org" source: hosted - version: "5.3.2" + version: "5.4.0" nested: dependency: transitive description: @@ -919,6 +982,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.7.3" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.1" process: dependency: transitive description: @@ -940,6 +1010,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" reorderable_grid_view: dependency: "direct main" description: @@ -1024,6 +1101,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" simple_gesture_detector: dependency: transitive description: @@ -1134,6 +1225,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.12" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" tint: dependency: transitive description: @@ -1239,6 +1337,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" webview_flutter: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d03fa4148..92ca57005 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -80,9 +80,10 @@ dev_dependencies: flutter_test: sdk: flutter lint: ^2.0.1 - mockito: ^5.3.2 + mockito: ^5.3.3 flutter_config: ^2.0.0 flutter_launcher_icons: ^0.11.0 + build_runner: ^2.3.3 flutter_icons: android: "launcher_icon" diff --git a/test/mock/managers/cache_manager_mock.dart b/test/mock/managers/cache_manager_mock.dart index 19bc43c80..ca7a00826 100644 --- a/test/mock/managers/cache_manager_mock.dart +++ b/test/mock/managers/cache_manager_mock.dart @@ -1,12 +1,16 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/managers/cache_manager.dart'; import 'package:notredame/core/utils/cache_exception.dart'; +import 'cache_manager_mock.mocks.dart'; + /// Mock for the [CacheManager] -class CacheManagerMock extends Mock implements CacheManager { +@GenerateNiceMocks([MockSpec()]) +class CacheManagerMock extends MockCacheManager { /// Stub the get function of [mock], when [key] is used, [valueToReturn] is answered. static void stubGet(CacheManagerMock mock, String key, String valueToReturn) { when(mock.get(key)).thenAnswer((_) async => valueToReturn); @@ -23,7 +27,7 @@ class CacheManagerMock extends Mock implements CacheManager { static void stubUpdateException(CacheManagerMock mock, String key, {Exception exceptionToThrow = const CacheException(prefix: 'CacheException', message: '')}) { - when(mock.update(key, any)).thenThrow(exceptionToThrow); + when(mock.update(key, '')).thenThrow(exceptionToThrow); } /// Stub a exception while calling the delete function of [mock] when [key] is used. diff --git a/test/mock/managers/course_repository_mock.dart b/test/mock/managers/course_repository_mock.dart index 4dfbda627..498ddf505 100644 --- a/test/mock/managers/course_repository_mock.dart +++ b/test/mock/managers/course_repository_mock.dart @@ -1,12 +1,16 @@ // Package imports: import 'package:ets_api_clients/exceptions.dart'; import 'package:ets_api_clients/models.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/managers/course_repository.dart'; -class CourseRepositoryMock extends Mock implements CourseRepository { +import 'course_repository_mock.mocks.dart'; + +@GenerateNiceMocks([MockSpec()]) +class CourseRepositoryMock extends MockCourseRepository { /// Stub the getter [coursesActivities] of [mock] when called will return [toReturn]. static void stubCoursesActivities(CourseRepositoryMock mock, {List toReturn = const []}) { @@ -27,18 +31,18 @@ class CourseRepositoryMock extends Mock implements CourseRepository { /// Stub the function [getCoursesActivities] of [mock] when called will return [toReturn]. static void stubGetCoursesActivities(CourseRepositoryMock mock, - {List toReturn = const [], bool fromCacheOnly}) { + {List toReturn = const [], bool fromCacheOnly = false}) { when(mock.getCoursesActivities( - fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) + fromCacheOnly: fromCacheOnly)) .thenAnswer((_) async => toReturn); } /// Stub the function [getCoursesActivities] of [mock] when called will throw [toThrow]. static void stubGetCoursesActivitiesException(CourseRepositoryMock mock, {Exception toThrow = const ApiException(prefix: 'ApiException'), - bool fromCacheOnly}) { + bool fromCacheOnly = false}) { when(mock.getCoursesActivities( - fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) + fromCacheOnly: fromCacheOnly)) .thenAnswer((_) => Future.delayed(const Duration(milliseconds: 50)) .then((value) => throw toThrow)); } @@ -59,9 +63,9 @@ class CourseRepositoryMock extends Mock implements CourseRepository { /// Stub the function [getCourses] of [mock] when called will return [toReturn]. static void stubGetCourses(CourseRepositoryMock mock, - {List toReturn = const [], bool fromCacheOnly}) { + {List toReturn = const [], bool fromCacheOnly = false}) { when(mock.getCourses( - fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) + fromCacheOnly: fromCacheOnly)) .thenAnswer((_) async => toReturn); } @@ -74,9 +78,9 @@ class CourseRepositoryMock extends Mock implements CourseRepository { /// Stub the function [getCourses] of [mock] when called will throw [toThrow]. static void stubGetCoursesException(CourseRepositoryMock mock, {Exception toThrow = const ApiException(prefix: 'ApiException'), - bool fromCacheOnly}) { + bool fromCacheOnly = false}) { when(mock.getCourses( - fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) + fromCacheOnly: fromCacheOnly)) .thenAnswer((_) => Future.delayed(const Duration(milliseconds: 50)) .then((value) => throw toThrow)); } @@ -84,7 +88,7 @@ class CourseRepositoryMock extends Mock implements CourseRepository { /// Stub the function [getCourseSummary] of [mock] when called will return [toReturn]. static void stubGetCourseSummary( CourseRepositoryMock mock, Course courseCalled, - {Course toReturn}) { + {required Course toReturn}) { when(mock.getCourseSummary(courseCalled)).thenAnswer((_) async => toReturn); } @@ -99,9 +103,9 @@ class CourseRepositoryMock extends Mock implements CourseRepository { /// Stub the function [getScheduleActivities] of [mock] when called will return [toReturn]. static void stubGetScheduleActivities(CourseRepositoryMock mock, - {List toReturn = const [], bool fromCacheOnly}) { + {List toReturn = const [], bool fromCacheOnly = false}) { when(mock.getScheduleActivities( - fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) + fromCacheOnly: fromCacheOnly)) .thenAnswer((_) async => toReturn); } diff --git a/test/mock/managers/quick_links_repository_mock.dart b/test/mock/managers/quick_links_repository_mock.dart index 8cde2beb5..485f8fa79 100644 --- a/test/mock/managers/quick_links_repository_mock.dart +++ b/test/mock/managers/quick_links_repository_mock.dart @@ -1,5 +1,6 @@ // Package imports: import 'package:ets_api_clients/exceptions.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: @@ -7,7 +8,10 @@ import 'package:notredame/core/managers/quick_link_repository.dart'; import 'package:notredame/core/models/quick_link.dart'; import 'package:notredame/core/models/quick_link_data.dart'; -class QuickLinkRepositoryMock extends Mock implements QuickLinkRepository { +import 'quick_links_repository_mock.mocks.dart'; + +@GenerateNiceMocks([MockSpec()]) +class QuickLinkRepositoryMock extends MockQuickLinkRepository { /// Stub the function [getQuickLinkDataFromCache] of [mock] when called will return [toReturn]. static void stubGetQuickLinkDataFromCache(QuickLinkRepositoryMock mock, {List toReturn = const []}) { diff --git a/test/mock/managers/settings_manager_mock.dart b/test/mock/managers/settings_manager_mock.dart index 5a90997cb..f4bc3c268 100644 --- a/test/mock/managers/settings_manager_mock.dart +++ b/test/mock/managers/settings_manager_mock.dart @@ -1,5 +1,6 @@ // Flutter imports: import 'package:flutter/material.dart'; +import 'package:mockito/annotations.dart'; // Package imports: import 'package:mockito/mockito.dart'; @@ -8,7 +9,10 @@ import 'package:mockito/mockito.dart'; import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/managers/settings_manager.dart'; -class SettingsManagerMock extends Mock implements SettingsManager { +import 'settings_manager_mock.mocks.dart'; + +@GenerateNiceMocks([MockSpec()]) +class SettingsManagerMock extends MockSettingsManager { /// Stub the [getScheduleSettings] function of [mock], when called return [toReturn]. static void stubGetScheduleSettings(SettingsManagerMock mock, {Map toReturn = const {}}) { @@ -71,7 +75,8 @@ class SettingsManagerMock extends Mock implements SettingsManager { } /// Stub the [dateTimeNow] function of [mock], when called return [toReturn]. - static void stubDateTimeNow(SettingsManagerMock mock, {DateTime toReturn}) { + static void stubDateTimeNow(SettingsManagerMock mock, {required DateTime toReturn}) { + // ignore: cast_nullable_to_non_nullable when(mock.dateTimeNow).thenReturn(toReturn); } } diff --git a/test/mock/managers/user_repository_mock.dart b/test/mock/managers/user_repository_mock.dart index 0eb6b9955..cf07a476e 100644 --- a/test/mock/managers/user_repository_mock.dart +++ b/test/mock/managers/user_repository_mock.dart @@ -1,13 +1,17 @@ // Package imports: import 'package:ets_api_clients/exceptions.dart'; import 'package:ets_api_clients/models.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/managers/user_repository.dart'; +import 'user_repository_mock.mocks.dart'; + /// Mock for the [UserRepository] -class UserRepositoryMock extends Mock implements UserRepository { +@GenerateNiceMocks([MockSpec()]) +class UserRepositoryMock extends MockUserRepository { /// When [monETSUser] is called will return [userToReturn] static void stubMonETSUser(UserRepositoryMock mock, MonETSUser userToReturn) { when(mock.monETSUser).thenAnswer((_) => userToReturn); @@ -43,22 +47,23 @@ class UserRepositoryMock extends Mock implements UserRepository { /// Stub the getter [ProfileStudent] of [mock] when called will return [toReturn]. static void stubProfileStudent(UserRepositoryMock mock, - {ProfileStudent toReturn}) { + {ProfileStudent? toReturn}) { when(mock.info).thenReturn(toReturn); } /// Stub the function [getInfo] of [mock] when called will return [toReturn]. static void stubGetInfo(UserRepositoryMock mock, - {ProfileStudent toReturn, bool fromCacheOnly}) { + {ProfileStudent? toReturn, bool? fromCacheOnly}) { when(mock.getInfo( fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) - .thenAnswer((_) async => toReturn); + // ignore: cast_nullable_to_non_nullable + .thenAnswer((_) async => toReturn ?? anyNamed("profileStudent") as ProfileStudent); } /// Stub the function [getInfo] of [mock] when called will throw [toThrow]. static void stubGetInfoException(UserRepositoryMock mock, {Exception toThrow = const ApiException(prefix: 'ApiException'), - bool fromCacheOnly}) { + bool? fromCacheOnly}) { when(mock.getInfo( fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) .thenAnswer((_) => Future.delayed(const Duration(milliseconds: 50)) @@ -73,7 +78,7 @@ class UserRepositoryMock extends Mock implements UserRepository { /// Stub the function [getPrograms] of [mock] when called will return [toReturn]. static void stubGetPrograms(UserRepositoryMock mock, - {List toReturn = const [], bool fromCacheOnly}) { + {List toReturn = const [], bool? fromCacheOnly}) { when(mock.getPrograms( fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) .thenAnswer((_) async => toReturn); @@ -82,7 +87,7 @@ class UserRepositoryMock extends Mock implements UserRepository { /// Stub the function [getPrograms] of [mock] when called will throw [toThrow]. static void stubGetProgramsException(UserRepositoryMock mock, {Exception toThrow = const ApiException(prefix: 'ApiException'), - bool fromCacheOnly}) { + bool? fromCacheOnly}) { when(mock.getPrograms( fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) .thenAnswer((_) => Future.delayed(const Duration(milliseconds: 50)) diff --git a/test/mock/services/analytics_service_mock.dart b/test/mock/services/analytics_service_mock.dart index 78cd8a958..4417498e6 100644 --- a/test/mock/services/analytics_service_mock.dart +++ b/test/mock/services/analytics_service_mock.dart @@ -1,8 +1,11 @@ // Package imports: -import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; // Project imports: import 'package:notredame/core/services/analytics_service.dart'; +import 'analytics_service_mock.mocks.dart'; + /// Mock for the [AnalyticsService] -class AnalyticsServiceMock extends Mock implements AnalyticsService {} +@GenerateNiceMocks([MockSpec()]) +class AnalyticsServiceMock extends MockAnalyticsService {} diff --git a/test/mock/services/app_widget_service_mock.dart b/test/mock/services/app_widget_service_mock.dart index f2edbb8b2..d4799802e 100644 --- a/test/mock/services/app_widget_service_mock.dart +++ b/test/mock/services/app_widget_service_mock.dart @@ -1,8 +1,11 @@ // Package imports: -import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; // Project imports: import 'package:notredame/core/services/app_widget_service.dart'; +import 'app_widget_service_mock.mocks.dart'; + /// Mock for the [AppWidgetService] -class AppWidgetServiceMock extends Mock implements AppWidgetService {} +@GenerateNiceMocks([MockSpec()]) +class AppWidgetServiceMock extends MockAppWidgetService {} diff --git a/test/mock/services/flutter_secure_storage_mock.dart b/test/mock/services/flutter_secure_storage_mock.dart index 5e1a8a59d..b1b961bc8 100644 --- a/test/mock/services/flutter_secure_storage_mock.dart +++ b/test/mock/services/flutter_secure_storage_mock.dart @@ -1,12 +1,13 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; +import 'flutter_secure_storage_mock.mocks.dart'; + /// Mock for the [FlutterSecureStorage] -class FlutterSecureStorageMock extends Mock implements FlutterSecureStorage { +@GenerateNiceMocks([MockSpec()]) +class FlutterSecureStorageMock extends MockFlutterSecureStorage { /// Stub the read function of [FlutterSecureStorage] static void stubRead(FlutterSecureStorageMock mock, {required String key, required String valueToReturn}) { diff --git a/test/mock/services/github_api_mock.dart b/test/mock/services/github_api_mock.dart index c70ffcab6..e69491384 100644 --- a/test/mock/services/github_api_mock.dart +++ b/test/mock/services/github_api_mock.dart @@ -3,14 +3,18 @@ import 'dart:io'; // Package imports: import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/models/feedback_issue.dart'; import 'package:notredame/core/services/github_api.dart'; +import 'github_api_mock.mocks.dart'; + /// Mock for the [GithubApi] -class GithubApiMock extends Mock implements GithubApi { +@GenerateNiceMocks([MockSpec()]) +class GithubApiMock extends MockGithubApi { /// Stub the localFile of propertie [localFile] and return [fileToReturn]. static void stubLocalFile(GithubApiMock client, File fileToReturn) { when(client.localFile).thenAnswer((_) async => fileToReturn); diff --git a/test/mock/services/home_widget_mock.dart b/test/mock/services/home_widget_mock.dart index 71f1f619c..5e9e23373 100644 --- a/test/mock/services/home_widget_mock.dart +++ b/test/mock/services/home_widget_mock.dart @@ -4,21 +4,24 @@ import 'package:flutter/services.dart'; // Package imports: import 'package:flutter_test/flutter_test.dart'; import 'package:home_widget/home_widget.dart'; -import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; // Project imports: import 'package:notredame/core/services/app_widget_service.dart'; +import 'home_widget_mock.mocks.dart'; + /// Pseudo-mock for the static [HomeWidget] class (mocks the channel instead) -class HomeWidgetMock extends Mock { - MethodChannel _channel; - TestDefaultBinaryMessenger _messenger; +@GenerateNiceMocks([MockSpec()]) +class HomeWidgetMock extends MockHomeWidget { + late MethodChannel _channel; + late TestDefaultBinaryMessenger _messenger; HomeWidgetMock() { _channel = const MethodChannel('home_widget'); _messenger = - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; + TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger; } /// Overrides [HomeWidget]'s channel messenger behavior on [HomeWidget.setAppGroupId] diff --git a/test/mock/services/http_client_mock.dart b/test/mock/services/http_client_mock.dart deleted file mode 100644 index 085cb1d69..000000000 --- a/test/mock/services/http_client_mock.dart +++ /dev/null @@ -1,26 +0,0 @@ -// Dart imports: -import 'dart:convert'; - -// Package imports: -import 'package:http/http.dart' as http; -import 'package:mockito/mockito.dart'; - -/// Mock for the Http client -class HttpClientMock extends Mock implements http.Client { - /// Stub the next post of [url] and return [jsonResponse] with [statusCode] as http response code. - static void stubJsonPost(HttpClientMock client, String url, - Map jsonResponse, int statusCode) { - when(client.post(Uri.parse(url), - headers: anyNamed('headers'), body: anyNamed('body'))) - .thenAnswer( - (_) async => http.Response(jsonEncode(jsonResponse), statusCode)); - } - - /// Stub the next post request to [url] and return [response] with [statusCode] as http response code. - static void stubPost(HttpClientMock client, String url, String response, - [int statusCode = 200]) { - when(client.post(Uri.parse(url), - headers: anyNamed('headers'), body: anyNamed('body'))) - .thenAnswer((_) async => http.Response(response, statusCode)); - } -} diff --git a/test/mock/services/in_app_review_service_mock.dart b/test/mock/services/in_app_review_service_mock.dart index a0367af1f..825ed9895 100644 --- a/test/mock/services/in_app_review_service_mock.dart +++ b/test/mock/services/in_app_review_service_mock.dart @@ -1,11 +1,15 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/services/in_app_review_service.dart'; +import 'in_app_review_service_mock.mocks.dart'; + /// Mock for the [AnalyticsService] -class InAppReviewServiceMock extends Mock implements InAppReviewService { +@GenerateNiceMocks([MockSpec()]) +class InAppReviewServiceMock extends MockInAppReviewService { /// Stub the answer of [isAvailable] static void stubIsAvailable(InAppReviewServiceMock mock, {bool toReturn = true}) { diff --git a/test/mock/services/internal_info_service_mock.dart b/test/mock/services/internal_info_service_mock.dart index 570b81ff3..35018fd1b 100644 --- a/test/mock/services/internal_info_service_mock.dart +++ b/test/mock/services/internal_info_service_mock.dart @@ -1,11 +1,15 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:package_info_plus/package_info_plus.dart'; // Project imports: import 'package:notredame/core/services/internal_info_service.dart'; -class InternalInfoServiceMock extends Mock implements InternalInfoService { +import 'internal_info_service_mock.mocks.dart'; + +@GenerateNiceMocks([MockSpec()]) +class InternalInfoServiceMock extends MockInternalInfoService { /// Stub the answer of [getDeviceInfoForErrorReporting] static void stubGetDeviceInfoForErrorReporting(InternalInfoServiceMock mock) { when(mock.getDeviceInfoForErrorReporting()) @@ -14,7 +18,7 @@ class InternalInfoServiceMock extends Mock implements InternalInfoService { /// Stub the answer of [getPackageInfo] static void stubGetPackageInfo(InternalInfoServiceMock mock, - {String version}) { + {String version = "0.0.0"}) { when(mock.getPackageInfo()).thenAnswer((_) async => PackageInfo( appName: "ÉTSMobile", packageName: "ca.etsmtl.applets.etsmobile", diff --git a/test/mock/services/launch_url_service_mock.dart b/test/mock/services/launch_url_service_mock.dart index 0a328d3b6..409a8377a 100644 --- a/test/mock/services/launch_url_service_mock.dart +++ b/test/mock/services/launch_url_service_mock.dart @@ -1,11 +1,15 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/services/launch_url_service.dart'; +import 'launch_url_service_mock.mocks.dart'; + /// Mock for the [LaunchUrlService] -class LaunchUrlServiceMock extends Mock implements LaunchUrlService { +@GenerateNiceMocks([MockSpec()]) +class LaunchUrlServiceMock extends MockLaunchUrlService { static void stubCanLaunchUrl(LaunchUrlServiceMock client, String url, {bool toReturn = true}) { when(client.canLaunch(url)).thenAnswer((_) async => toReturn); diff --git a/test/mock/services/navigation_service_mock.dart b/test/mock/services/navigation_service_mock.dart index 0d53f6aef..ef9bb4f5a 100644 --- a/test/mock/services/navigation_service_mock.dart +++ b/test/mock/services/navigation_service_mock.dart @@ -1,8 +1,11 @@ // Package imports: -import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; // Project imports: import 'package:notredame/core/services/navigation_service.dart'; +import 'navigation_service_mock.mocks.dart'; + /// Mock for the [NavigationService] -class NavigationServiceMock extends Mock implements NavigationService {} +@GenerateNiceMocks([MockSpec()]) +class NavigationServiceMock extends MockNavigationService {} diff --git a/test/mock/services/networking_service_mock.dart b/test/mock/services/networking_service_mock.dart index e56f0ffd9..60505d609 100644 --- a/test/mock/services/networking_service_mock.dart +++ b/test/mock/services/networking_service_mock.dart @@ -1,12 +1,16 @@ // Package imports: import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/services/networking_service.dart'; +import 'networking_service_mock.mocks.dart'; + /// Mock for the [NetworkingService] -class NetworkingServiceMock extends Mock implements NetworkingService { +@GenerateNiceMocks([MockSpec()]) +class NetworkingServiceMock extends MockNetworkingService { /// Stub the user connection state static void stubHasConnectivity(NetworkingServiceMock service, {bool hasConnectivity = true}) { diff --git a/test/mock/services/preferences_service_mock.dart b/test/mock/services/preferences_service_mock.dart index dcacca670..f38d7c42a 100644 --- a/test/mock/services/preferences_service_mock.dart +++ b/test/mock/services/preferences_service_mock.dart @@ -1,11 +1,15 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/services/preferences_service.dart'; -class PreferencesServiceMock extends Mock implements PreferencesService { +import 'preferences_service_mock.mocks.dart'; + +@GenerateNiceMocks([MockSpec()]) +class PreferencesServiceMock extends MockPreferencesService { /// Stub the answer of [setString] when the [flag] is used. static void stubSetString(PreferencesServiceMock mock, PreferencesFlag flag, {bool toReturn = true}) { @@ -45,14 +49,14 @@ class PreferencesServiceMock extends Mock implements PreferencesService { /// Stub the answer of [getDateTime] when the [flag] is used. static void stubGetDateTime(PreferencesServiceMock mock, PreferencesFlag flag, - {DateTime toReturn}) { + {DateTime? toReturn}) { when(mock.getDateTime(flag)).thenAnswer((_) async => toReturn); } /// Stub the answer of [getPreferencesFlag] when the [flag] is used. static void stubGetPreferencesFlag( PreferencesServiceMock mock, PreferencesFlag flag, - {Object toReturn}) { + {Object? toReturn}) { when(mock.getPreferencesFlag(flag)).thenAnswer((_) async => toReturn); } diff --git a/test/mock/services/remote_config_service_mock.dart b/test/mock/services/remote_config_service_mock.dart index f4eea8f4b..4b01c6bad 100644 --- a/test/mock/services/remote_config_service_mock.dart +++ b/test/mock/services/remote_config_service_mock.dart @@ -1,11 +1,15 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/services/remote_config_service.dart'; +import 'remote_config_service_mock.mocks.dart'; + /// Mock for the [RemoteConfigService] -class RemoteConfigServiceMock extends Mock implements RemoteConfigService { +@GenerateNiceMocks([MockSpec()]) +class RemoteConfigServiceMock extends MockRemoteConfigService { /// Stub the getter [coursesActivities] of [mock] when called will return [toReturn]. static void stubGetCalendarViewEnabled(RemoteConfigServiceMock mock, {bool toReturn = true}) { diff --git a/test/mock/services/rive_animation_service_mock.dart b/test/mock/services/rive_animation_service_mock.dart index 958573652..cda80059f 100644 --- a/test/mock/services/rive_animation_service_mock.dart +++ b/test/mock/services/rive_animation_service_mock.dart @@ -1,4 +1,5 @@ // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:rive/rive.dart'; @@ -6,8 +7,11 @@ import 'package:rive/rive.dart'; import 'package:notredame/core/services/rive_animation_service.dart'; import 'package:notredame/core/utils/animation_exception.dart'; +import 'rive_animation_service_mock.mocks.dart'; + /// Mock for the [RiveAnimationService] -class RiveAnimationServiceMock extends Mock implements RiveAnimationService { +@GenerateNiceMocks([MockSpec()]) +class RiveAnimationServiceMock extends MockRiveAnimationService { static const startException = AnimationException( prefix: "addControllerToAnimation", message: diff --git a/test/mock/services/siren_flutter_service_mock.dart b/test/mock/services/siren_flutter_service_mock.dart index 46ff35783..7aa9652a0 100644 --- a/test/mock/services/siren_flutter_service_mock.dart +++ b/test/mock/services/siren_flutter_service_mock.dart @@ -1,15 +1,16 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Package imports: +import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:pub_semver/pub_semver.dart'; // Project imports: import 'package:notredame/core/services/siren_flutter_service.dart'; +import 'siren_flutter_service_mock.mocks.dart'; + /// Mock for the [SirenFlutterService] -class SirenFlutterServiceMock extends Mock implements SirenFlutterService { +@GenerateNiceMocks([MockSpec()]) +class SirenFlutterServiceMock extends MockSirenFlutterService { /// Stub the updateIsAvailable function of [SirenFlutterService] static void stubUpdateIsAvailable(SirenFlutterServiceMock mock, {bool valueToReturn = false}) { diff --git a/test/mock/viewmodels/login_viewmodel.dart b/test/mock/viewmodels/login_viewmodel.dart deleted file mode 100644 index f61441693..000000000 --- a/test/mock/viewmodels/login_viewmodel.dart +++ /dev/null @@ -1,7 +0,0 @@ -// Package imports: -import 'package:mockito/mockito.dart'; - -// Project imports: -import 'package:notredame/core/viewmodels/login_viewmodel.dart'; - -class LoginViewModelMock extends Mock implements LoginViewModel {} From ebc9dae9376b7fa60ac37d451171a9789fdd7298 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 11:11:57 -0500 Subject: [PATCH 14/62] Use late for all tests --- test/helpers.dart | 2 +- test/managers/course_repository_test.dart | 12 ++++++------ test/managers/quick_link_repository_test.dart | 4 ++-- test/managers/settings_manager_test.dart | 8 ++++---- test/managers/user_repository_test.dart | 16 ++++++++-------- test/services/app_widget_service_test.dart | 4 ++-- test/services/preferences_service_test.dart | 4 ++-- .../choose_language_viewmodel_test.dart | 6 +++--- test/viewmodels/dashboard_viewmodel_test.dart | 16 ++++++++-------- test/viewmodels/faq_viewmodel_test.dart | 4 ++-- test/viewmodels/feedback_viewmodel_test.dart | 8 ++++---- .../grades_details_viewmodel_test.dart | 6 +++--- test/viewmodels/grades_viewmodel_test.dart | 6 +++--- test/viewmodels/login_viewmodel_test.dart | 8 ++++---- test/viewmodels/more_viewmodel_test.dart | 14 +++++++------- test/viewmodels/not_found_viewmodel_test.dart | 8 ++++---- test/viewmodels/profile_viewmodel_test.dart | 6 +++--- .../viewmodels/quick_links_viewmodel_test.dart | 10 +++++----- .../schedule_settings_viewmodel_test.dart | 6 +++--- test/viewmodels/schedule_viewmodel_test.dart | 6 +++--- test/viewmodels/settings_viewmodel_test.dart | 4 ++-- test/viewmodels/startup_viewmodel_test.dart | 18 +++++++++--------- .../web_link_card_viewmodel_test.dart | 10 +++++----- 23 files changed, 93 insertions(+), 93 deletions(-) diff --git a/test/helpers.dart b/test/helpers.dart index 65f401ea4..3d0a42463 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -53,7 +53,7 @@ import 'mock/services/siren_flutter_service_mock.dart'; String goldenFilePath(String goldenName) => "./goldenFiles/$goldenName.png"; /// Unregister the service [T] from GetIt -void unregister() { +void unregister() { if (locator.isRegistered()) { locator.unregister(); } diff --git a/test/managers/course_repository_test.dart b/test/managers/course_repository_test.dart index 9ec3e0da1..b6a084f22 100644 --- a/test/managers/course_repository_test.dart +++ b/test/managers/course_repository_test.dart @@ -21,13 +21,13 @@ import '../mock/managers/user_repository_mock.dart'; import '../mock/services/networking_service_mock.dart'; void main() { - AnalyticsService analyticsService; - NetworkingServiceMock networkingService; - UserRepository userRepository; - CacheManager cacheManager; + late AnalyticsService analyticsService; + late NetworkingServiceMock networkingService; + late UserRepository userRepository; + late CacheManager cacheManager; - CourseRepository manager; - SignetsAPIClient signetsApi; + late CourseRepository manager; + late SignetsAPIClient signetsApi; final Session session = Session( shortName: 'NOW', diff --git a/test/managers/quick_link_repository_test.dart b/test/managers/quick_link_repository_test.dart index f3de245f0..070c5fba5 100644 --- a/test/managers/quick_link_repository_test.dart +++ b/test/managers/quick_link_repository_test.dart @@ -17,8 +17,8 @@ import '../helpers.dart'; import '../mock/managers/cache_manager_mock.dart'; void main() { - CacheManager cacheManager; - QuickLinkRepository quickLinkRepository; + late CacheManager cacheManager; + late QuickLinkRepository quickLinkRepository; group("QuickLinkRepository - ", () { setUp(() { diff --git a/test/managers/settings_manager_test.dart b/test/managers/settings_manager_test.dart index e3ff48dca..3ea16b4e4 100644 --- a/test/managers/settings_manager_test.dart +++ b/test/managers/settings_manager_test.dart @@ -20,10 +20,10 @@ import '../mock/services/preferences_service_mock.dart'; import '../mock/services/remote_config_service_mock.dart'; void main() { - AnalyticsService analyticsService; - RemoteConfigService remoteConfigService; - PreferencesService preferencesService; - SettingsManager manager; + late AnalyticsService analyticsService; + late RemoteConfigService remoteConfigService; + late PreferencesService preferencesService; + late SettingsManager manager; group("SettingsManager - ", () { setUp(() async { diff --git a/test/managers/user_repository_test.dart b/test/managers/user_repository_test.dart index b475990d4..4bdc89bb9 100644 --- a/test/managers/user_repository_test.dart +++ b/test/managers/user_repository_test.dart @@ -24,14 +24,14 @@ import '../mock/services/flutter_secure_storage_mock.dart'; import '../mock/services/networking_service_mock.dart'; void main() { - AnalyticsService analyticsService; - MonETSAPIClient monETSApi; - FlutterSecureStorageMock secureStorage; - CacheManager cacheManager; - SignetsAPIClient signetsApi; - NetworkingServiceMock networkingService; - - UserRepository manager; + late AnalyticsService analyticsService; + late MonETSAPIClient monETSApi; + late FlutterSecureStorageMock secureStorage; + late CacheManager cacheManager; + late SignetsAPIClient signetsApi; + late NetworkingServiceMock networkingService; + + late UserRepository manager; group('UserRepository - ', () { setUp(() { diff --git a/test/services/app_widget_service_test.dart b/test/services/app_widget_service_test.dart index 5e291b4a3..cc3eea619 100644 --- a/test/services/app_widget_service_test.dart +++ b/test/services/app_widget_service_test.dart @@ -12,8 +12,8 @@ import '../mock/services/home_widget_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - AppWidgetService service; - HomeWidgetMock homeWidgetMock; + late AppWidgetService service; + late HomeWidgetMock homeWidgetMock; group("AppWidgetServiceTest - ", () { setUp(() { diff --git a/test/services/preferences_service_test.dart b/test/services/preferences_service_test.dart index b103d5100..547faeaba 100644 --- a/test/services/preferences_service_test.dart +++ b/test/services/preferences_service_test.dart @@ -7,9 +7,9 @@ import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/services/preferences_service.dart'; void main() { - SharedPreferences sharedPreferences; + late SharedPreferences sharedPreferences; - PreferencesService service; + late PreferencesService service; SharedPreferences.setMockInitialValues({}); TestWidgetsFlutterBinding.ensureInitialized(); diff --git a/test/viewmodels/choose_language_viewmodel_test.dart b/test/viewmodels/choose_language_viewmodel_test.dart index 8873d58a3..0e02c4368 100644 --- a/test/viewmodels/choose_language_viewmodel_test.dart +++ b/test/viewmodels/choose_language_viewmodel_test.dart @@ -12,11 +12,11 @@ import 'package:notredame/core/viewmodels/choose_language_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/settings_manager_mock.dart'; -ChooseLanguageViewModel viewModel; +late ChooseLanguageViewModel viewModel; void main() { - NavigationService navigationService; - SettingsManager settingsManager; + late NavigationService navigationService; + late SettingsManager settingsManager; group("ChooseLanguageViewModel - ", () { setUp(() async { diff --git a/test/viewmodels/dashboard_viewmodel_test.dart b/test/viewmodels/dashboard_viewmodel_test.dart index 2154d8c57..d5548719a 100644 --- a/test/viewmodels/dashboard_viewmodel_test.dart +++ b/test/viewmodels/dashboard_viewmodel_test.dart @@ -20,14 +20,14 @@ import '../mock/services/preferences_service_mock.dart'; import '../mock/services/remote_config_service_mock.dart'; void main() { - PreferencesService preferenceService; - SettingsManager settingsManager; - DashboardViewModel viewModel; - CourseRepository courseRepository; - RemoteConfigService remoteConfigService; - PreferencesServiceMock preferencesServiceMock; - InAppReviewServiceMock inAppReviewServiceMock; - AnalyticsService analyticsService; + late PreferencesService preferenceService; + late SettingsManager settingsManager; + late DashboardViewModel viewModel; + late CourseRepository courseRepository; + late RemoteConfigService remoteConfigService; + late PreferencesServiceMock preferencesServiceMock; + late InAppReviewServiceMock inAppReviewServiceMock; + late AnalyticsService analyticsService; final gen101 = CourseActivity( courseGroup: "GEN101", diff --git a/test/viewmodels/faq_viewmodel_test.dart b/test/viewmodels/faq_viewmodel_test.dart index 219fd8df5..2f433fe8c 100644 --- a/test/viewmodels/faq_viewmodel_test.dart +++ b/test/viewmodels/faq_viewmodel_test.dart @@ -13,9 +13,9 @@ import '../helpers.dart'; import '../mock/services/launch_url_service_mock.dart'; void main() { - LaunchUrlServiceMock launchUrlService; + late LaunchUrlServiceMock launchUrlService; - FaqViewModel viewModel; + late FaqViewModel viewModel; group('FaqViewModel - ', () { setUp(() async { diff --git a/test/viewmodels/feedback_viewmodel_test.dart b/test/viewmodels/feedback_viewmodel_test.dart index 744d9c732..e90d70035 100644 --- a/test/viewmodels/feedback_viewmodel_test.dart +++ b/test/viewmodels/feedback_viewmodel_test.dart @@ -27,12 +27,12 @@ void main() { // Needed to support FlutterToast. TestWidgetsFlutterBinding.ensureInitialized(); - GithubApiMock githubApiMock; + late GithubApiMock githubApiMock; - PreferencesServiceMock preferencesServiceMock; + late PreferencesServiceMock preferencesServiceMock; - AppIntl appIntl; - FeedbackViewModel viewModel; + late AppIntl appIntl; + late FeedbackViewModel viewModel; const feedBackText = 'Notre-Dame bug report'; final file = File('bugReportTest.png'); final filePath = file.path.split('/').last; diff --git a/test/viewmodels/grades_details_viewmodel_test.dart b/test/viewmodels/grades_details_viewmodel_test.dart index d90ec987f..83bfaab4e 100644 --- a/test/viewmodels/grades_details_viewmodel_test.dart +++ b/test/viewmodels/grades_details_viewmodel_test.dart @@ -13,9 +13,9 @@ import '../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - AppIntl intl; - GradesDetailsViewModel viewModel; - CourseRepository courseRepository; + late AppIntl intl; + late GradesDetailsViewModel viewModel; + late CourseRepository courseRepository; final CourseSummary courseSummary = CourseSummary( currentMark: 5, diff --git a/test/viewmodels/grades_viewmodel_test.dart b/test/viewmodels/grades_viewmodel_test.dart index d1e5df79f..ee07175e2 100644 --- a/test/viewmodels/grades_viewmodel_test.dart +++ b/test/viewmodels/grades_viewmodel_test.dart @@ -14,9 +14,9 @@ import '../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - CourseRepository courseRepository; - AppIntl intl; - GradesViewModel viewModel; + late CourseRepository courseRepository; + late AppIntl intl; + late GradesViewModel viewModel; final Course courseSummer = Course( acronym: 'GEN101', diff --git a/test/viewmodels/login_viewmodel_test.dart b/test/viewmodels/login_viewmodel_test.dart index 5391ffbb2..df2532840 100644 --- a/test/viewmodels/login_viewmodel_test.dart +++ b/test/viewmodels/login_viewmodel_test.dart @@ -20,12 +20,12 @@ void main() { const String passwordCodeValid = "password"; const String passwordCodeInvalid = ""; - NavigationService navigationService; - UserRepositoryMock userRepositoryMock; + late NavigationService navigationService; + late UserRepositoryMock userRepositoryMock; - AppIntl appIntl; + late AppIntl appIntl; - LoginViewModel viewModel; + late LoginViewModel viewModel; group('LoginViewModel - ', () { setUp(() async { diff --git a/test/viewmodels/more_viewmodel_test.dart b/test/viewmodels/more_viewmodel_test.dart index 9d1ed4603..f43b5cbac 100644 --- a/test/viewmodels/more_viewmodel_test.dart +++ b/test/viewmodels/more_viewmodel_test.dart @@ -25,13 +25,13 @@ void main() { // Needed to support FlutterToast. TestWidgetsFlutterBinding.ensureInitialized(); - CacheManagerMock cacheManagerMock; - SettingsManagerMock settingsManagerMock; - CourseRepositoryMock courseRepositoryMock; - PreferencesService preferenceService; - RemoteConfigService remoteConfigService; - UserRepositoryMock userRepositoryMock; - NavigationService navigationService; + late CacheManagerMock cacheManagerMock; + late SettingsManagerMock settingsManagerMock; + late CourseRepositoryMock courseRepositoryMock; + late PreferencesService preferenceService; + late RemoteConfigService remoteConfigService; + late UserRepositoryMock userRepositoryMock; + late NavigationService navigationService; AppIntl appIntl; MoreViewModel viewModel; diff --git a/test/viewmodels/not_found_viewmodel_test.dart b/test/viewmodels/not_found_viewmodel_test.dart index f70b73d14..b0ba10a91 100644 --- a/test/viewmodels/not_found_viewmodel_test.dart +++ b/test/viewmodels/not_found_viewmodel_test.dart @@ -13,11 +13,11 @@ import '../helpers.dart'; import '../mock/services/rive_animation_service_mock.dart'; void main() { - NavigationService navigationService; - RiveAnimationService riveAnimationService; - AnalyticsService analyticsService; + late NavigationService navigationService; + late RiveAnimationService riveAnimationService; + late AnalyticsService analyticsService; - NotFoundViewModel viewModel; + late NotFoundViewModel viewModel; group('NotFoundViewModel - ', () { const String pageNotFoundPassed = "/test"; diff --git a/test/viewmodels/profile_viewmodel_test.dart b/test/viewmodels/profile_viewmodel_test.dart index 7dd5faaf0..6c83462b2 100644 --- a/test/viewmodels/profile_viewmodel_test.dart +++ b/test/viewmodels/profile_viewmodel_test.dart @@ -11,9 +11,9 @@ import 'package:notredame/core/viewmodels/profile_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/user_repository_mock.dart'; -UserRepository userRepository; -SettingsManager settingsManager; -ProfileViewModel viewModel; +late UserRepository userRepository; +late SettingsManager settingsManager; +late ProfileViewModel viewModel; void main() { // Needed to support FlutterToast. diff --git a/test/viewmodels/quick_links_viewmodel_test.dart b/test/viewmodels/quick_links_viewmodel_test.dart index 21ac94f1a..61d17c88a 100644 --- a/test/viewmodels/quick_links_viewmodel_test.dart +++ b/test/viewmodels/quick_links_viewmodel_test.dart @@ -12,13 +12,13 @@ import '../helpers.dart'; import '../mock/managers/quick_links_repository_mock.dart'; void main() { - AppIntl intl; - QuickLinksViewModel viewModel; - QuickLinkRepository quickLinkRepository; + late AppIntl intl; + late QuickLinksViewModel viewModel; + late QuickLinkRepository quickLinkRepository; // Sample data for tests - QuickLinkData quickLinkDataSample; - QuickLink quickLinkSample; + late QuickLinkData quickLinkDataSample; + late QuickLink quickLinkSample; group("QuickLinksViewModel - ", () { setUp(() async { diff --git a/test/viewmodels/schedule_settings_viewmodel_test.dart b/test/viewmodels/schedule_settings_viewmodel_test.dart index e49d47f64..aa47527a0 100644 --- a/test/viewmodels/schedule_settings_viewmodel_test.dart +++ b/test/viewmodels/schedule_settings_viewmodel_test.dart @@ -14,9 +14,9 @@ import '../helpers.dart'; import '../mock/managers/course_repository_mock.dart'; import '../mock/managers/settings_manager_mock.dart'; -SettingsManager settingsManager; -CourseRepository courseRepository; -ScheduleSettingsViewModel viewModel; +late SettingsManager settingsManager; +late CourseRepository courseRepository; +late ScheduleSettingsViewModel viewModel; void main() { // Needed to support FlutterToast. diff --git a/test/viewmodels/schedule_viewmodel_test.dart b/test/viewmodels/schedule_viewmodel_test.dart index 5e599bf82..f5baa1631 100644 --- a/test/viewmodels/schedule_viewmodel_test.dart +++ b/test/viewmodels/schedule_viewmodel_test.dart @@ -14,9 +14,9 @@ import '../helpers.dart'; import '../mock/managers/course_repository_mock.dart'; import '../mock/managers/settings_manager_mock.dart'; -CourseRepository courseRepository; -SettingsManager settingsManager; -ScheduleViewModel viewModel; +late CourseRepository courseRepository; +late SettingsManager settingsManager; +late ScheduleViewModel viewModel; void main() { // Needed to support FlutterToast. diff --git a/test/viewmodels/settings_viewmodel_test.dart b/test/viewmodels/settings_viewmodel_test.dart index 6e9f696fb..eec9b07d0 100644 --- a/test/viewmodels/settings_viewmodel_test.dart +++ b/test/viewmodels/settings_viewmodel_test.dart @@ -13,10 +13,10 @@ import 'package:notredame/core/viewmodels/settings_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/settings_manager_mock.dart'; -SettingsViewModel viewModel; +late SettingsViewModel viewModel; void main() { - SettingsManager settingsManager; + late SettingsManager settingsManager; group("SettingsViewModel - ", () { setUp(() async { diff --git a/test/viewmodels/startup_viewmodel_test.dart b/test/viewmodels/startup_viewmodel_test.dart index c2fc6b5f3..baebdea9e 100644 --- a/test/viewmodels/startup_viewmodel_test.dart +++ b/test/viewmodels/startup_viewmodel_test.dart @@ -22,15 +22,15 @@ import '../mock/services/preferences_service_mock.dart'; import '../mock/services/siren_flutter_service_mock.dart'; void main() { - NavigationService navigationService; - UserRepositoryMock userRepositoryMock; - SettingsManagerMock settingsManagerMock; - PreferencesServiceMock preferencesServiceMock; - NetworkingServiceMock networkingService; - InternalInfoServiceMock internalInfoServiceMock; - SirenFlutterServiceMock sirenFlutterServiceMock; - - StartUpViewModel viewModel; + late NavigationService navigationService; + late UserRepositoryMock userRepositoryMock; + late SettingsManagerMock settingsManagerMock; + late PreferencesServiceMock preferencesServiceMock; + late NetworkingServiceMock networkingService; + late InternalInfoServiceMock internalInfoServiceMock; + late SirenFlutterServiceMock sirenFlutterServiceMock; + + late StartUpViewModel viewModel; group('StartupViewModel - ', () { setUp(() async { diff --git a/test/viewmodels/web_link_card_viewmodel_test.dart b/test/viewmodels/web_link_card_viewmodel_test.dart index cdd207b5c..dbf350b3c 100644 --- a/test/viewmodels/web_link_card_viewmodel_test.dart +++ b/test/viewmodels/web_link_card_viewmodel_test.dart @@ -19,12 +19,12 @@ import '../mock/services/internal_info_service_mock.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); - NavigationService navigationService; - AnalyticsService analyticsService; - InternalInfoService internalInfoService; - LaunchUrlService launchUrlService; + late NavigationService navigationService; + late AnalyticsService analyticsService; + late InternalInfoService internalInfoService; + late LaunchUrlService launchUrlService; - WebLinkCardViewModel viewModel; + late WebLinkCardViewModel viewModel; final quickLink = QuickLink( id: 1, image: const Icon(Icons.ac_unit), name: 'test', link: 'testlink'); From 14b8317e4ac14b0180d1f993ad30966504f30cc1 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 11:18:41 -0500 Subject: [PATCH 15/62] Fix service tests --- test/services/app_widget_service_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/services/app_widget_service_test.dart b/test/services/app_widget_service_test.dart index cc3eea619..785c8e0ae 100644 --- a/test/services/app_widget_service_test.dart +++ b/test/services/app_widget_service_test.dart @@ -133,7 +133,7 @@ void main() { test("progress", () async { const WidgetType type = WidgetType.progress; homeWidgetMock.stubUpdateWidgetMock( - type.androidName, type.androidName, type.iOSname); + type.androidName!, type.androidName!, type.iOSname!); expect( await HomeWidget.updateWidget( name: type.androidName, @@ -145,7 +145,7 @@ void main() { test("grades", () async { const WidgetType type = WidgetType.grades; homeWidgetMock.stubUpdateWidgetMock( - type.androidName, type.androidName, type.iOSname); + type.androidName!, type.androidName!, type.iOSname!); expect( await HomeWidget.updateWidget( name: type.androidName, From c831dd637dd9ff7085b1ef42339043fba1a829f4 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 11:22:21 -0500 Subject: [PATCH 16/62] Migrate helpers to null safety --- test/helpers.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/helpers.dart b/test/helpers.dart index 3d0a42463..29ee4db8a 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -148,7 +148,7 @@ SirenFlutterService setupSirenFlutterServiceMock() { return service; } -void setupFlutterToastMock([WidgetTester tester]) { +void setupFlutterToastMock([WidgetTester? tester]) { const MethodChannel channel = MethodChannel('PonnamKarthik/fluttertoast'); TestDefaultBinaryMessenger messenger; @@ -157,7 +157,7 @@ void setupFlutterToastMock([WidgetTester tester]) { messenger = tester.binding.defaultBinaryMessenger; } else { messenger = - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; + TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger; } messenger.setMockMethodCallHandler(channel, (MethodCall methodCall) async { @@ -288,7 +288,7 @@ NetworkingService setupNetworkingServiceMock() { return service; } -void setupInAppReviewMock([WidgetTester tester]) { +void setupInAppReviewMock([WidgetTester? tester]) { const MethodChannel channel = MethodChannel('dev.britannio.in_app_review'); TestDefaultBinaryMessenger messenger; @@ -297,7 +297,7 @@ void setupInAppReviewMock([WidgetTester tester]) { messenger = tester.binding.defaultBinaryMessenger; } else { messenger = - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; + TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger; } messenger.setMockMethodCallHandler(channel, (MethodCall methodCall) async { From db1fddfea8427aeeaeba00e492877697e183bda2 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 16:55:45 -0500 Subject: [PATCH 17/62] Migrate managers tests to null safety --- test/helpers.dart | 12 +- test/managers/course_repository_test.dart | 677 +++++++++--------- test/managers/settings_manager_test.dart | 250 ++++--- test/managers/user_repository_test.dart | 261 +++---- .../services/flutter_secure_storage_mock.dart | 2 +- .../choose_language_viewmodel_test.dart | 10 - 6 files changed, 597 insertions(+), 615 deletions(-) diff --git a/test/helpers.dart b/test/helpers.dart index 29ee4db8a..bf5c2048f 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -79,7 +79,7 @@ Widget localizedWidget( ); /// Load a mock of the [SignetsAPIClient] -SignetsAPIClient setupSignetsApiMock() { +SignetsAPIClientMock setupSignetsApiMock() { unregister(); final service = SignetsAPIClientMock(); @@ -109,7 +109,7 @@ MonETSAPIClient setupMonETSApiMock() { } /// Load a mock of the [AnalyticsService] -AnalyticsService setupAnalyticsServiceMock() { +AnalyticsServiceMock setupAnalyticsServiceMock() { unregister(); final service = AnalyticsServiceMock(); @@ -199,7 +199,7 @@ GithubApi setupGithubApiMock() { } /// Load a mock of the [FlutterSecureStorage] -FlutterSecureStorage setupFlutterSecureStorageMock() { +FlutterSecureStorageMock setupFlutterSecureStorageMock() { unregister(); final service = FlutterSecureStorageMock(); @@ -224,7 +224,7 @@ Future setupAppIntl() async { } /// Load a mock of the [CacheManager] -CacheManager setupCacheManagerMock() { +CacheManagerMock setupCacheManagerMock() { unregister(); final service = CacheManagerMock(); @@ -245,7 +245,7 @@ Logger setupLogger() { } /// Load a mock of the [PreferencesService] -PreferencesService setupPreferencesServiceMock() { +PreferencesServiceMock setupPreferencesServiceMock() { unregister(); final service = PreferencesServiceMock(); @@ -276,7 +276,7 @@ CourseRepository setupCourseRepositoryMock() { /// Load a mock of the [NetworkingService] /// Will also stub the first value of changeConnectivityStream -NetworkingService setupNetworkingServiceMock() { +NetworkingServiceMock setupNetworkingServiceMock() { unregister(); final service = NetworkingServiceMock(); diff --git a/test/managers/course_repository_test.dart b/test/managers/course_repository_test.dart index b6a084f22..042551c05 100644 --- a/test/managers/course_repository_test.dart +++ b/test/managers/course_repository_test.dart @@ -18,16 +18,17 @@ import 'package:notredame/core/services/analytics_service.dart'; import '../helpers.dart'; import '../mock/managers/cache_manager_mock.dart'; import '../mock/managers/user_repository_mock.dart'; +import '../mock/services/analytics_service_mock.dart'; import '../mock/services/networking_service_mock.dart'; void main() { - late AnalyticsService analyticsService; - late NetworkingServiceMock networkingService; + late AnalyticsServiceMock analyticsServiceMock; + late NetworkingServiceMock networkingServiceMock; late UserRepository userRepository; - late CacheManager cacheManager; + late CacheManagerMock cacheManagerMock; late CourseRepository manager; - late SignetsAPIClient signetsApi; + late SignetsAPIClientMock signetsApiMock; final Session session = Session( shortName: 'NOW', @@ -47,26 +48,26 @@ void main() { group("CourseRepository - ", () { setUp(() { // Setup needed services and managers - analyticsService = setupAnalyticsServiceMock(); - signetsApi = setupSignetsApiMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); + signetsApiMock = setupSignetsApiMock(); userRepository = setupUserRepositoryMock(); - cacheManager = setupCacheManagerMock(); - networkingService = setupNetworkingServiceMock() as NetworkingServiceMock; + cacheManagerMock = setupCacheManagerMock(); + networkingServiceMock = setupNetworkingServiceMock(); setupLogger(); manager = CourseRepository(); }); tearDown(() { - clearInteractions(analyticsService); + clearInteractions(analyticsServiceMock); unregister(); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); unregister(); clearInteractions(userRepository); unregister(); - clearInteractions(cacheManager); + clearInteractions(cacheManagerMock); unregister(); - clearInteractions(networkingService); + clearInteractions(networkingServiceMock); unregister(); }); @@ -87,31 +88,31 @@ void main() { setUp(() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, "password"); // Stub some sessions - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, [session]); + signetsApiMock, username, [session]); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("Activities are loaded from cache.", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(fromCacheOnly: true); expect(results, isInstanceOf>()); @@ -120,16 +121,16 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder( - [cacheManager.get(CourseRepository.coursesActivitiesCacheKey)]); + [cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey)]); }); test("Activities are only loaded from cache.", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(fromCacheOnly: true); expect(results, isInstanceOf>()); @@ -138,10 +139,10 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), ]); - verifyNoMoreInteractions(signetsApi); + verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(userRepository); }); @@ -149,15 +150,15 @@ void main() { "Trying to recover activities from cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubGetException(cacheManager as CacheManagerMock, + CacheManagerMock.stubGetException(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(); expect(results, isInstanceOf>()); @@ -166,39 +167,39 @@ void main() { reason: "The list of activities should be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.coursesActivitiesCacheKey, any) + cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, any) ]); - verify(signetsApi.getSessions( + verify(signetsApiMock.getSessions( username: username, password: anyNamed("password"))) .called(1); }); test("Doesn't retrieve sessions if they are already loaded", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); // Stub the SignetsAPI to return 1 activities SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, session.shortName, activities); + signetsApiMock, session.shortName, activities); // Load the sessions await manager.getSessions(); expect(manager.sessions, isNotEmpty); - clearInteractions(cacheManager); + clearInteractions(cacheManagerMock); clearInteractions(userRepository); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(); expect(results, isInstanceOf>()); @@ -207,61 +208,61 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.coursesActivitiesCacheKey, any) + cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, any) ]); - verifyNoMoreInteractions(signetsApi); + verifyNoMoreInteractions(signetsApiMock); }); test("getSessions fails", () async { // Stub SignetsApi to throw an exception - reset(signetsApi); + reset(signetsApiMock); SignetsAPIClientMock.stubGetSessionsException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); expect(manager.coursesActivities, isNull); expect(manager.getCoursesActivities(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.coursesActivities, isEmpty, reason: "The list of activities should be empty"); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); }); test("User authentication fails.", () async { // Stub the cache to return 0 activities - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode([])); // Load the sessions await manager.getSessions(); expect(manager.sessions, isNotEmpty); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); // Stub an authentication error reset(userRepository); @@ -271,21 +272,21 @@ void main() { expect(manager.getCoursesActivities(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.coursesActivities, isEmpty, reason: "There isn't any activities saved in the cache so the list should be empty"); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNoMoreInteractions(signetsApi); + verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(userRepository); }); @@ -293,7 +294,7 @@ void main() { "SignetsAPI returns new activities, the old ones should be maintained and the cache updated.", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); final CourseActivity courseActivity = CourseActivity( @@ -307,12 +308,12 @@ void main() { // Stub the SignetsAPI to return 2 activities SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, + signetsApiMock, session.shortName, [activity, courseActivity]); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(); expect(results, isInstanceOf>()); @@ -321,14 +322,14 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.coursesActivitiesCacheKey, + cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, jsonEncode([activity, courseActivity])) ]); }); @@ -337,15 +338,15 @@ void main() { "SignetsAPI returns activities that already exists, should avoid duplicata.", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); // Stub the SignetsAPI to return the same activity as the cache SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, session.shortName, activities); + signetsApiMock, session.shortName, activities); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(); expect(results, isInstanceOf>()); @@ -354,14 +355,14 @@ void main() { reason: "The list of activities should not have duplicata"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.coursesActivitiesCacheKey, + cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)) ]); }); @@ -370,15 +371,15 @@ void main() { "SignetsAPI returns activities that changed (for example class location changed).", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); // Load the sessions await manager.getSessions(); expect(manager.sessions, isNotEmpty); - clearInteractions(cacheManager); + clearInteractions(cacheManagerMock); clearInteractions(userRepository); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); final changedActivity = CourseActivity( courseGroup: activity.courseGroup, @@ -391,12 +392,12 @@ void main() { // Stub the SignetsAPI to return the same activity as the cache SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, + signetsApiMock, session.shortName, [changedActivity]); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(); expect(results, isInstanceOf>()); @@ -405,48 +406,48 @@ void main() { reason: "The list of activities should be updated"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.coursesActivitiesCacheKey, + cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, jsonEncode([changedActivity])) ]); }); test("SignetsAPI raise a exception.", () async { // Stub the cache to return no activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode([])); // Stub the SignetsAPI to throw an exception SignetsAPIClientMock.stubGetCoursesActivitiesException( - signetsApi as SignetsAPIClientMock, session.shortName, + signetsApiMock, session.shortName, exceptionToThrow: const ApiException(prefix: CourseRepository.tag)); expect(manager.coursesActivities, isNull); expect(manager.getCoursesActivities(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.coursesActivities, isEmpty, reason: "The list of activities should be empty"); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); }); @@ -454,18 +455,18 @@ void main() { "Cache update fails, should still return the updated list of activities.", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); // Stub the SignetsAPI to return 1 activity SignetsAPIClientMock.stubGetCoursesActivities( - signetsApi as SignetsAPIClientMock, session.shortName, activities); + signetsApiMock, session.shortName, activities); - CacheManagerMock.stubUpdateException(cacheManager as CacheManagerMock, + CacheManagerMock.stubUpdateException(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey); expect(manager.coursesActivities, isNull); - final List results = + final List? results = await manager.getCoursesActivities(); expect(results, isInstanceOf>()); @@ -474,10 +475,10 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.coursesActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCoursesActivities( + signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), session: session.shortName) @@ -487,12 +488,12 @@ void main() { test("Should force fromCacheOnly mode when user has no connectivity", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesActivitiesCacheKey, jsonEncode(activities)); //Stub the networkingService to return no connectivity - reset(networkingService); - NetworkingServiceMock.stubHasConnectivity(networkingService, + reset(networkingServiceMock); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock, hasConnectivity: false); final activitiesCache = await manager.getCoursesActivities(); @@ -536,30 +537,30 @@ void main() { setUp(() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, "password"); // Stub some sessions - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, [session]); + signetsApiMock, username, [session]); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("Activities are loaded from cache.", () async { // Stub the cache to return 1 activity CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode(scheduleActivities)); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetScheduleActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); expect(manager.coursesActivities, isNull); final List results = @@ -571,21 +572,21 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getScheduleActivities( + signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.scheduleActivitiesCacheKey, any) + cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, any) ]); }); test("Activities are only loaded from cache.", () async { // Stub the cache to return 1 activity CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode(scheduleActivities)); @@ -599,10 +600,10 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), ]); - verifyNoMoreInteractions(signetsApi); + verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(userRepository); }); @@ -610,12 +611,12 @@ void main() { "Trying to recover activities from cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubGetException(cacheManager as CacheManagerMock, + CacheManagerMock.stubGetException(cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetScheduleActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); expect(manager.scheduleActivities, isNull); final List results = @@ -627,17 +628,17 @@ void main() { reason: "The list of activities should be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getScheduleActivities( + signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.scheduleActivitiesCacheKey, any) + cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, any) ]); - verify(signetsApi.getSessions( + verify(signetsApiMock.getSessions( username: username, password: anyNamed("password"))) .called(1); }); @@ -645,20 +646,20 @@ void main() { test("Doesn't retrieve sessions if they are already loaded", () async { // Stub the cache to return 1 activity CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode(scheduleActivities)); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetScheduleActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); // Load the sessions await manager.getSessions(); expect(manager.sessions, isNotEmpty); - clearInteractions(cacheManager); + clearInteractions(cacheManagerMock); clearInteractions(userRepository); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); expect(manager.scheduleActivities, isNull); final List results = @@ -670,63 +671,63 @@ void main() { reason: "The list of activities should not be empty"); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getScheduleActivities( + signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.scheduleActivitiesCacheKey, any) + cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, any) ]); - verifyNoMoreInteractions(signetsApi); + verifyNoMoreInteractions(signetsApiMock); }); test("getSessions fails", () async { // Stub SignetsApi to throw an exception - reset(signetsApi); + reset(signetsApiMock); SignetsAPIClientMock.stubGetSessionsException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); // Stub the cache to return 1 activity CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode(scheduleActivities)); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetScheduleActivities( - signetsApi as SignetsAPIClientMock, session.shortName, []); + signetsApiMock, session.shortName, []); expect(manager.scheduleActivities, isNull); expect(manager.getScheduleActivities(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.scheduleActivities, isEmpty, reason: "The list of activities should be empty"); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); }); test("User authentication fails.", () async { // Stub the cache to return 0 activities - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode([])); // Load the sessions await manager.getSessions(); expect(manager.sessions, isNotEmpty); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); // Stub an authentication error reset(userRepository); @@ -736,21 +737,21 @@ void main() { expect(manager.getScheduleActivities(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.scheduleActivities, isEmpty, reason: "There isn't any activities saved in the cache so the list should be empty"); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNoMoreInteractions(signetsApi); + verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(userRepository); }); @@ -759,13 +760,13 @@ void main() { () async { // Stub the cache to return 1 activity CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode(scheduleActivities)); // Stub the SignetsAPI to return the same activity as the cache SignetsAPIClientMock.stubGetScheduleActivities( - signetsApi as SignetsAPIClientMock, + signetsApiMock, session.shortName, scheduleActivities); @@ -779,48 +780,48 @@ void main() { reason: "The list of activities should not have duplicata"); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getScheduleActivities( + signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), session: session.shortName), - cacheManager.update(CourseRepository.scheduleActivitiesCacheKey, + cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, jsonEncode(scheduleActivities)) ]); }); test("SignetsAPI raise a exception.", () async { // Stub the cache to return no activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey, jsonEncode([])); // Stub the SignetsAPI to throw an exception SignetsAPIClientMock.stubGetScheduleActivitiesException( - signetsApi as SignetsAPIClientMock, session.shortName, + signetsApiMock, session.shortName, exceptionToThrow: const ApiException(prefix: CourseRepository.tag)); expect(manager.scheduleActivities, isNull); expect(manager.getScheduleActivities(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.scheduleActivities, isEmpty, reason: "The list of activities should be empty"); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.scheduleActivitiesCacheKey), + cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getScheduleActivities( + signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), session: session.shortName), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); }); }); @@ -850,19 +851,19 @@ void main() { setUp(() { // Stub to simulate presence of session cache - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, []); + signetsApiMock, username, []); UserRepositoryMock.stubMonETSUser( userRepository as UserRepositoryMock, user); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, password); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("Sessions are loaded from cache", () async { @@ -875,11 +876,11 @@ void main() { reason: 'The sessions list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getSessions(username: username, password: password), - cacheManager.update( + signetsApiMock.getSessions(username: username, password: password), + cacheManagerMock.update( CourseRepository.sessionsCacheKey, jsonEncode(sessions)) ]); }); @@ -887,8 +888,8 @@ void main() { test("Trying to load sessions from cache but cache doesn't exist", () async { // Stub to simulate an exception when trying to get the sessions from the cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGetException(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGetException(cacheManagerMock, CourseRepository.sessionsCacheKey); expect(manager.sessions, isNull); @@ -899,24 +900,24 @@ void main() { expect(manager.sessions, []); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getSessions(username: username, password: password), - cacheManager.update(CourseRepository.sessionsCacheKey, jsonEncode([])) + signetsApiMock.getSessions(username: username, password: password), + cacheManagerMock.update(CourseRepository.sessionsCacheKey, jsonEncode([])) ]); }); test("SignetsAPI return another session", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving - reset(signetsApi as SignetsAPIClientMock); + reset(signetsApiMock); SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, sessions); + signetsApiMock, username, sessions); expect(manager.sessions, isNull); final results = await manager.getSessions(); @@ -927,20 +928,20 @@ void main() { reason: 'The sessions list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getSessions(username: username, password: password), - cacheManager.update( + signetsApiMock.getSessions(username: username, password: password), + cacheManagerMock.update( CourseRepository.sessionsCacheKey, jsonEncode(sessions)) ]); }); test("SignetsAPI return a session that already exists", () async { // Stub SignetsApi answer to test only the cache retrieving - reset(signetsApi as SignetsAPIClientMock); + reset(signetsApiMock); SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, sessions); + signetsApiMock, username, sessions); expect(manager.sessions, isNull); final results = await manager.getSessions(); @@ -951,24 +952,24 @@ void main() { reason: 'The sessions list should not have any duplicata..'); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getSessions(username: username, password: password), - cacheManager.update( + signetsApiMock.getSessions(username: username, password: password), + cacheManagerMock.update( CourseRepository.sessionsCacheKey, jsonEncode(sessions)) ]); }); test("SignetsAPI return an exception", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetSessionsException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); expect(manager.sessions, isNull); expect(manager.getSessions(), throwsA(isInstanceOf())); @@ -976,33 +977,33 @@ void main() { reason: 'The session list should be empty'); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getSessions(username: username, password: password), - analyticsService.logError(CourseRepository.tag, any, any, any) + signetsApiMock.getSessions(username: username, password: password), + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); verifyNever( - cacheManager.update(CourseRepository.sessionsCacheKey, any)); + cacheManagerMock.update(CourseRepository.sessionsCacheKey, any)); }); test("Cache update fail", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub to simulate exception when updating cache - CacheManagerMock.stubUpdateException(cacheManager as CacheManagerMock, + CacheManagerMock.stubUpdateException(cacheManagerMock, CourseRepository.sessionsCacheKey); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, sessions); + signetsApiMock, username, sessions); expect(manager.sessions, isNull); final results = await manager.getSessions(); @@ -1014,17 +1015,17 @@ void main() { 'The sessions list should now be loaded even if the caching fails.'); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getSessions(username: username, password: password) + signetsApiMock.getSessions(username: username, password: password) ]); }); test("UserRepository return an exception", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub UserRepository to throw a exception @@ -1037,33 +1038,33 @@ void main() { reason: 'The session list should be empty'); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.sessionsCacheKey), + cacheManagerMock.get(CourseRepository.sessionsCacheKey), userRepository.getPassword(), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNever(signetsApi.getSessions( + verifyNever(signetsApiMock.getSessions( username: anyNamed("username"), password: anyNamed("password"))); verifyNever( - cacheManager.update(CourseRepository.sessionsCacheKey, any)); + cacheManagerMock.update(CourseRepository.sessionsCacheKey, any)); }); test("Should not try to fetch from signets when offline", () async { - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); //Stub the networkingService to return no connectivity - reset(networkingService); - NetworkingServiceMock.stubHasConnectivity(networkingService, + reset(networkingServiceMock); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock, hasConnectivity: false); final sessionsCache = await manager.getSessions(); expect(sessionsCache, sessions); verifyNever( - signetsApi.getSessions(username: username, password: password)); + signetsApiMock.getSessions(username: username, password: password)); }); }); @@ -1107,14 +1108,14 @@ void main() { final sessions = [oldSession, active]; SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, sessions); + signetsApiMock, username, sessions); UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, password); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); await manager.getSessions(); @@ -1141,14 +1142,14 @@ void main() { final sessions = [oldSession, old]; SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, sessions); + signetsApiMock, username, sessions); UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, password); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); await manager.getSessions(); @@ -1175,14 +1176,14 @@ void main() { final sessions = [oldSession, active]; SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, sessions); + signetsApiMock, username, sessions); UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, password); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); await manager.getSessions(); @@ -1191,14 +1192,14 @@ void main() { test("there is no session", () async { SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, []); + signetsApiMock, username, []); UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, password); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); await manager.getSessions(); @@ -1275,27 +1276,27 @@ void main() { setUp(() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, "password"); // Stub some sessions SignetsAPIClientMock.stubGetSessions( - signetsApi as SignetsAPIClientMock, username, [session]); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + signetsApiMock, username, [session]); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("Courses are loaded from cache and cache is updated", () async { SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseWithGrade]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + signetsApiMock, username); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])); expect(manager.courses, isNull); @@ -1307,11 +1308,11 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - cacheManager.update( + signetsApiMock.getCourses(username: username, password: password), + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])) ]); }); @@ -1319,7 +1320,7 @@ void main() { test("Courses are only loaded from cache", () async { expect(manager.courses, isNull); CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([ courseWithGrade, @@ -1343,10 +1344,10 @@ void main() { ], reason: 'The courses list should now be loaded.'); - verifyInOrder([cacheManager.get(CourseRepository.coursesCacheKey)]); + verifyInOrder([cacheManagerMock.get(CourseRepository.coursesCacheKey)]); - verifyNoMoreInteractions(signetsApi); - verifyNoMoreInteractions(cacheManager); + verifyNoMoreInteractions(signetsApiMock); + verifyNoMoreInteractions(cacheManagerMock); verifyNoMoreInteractions(userRepository); }); @@ -1361,14 +1362,14 @@ void main() { title: 'Cours générique'); CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade, courseWithGradeDuplicate])); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseFetched, courseWithGradeDuplicate]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1379,11 +1380,11 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - cacheManager.update(CourseRepository.coursesCacheKey, + signetsApiMock.getCourses(username: username, password: password), + cacheManagerMock.update(CourseRepository.coursesCacheKey, jsonEncode([courseFetched, courseWithGradeDuplicate])) ]); }); @@ -1392,9 +1393,9 @@ void main() { () async { expect(manager.courses, isNull); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); CacheManagerMock.stubGetException( - cacheManager as CacheManagerMock, CourseRepository.coursesCacheKey); + cacheManagerMock, CourseRepository.coursesCacheKey); final results = await manager.getCourses(fromCacheOnly: true); @@ -1404,70 +1405,70 @@ void main() { reason: 'The courses list should be empty.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), ]); - verifyNoMoreInteractions(signetsApi); - verifyNoMoreInteractions(cacheManager); + verifyNoMoreInteractions(signetsApiMock); + verifyNoMoreInteractions(cacheManagerMock); }); test("Signets raised an exception while trying to recover courses", () async { - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); SignetsAPIClientMock.stubGetCoursesException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); expect(manager.courses, isNull); expect(manager.getCourses(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.courses, []); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - analyticsService.logError(CourseRepository.tag, any, any, any) + signetsApiMock.getCourses(username: username, password: password), + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNoMoreInteractions(signetsApi); - verifyNoMoreInteractions(cacheManager); + verifyNoMoreInteractions(signetsApiMock); + verifyNoMoreInteractions(cacheManagerMock); verifyNoMoreInteractions(userRepository); }); test("Student dropped out of a course, the course should disappear", () async { - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithoutGrade])); SignetsAPIClientMock.stubGetCoursesException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); expect(manager.courses, isNull); expect(manager.getCourses(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.courses, []); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - analyticsService.logError(CourseRepository.tag, any, any, any) + signetsApiMock.getCourses(username: username, password: password), + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNoMoreInteractions(signetsApi); - verifyNoMoreInteractions(cacheManager); + verifyNoMoreInteractions(signetsApiMock); + verifyNoMoreInteractions(cacheManagerMock); verifyNoMoreInteractions(userRepository); }); @@ -1498,14 +1499,14 @@ void main() { summary: summary); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseFetched]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); SignetsAPIClientMock.stubGetCourseSummary( - signetsApi as SignetsAPIClientMock, username, courseFetched, + signetsApiMock, username, courseFetched, summaryToReturn: summary); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); @@ -1517,13 +1518,13 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - signetsApi.getCourseSummary( + signetsApiMock.getCourses(username: username, password: password), + signetsApiMock.getCourseSummary( username: username, password: password, course: courseFetched), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseUpdated])) ]); }); @@ -1538,13 +1539,13 @@ void main() { title: 'Cours générique'); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseFetched]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); SignetsAPIClientMock.stubGetCourseSummaryException( - signetsApi as SignetsAPIClientMock, username, courseFetched); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + signetsApiMock, username, courseFetched); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); @@ -1556,13 +1557,13 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - signetsApi.getCourseSummary( + signetsApiMock.getCourses(username: username, password: password), + signetsApiMock.getCourseSummary( username: username, password: password, course: courseFetched), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseFetched])) ]); }); @@ -1570,14 +1571,14 @@ void main() { test("Cache update fails, should still return the list of courses", () async { SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseWithGrade]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + signetsApiMock, username); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])); CacheManagerMock.stubUpdateException( - cacheManager as CacheManagerMock, CourseRepository.coursesCacheKey); + cacheManagerMock, CourseRepository.coursesCacheKey); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1589,19 +1590,19 @@ void main() { 'The courses list should now be loaded even if the caching fails.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - cacheManager.update( + signetsApiMock.getCourses(username: username, password: password), + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])) ]); }); test("UserRepository return an exception", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); // Stub UserRepository to throw a exception @@ -1611,32 +1612,32 @@ void main() { expect(manager.sessions, isNull); expect(manager.getCourses(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.courses, [], reason: 'The courses list should be empty'); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNever(signetsApi.getCourses( + verifyNever(signetsApiMock.getCourses( username: anyNamed("username"), password: anyNamed("password"))); - verifyNever(cacheManager.update(CourseRepository.coursesCacheKey, any)); + verifyNever(cacheManagerMock.update(CourseRepository.coursesCacheKey, any)); }); test("Should force fromCacheOnly mode when user has no connectivity", () async { // Stub the cache to return 1 activity - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])); //Stub the networkingService to return no connectivity - reset(networkingService); - NetworkingServiceMock.stubHasConnectivity(networkingService, + reset(networkingServiceMock); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock, hasConnectivity: false); final coursesCache = await manager.getCourses(); @@ -1654,12 +1655,12 @@ void main() { title: 'Cours générique'); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseFetched]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, session: session); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); @@ -1671,13 +1672,13 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - signetsApi.getCourseReviews( + signetsApiMock.getCourses(username: username, password: password), + signetsApiMock.getCourseReviews( username: username, password: password, session: session), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseFetched])) ]); }); @@ -1713,12 +1714,12 @@ void main() { review: review); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseFetched]); SignetsAPIClientMock.stubGetCourseReviews( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, session: session, reviewsToReturn: [review]); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); @@ -1730,13 +1731,13 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - signetsApi.getCourseReviews( + signetsApiMock.getCourses(username: username, password: password), + signetsApiMock.getCourseReviews( username: username, password: password, session: session), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([updated])) ]); }); @@ -1752,12 +1753,12 @@ void main() { title: 'Cours générique'); SignetsAPIClientMock.stubGetCourses( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, coursesToReturn: [courseFetched]); SignetsAPIClientMock.stubGetCourseReviewsException( - signetsApi as SignetsAPIClientMock, username, + signetsApiMock, username, session: session); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); @@ -1769,22 +1770,22 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - cacheManager.get(CourseRepository.coursesCacheKey), + cacheManagerMock.get(CourseRepository.coursesCacheKey), userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourses(username: username, password: password), - signetsApi.getCourseReviews( + signetsApiMock.getCourses(username: username, password: password), + signetsApiMock.getCourseReviews( username: username, password: password, session: session), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseFetched])) ]); }); }); group("getCourseSummary - ", () { - Course course; + late Course course; - Course courseUpdated; + late Course courseUpdated; const String username = "username"; const String password = "password"; @@ -1792,7 +1793,7 @@ void main() { setUp(() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, - MonETSUser(domain: null, typeUsagerId: null, username: username)); + MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( userRepository as UserRepositoryMock, "password"); @@ -1831,12 +1832,12 @@ void main() { ])); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("CourseSummary is fetched and cache is updated", () async { SignetsAPIClientMock.stubGetCourseSummary( - signetsApi as SignetsAPIClientMock, username, course, + signetsApiMock, username, course, summaryToReturn: courseUpdated.summary); expect(manager.courses, isNull); @@ -1850,25 +1851,25 @@ void main() { verifyInOrder([ userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourseSummary( + signetsApiMock.getCourseSummary( username: username, password: password, course: course), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseUpdated])) ]); }); test("Course is updated on the repository", () async { - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([course])); SignetsAPIClientMock.stubGetCourseSummary( - signetsApi as SignetsAPIClientMock, username, course, + signetsApiMock, username, course, summaryToReturn: courseUpdated.summary); // Load a course await manager.getCourses(fromCacheOnly: true); - clearInteractions(cacheManager); - clearInteractions(signetsApi); + clearInteractions(cacheManagerMock); + clearInteractions(signetsApiMock); clearInteractions(userRepository); expect(manager.courses, [course]); @@ -1883,9 +1884,9 @@ void main() { verifyInOrder([ userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourseSummary( + signetsApiMock.getCourseSummary( username: username, password: password, course: course), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseUpdated])) ]); }); @@ -1893,7 +1894,7 @@ void main() { test("Signets raised an exception while trying to recover summary", () async { SignetsAPIClientMock.stubGetCourseSummaryException( - signetsApi as SignetsAPIClientMock, username, course); + signetsApiMock, username, course); expect(manager.courses, isNull); @@ -1902,18 +1903,18 @@ void main() { expect(manager.courses, isNull); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourseSummary( + signetsApiMock.getCourseSummary( username: username, password: password, course: course), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNoMoreInteractions(signetsApi); - verifyNoMoreInteractions(cacheManager); + verifyNoMoreInteractions(signetsApiMock); + verifyNoMoreInteractions(cacheManagerMock); verifyNoMoreInteractions(userRepository); }); @@ -1921,10 +1922,10 @@ void main() { "Cache update fails, should still return the course with its summary", () async { SignetsAPIClientMock.stubGetCourseSummary( - signetsApi as SignetsAPIClientMock, username, course, + signetsApiMock, username, course, summaryToReturn: courseUpdated.summary); CacheManagerMock.stubUpdateException( - cacheManager as CacheManagerMock, CourseRepository.coursesCacheKey); + cacheManagerMock, CourseRepository.coursesCacheKey); expect(manager.courses, isNull); final results = await manager.getCourseSummary(course); @@ -1938,17 +1939,17 @@ void main() { verifyInOrder([ userRepository.getPassword(), userRepository.monETSUser, - signetsApi.getCourseSummary( + signetsApiMock.getCourseSummary( username: username, password: password, course: course), - cacheManager.update( + cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseUpdated])) ]); }); test("UserRepository return an exception", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); // Stub UserRepository to throw a exception @@ -1961,26 +1962,26 @@ void main() { expect(manager.courses, isNull); await untilCalled( - analyticsService.logError(CourseRepository.tag, any, any, any)); + analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ userRepository.getPassword(), - analyticsService.logError(CourseRepository.tag, any, any, any) + analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); - verifyNoMoreInteractions(signetsApi); - verifyNoMoreInteractions(cacheManager); + verifyNoMoreInteractions(signetsApiMock); + verifyNoMoreInteractions(cacheManagerMock); }); test("Should not try to update course summary when offline", () async { //Stub the networkingService to return no connectivity - reset(networkingService); - NetworkingServiceMock.stubHasConnectivity(networkingService, + reset(networkingServiceMock); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock, hasConnectivity: false); final results = await manager.getCourseSummary(course); expect(results, course); - verifyNever(signetsApi.getCourseSummary( + verifyNever(signetsApiMock.getCourseSummary( username: username, password: password, course: course)); }); }); diff --git a/test/managers/settings_manager_test.dart b/test/managers/settings_manager_test.dart index 3ea16b4e4..4a3348d1a 100644 --- a/test/managers/settings_manager_test.dart +++ b/test/managers/settings_manager_test.dart @@ -12,25 +12,25 @@ import 'package:table_calendar/table_calendar.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/managers/settings_manager.dart'; -import 'package:notredame/core/services/analytics_service.dart'; import 'package:notredame/core/services/preferences_service.dart'; import 'package:notredame/core/services/remote_config_service.dart'; import '../helpers.dart'; +import '../mock/services/analytics_service_mock.dart'; import '../mock/services/preferences_service_mock.dart'; import '../mock/services/remote_config_service_mock.dart'; void main() { - late AnalyticsService analyticsService; + late AnalyticsServiceMock analyticsServiceMock; late RemoteConfigService remoteConfigService; - late PreferencesService preferencesService; + late PreferencesServiceMock preferencesServiceMock; late SettingsManager manager; group("SettingsManager - ", () { setUp(() async { // Setting up mocks setupLogger(); - analyticsService = setupAnalyticsServiceMock(); - preferencesService = setupPreferencesServiceMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); + preferencesServiceMock = setupPreferencesServiceMock(); remoteConfigService = setupRemoteConfigServiceMock(); await setupAppIntl(); @@ -46,29 +46,23 @@ void main() { test("validate default behaviour", () async { // Stubs the answer of the preferences services PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleStartWeekday, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleStartWeekday); PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleOtherWeekday, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleOtherWeekday); PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleCalendarFormat, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleCalendarFormat); PreferencesServiceMock.stubGetBool( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleShowTodayBtn, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleShowTodayBtn); PreferencesServiceMock.stubGetBool( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleListView, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleListView); PreferencesServiceMock.stubGetBool( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleShowWeekEvents, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleShowWeekEvents); RemoteConfigServiceMock.stubGetCalendarViewEnabled( remoteConfigService as RemoteConfigServiceMock); @@ -85,51 +79,51 @@ void main() { expect(result, expected); - verify(preferencesService + verify(preferencesServiceMock .getString(PreferencesFlag.scheduleStartWeekday)) .called(1); - verify(preferencesService + verify(preferencesServiceMock .getString(PreferencesFlag.scheduleOtherWeekday)) .called(1); - verify(preferencesService + verify(preferencesServiceMock .getString(PreferencesFlag.scheduleCalendarFormat)) .called(1); - verify(preferencesService.getBool(PreferencesFlag.scheduleShowTodayBtn)) + verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleShowTodayBtn)) .called(1); - verify(preferencesService.getBool(PreferencesFlag.scheduleListView)) + verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleListView)) .called(1); - verify(preferencesService + verify(preferencesServiceMock .getBool(PreferencesFlag.scheduleShowWeekEvents)) .called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); test("validate the loading of the settings", () async { // Stubs the answer of the preferences services PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleStartWeekday, toReturn: EnumToString.convertToString(StartingDayOfWeek.sunday)); PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleOtherWeekday, toReturn: EnumToString.convertToString(WeekDays.monday)); PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleCalendarFormat, toReturn: EnumToString.convertToString(CalendarFormat.month)); PreferencesServiceMock.stubGetBool( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleShowTodayBtn, toReturn: false); PreferencesServiceMock.stubGetBool( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleListView, toReturn: false); PreferencesServiceMock.stubGetBool( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleShowWeekEvents, toReturn: false); @@ -146,25 +140,25 @@ void main() { expect(result, expected); - verify(preferencesService + verify(preferencesServiceMock .getString(PreferencesFlag.scheduleOtherWeekday)) .called(1); - verify(preferencesService + verify(preferencesServiceMock .getString(PreferencesFlag.scheduleStartWeekday)) .called(1); - verify(preferencesService + verify(preferencesServiceMock .getString(PreferencesFlag.scheduleCalendarFormat)) .called(1); - verify(preferencesService.getBool(PreferencesFlag.scheduleShowTodayBtn)) + verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleShowTodayBtn)) .called(1); - verify(preferencesService.getBool(PreferencesFlag.scheduleListView)) + verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleListView)) .called(1); - verify(preferencesService + verify(preferencesServiceMock .getBool(PreferencesFlag.scheduleShowWeekEvents)) .called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); }); @@ -173,55 +167,55 @@ void main() { const flag = PreferencesFlag.theme; manager.setThemeMode(ThemeMode.light); - verify(preferencesService.setString( + verify(preferencesServiceMock.setString( PreferencesFlag.theme, ThemeMode.light.toString())) .called(1); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); manager.setThemeMode(ThemeMode.dark); - verify(preferencesService.setString( + verify(preferencesServiceMock.setString( PreferencesFlag.theme, ThemeMode.dark.toString())) .called(1); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); manager.setThemeMode(ThemeMode.system); - verify(preferencesService.setString( + verify(preferencesServiceMock.setString( PreferencesFlag.theme, ThemeMode.system.toString())) .called(1); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); test("validate default behaviour", () async { const flag = PreferencesFlag.theme; PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, flag, + preferencesServiceMock, flag, toReturn: ThemeMode.light.toString()); manager.themeMode; - await untilCalled(preferencesService.getString(flag)); + await untilCalled(preferencesServiceMock.getString(flag)); expect(manager.themeMode, ThemeMode.light); - verify(preferencesService.getString(flag)).called(2); + verify(preferencesServiceMock.getString(flag)).called(2); - verifyNoMoreInteractions(preferencesService); + verifyNoMoreInteractions(preferencesServiceMock); }); }); @@ -229,98 +223,98 @@ void main() { test("validate default behaviour", () async { const flag = PreferencesFlag.locale; PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.locale, toReturn: const Locale('fr').toString()); manager.setLocale('fr'); manager.locale; - verify(preferencesService.setString(PreferencesFlag.locale, 'fr')) + verify(preferencesServiceMock.setString(PreferencesFlag.locale, 'fr')) .called(1); - verify(preferencesService.getString(PreferencesFlag.locale)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.locale)).called(1); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); test("set french/english", () async { const flag = PreferencesFlag.locale; manager.setLocale('fr'); - verify(preferencesService.setString(PreferencesFlag.locale, 'fr')) + verify(preferencesServiceMock.setString(PreferencesFlag.locale, 'fr')) .called(1); - untilCalled(analyticsService.logEvent( + untilCalled(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); manager.setLocale('en'); - verify(preferencesService.setString(PreferencesFlag.locale, 'en')) + verify(preferencesServiceMock.setString(PreferencesFlag.locale, 'en')) .called(1); - untilCalled(analyticsService.logEvent( + untilCalled(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); test("default locale isn't set", () { const flag = PreferencesFlag.locale; - when((preferencesService as PreferencesServiceMock).getString(flag)) + when(preferencesServiceMock.getString(flag)) .thenAnswer((_) async => null); expect(manager.locale, const Locale('en')); - verify(preferencesService.getString(PreferencesFlag.locale)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.locale)).called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); }); test("fetch theme and locale", () async { PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, PreferencesFlag.locale, + preferencesServiceMock, PreferencesFlag.locale, toReturn: const Locale('fr').toString()); PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, PreferencesFlag.theme, + preferencesServiceMock, PreferencesFlag.theme, toReturn: 'ThemeMode.system'); await manager.fetchLanguageAndThemeMode(); - verify(preferencesService.getString(PreferencesFlag.theme)).called(1); - verify(preferencesService.getString(PreferencesFlag.locale)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.theme)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.locale)).called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); test("reset language and theme", () async { // Set local and theme PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, PreferencesFlag.locale, + preferencesServiceMock, PreferencesFlag.locale, toReturn: const Locale('fr').toString()); PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, PreferencesFlag.theme, + preferencesServiceMock, PreferencesFlag.theme, toReturn: 'ThemeMode.system'); await manager.fetchLanguageAndThemeMode(); @@ -341,97 +335,93 @@ void main() { test("setString", () async { const flag = PreferencesFlag.scheduleCalendarFormat; PreferencesServiceMock.stubSetString( - preferencesService as PreferencesServiceMock, flag); + preferencesServiceMock, flag); expect(await manager.setString(flag, "test"), true, reason: "setString should return true if the PreferenceService return true"); - untilCalled(analyticsService.logEvent( + untilCalled(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verify(preferencesService.setString(flag, any)); + verify(preferencesServiceMock.setString(flag, any)); }); test("setInt", () async { const flag = PreferencesFlag.aboutUsCard; PreferencesServiceMock.stubSetInt( - preferencesService as PreferencesServiceMock, flag); + preferencesServiceMock, flag); expect(await manager.setInt(flag, 0), true, reason: "setInt should return true if the PreferenceService return true"); - untilCalled(analyticsService.logEvent( + untilCalled(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verify(preferencesService.setInt(flag, any)); + verify(preferencesServiceMock.setInt(flag, any)); }); test("getString", () async { const flag = PreferencesFlag.scheduleCalendarFormat; PreferencesServiceMock.stubGetString( - preferencesService as PreferencesServiceMock, flag); + preferencesServiceMock, flag); expect(await manager.getString(flag), 'test', reason: "setString should return true if the PreferenceService return true"); - untilCalled(analyticsService.logEvent( + untilCalled(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verify(preferencesService.getString(flag)); + verify(preferencesServiceMock.getString(flag)); }); test("setBool", () async { const flag = PreferencesFlag.scheduleCalendarFormat; PreferencesServiceMock.stubSetBool( - preferencesService as PreferencesServiceMock, flag); + preferencesServiceMock, flag); expect(await manager.setBool(flag, true), true, reason: "setString should return true if the PreferenceService return true"); - untilCalled(analyticsService.logEvent( + untilCalled(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", any)) .called(1); - verify(preferencesService.setBool(flag, value: anyNamed("value"))); + verify(preferencesServiceMock.setBool(flag, value: anyNamed("value"))); }); group("Dashboard - ", () { test("validate default behaviour", () async { PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, - PreferencesFlag.aboutUsCard, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.aboutUsCard); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, - PreferencesFlag.scheduleCard, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.scheduleCard); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, - PreferencesFlag.progressBarCard, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.progressBarCard); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, - PreferencesFlag.gradesCard, - toReturn: null); + preferencesServiceMock, + PreferencesFlag.gradesCard); // Cards final Map expected = { @@ -447,40 +437,40 @@ void main() { expected, ); - verify(preferencesService.getInt(PreferencesFlag.broadcastCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.broadcastCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.aboutUsCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.aboutUsCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.scheduleCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.scheduleCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.progressBarCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.progressBarCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.gradesCard)).called(1); + verify(preferencesServiceMock.getInt(PreferencesFlag.gradesCard)).called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); test("validate the loading of the cards", () async { PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.broadcastCard, toReturn: 0); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.aboutUsCard, toReturn: 2); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.scheduleCard, toReturn: 3); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.progressBarCard, // ignore: avoid_redundant_argument_values toReturn: 1); PreferencesServiceMock.stubGetInt( - preferencesService as PreferencesServiceMock, + preferencesServiceMock, PreferencesFlag.gradesCard, toReturn: 4); @@ -498,18 +488,18 @@ void main() { expected, ); - verify(preferencesService.getInt(PreferencesFlag.broadcastCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.broadcastCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.aboutUsCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.aboutUsCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.scheduleCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.scheduleCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.progressBarCard)) + verify(preferencesServiceMock.getInt(PreferencesFlag.progressBarCard)) .called(1); - verify(preferencesService.getInt(PreferencesFlag.gradesCard)).called(1); + verify(preferencesServiceMock.getInt(PreferencesFlag.gradesCard)).called(1); - verifyNoMoreInteractions(preferencesService); - verifyNoMoreInteractions(analyticsService); + verifyNoMoreInteractions(preferencesServiceMock); + verifyNoMoreInteractions(analyticsServiceMock); }); }); }); diff --git a/test/managers/user_repository_test.dart b/test/managers/user_repository_test.dart index 4bdc89bb9..0c6e78ff6 100644 --- a/test/managers/user_repository_test.dart +++ b/test/managers/user_repository_test.dart @@ -20,29 +20,30 @@ import 'package:notredame/core/services/analytics_service.dart'; import 'package:notredame/core/services/networking_service.dart'; import '../helpers.dart'; import '../mock/managers/cache_manager_mock.dart'; +import '../mock/services/analytics_service_mock.dart'; import '../mock/services/flutter_secure_storage_mock.dart'; import '../mock/services/networking_service_mock.dart'; void main() { - late AnalyticsService analyticsService; + late AnalyticsServiceMock analyticsServiceMock; late MonETSAPIClient monETSApi; - late FlutterSecureStorageMock secureStorage; - late CacheManager cacheManager; + late FlutterSecureStorageMock secureStorageMock; + late CacheManagerMock cacheManagerMock; late SignetsAPIClient signetsApi; - late NetworkingServiceMock networkingService; + late NetworkingServiceMock networkingServiceMock; late UserRepository manager; group('UserRepository - ', () { setUp(() { // Setup needed service - analyticsService = setupAnalyticsServiceMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); monETSApi = setupMonETSApiMock(); - secureStorage = - setupFlutterSecureStorageMock() as FlutterSecureStorageMock; - cacheManager = setupCacheManagerMock(); + secureStorageMock = + setupFlutterSecureStorageMock(); + cacheManagerMock = setupCacheManagerMock(); signetsApi = setupSignetsApiMock(); - networkingService = setupNetworkingServiceMock() as NetworkingServiceMock; + networkingServiceMock = setupNetworkingServiceMock(); setupLogger(); manager = UserRepository(); @@ -53,7 +54,7 @@ void main() { unregister(); unregister(); unregister(); - clearInteractions(cacheManager); + clearInteractions(cacheManagerMock); unregister(); clearInteractions(signetsApi); unregister(); @@ -75,13 +76,13 @@ void main() { reason: "Check the authentication is successful"); // Verify the secureStorage is used - verify(secureStorage.write( + verify(secureStorageMock.write( key: UserRepository.usernameSecureKey, value: user.username)); - verify(secureStorage.write( + verify(secureStorageMock.write( key: UserRepository.passwordSecureKey, value: "")); // Verify the user id is set in the analytics - verify(analyticsService.setUserProperties( + verify(analyticsServiceMock.setUserProperties( userId: user.username, domain: user.domain)); expect(manager.monETSUser, user, @@ -98,17 +99,17 @@ void main() { reason: "The authentication failed so the result should be false"); // Verify the user id isn't set in the analytics - verify(analyticsService.logError(UserRepository.tag, any, any, any)) + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)) .called(1); // Verify the secureStorage isn't used - verifyNever(secureStorage.write( + verifyNever(secureStorageMock.write( key: UserRepository.usernameSecureKey, value: username)); - verifyNever(secureStorage.write( + verifyNever(secureStorageMock.write( key: UserRepository.passwordSecureKey, value: "")); // Verify the user id is set in the analytics - verifyNever(analyticsService.setUserProperties( + verifyNever(analyticsServiceMock.setUserProperties( userId: username, domain: anyNamed("domain"))); expect(manager.monETSUser, null, @@ -122,7 +123,7 @@ void main() { MonETSAPIClientMock.stubAuthenticate( monETSApi as MonETSAPIClientMock, user); - FlutterSecureStorageMock.stubWriteException(secureStorage, + FlutterSecureStorageMock.stubWriteException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -133,16 +134,16 @@ void main() { reason: "Check the authentication is successful"); // Verify the secureStorage is used - verify(secureStorage.write( + verify(secureStorageMock.write( key: UserRepository.usernameSecureKey, value: user.username)); // Verify the user id is set in the analytics - verify(analyticsService.setUserProperties( + verify(analyticsServiceMock.setUserProperties( userId: user.username, domain: anyNamed("domain"))); expect(manager.monETSUser, user); // Verify the secureStorage is deleted - verify(secureStorage.deleteAll()); + verify(secureStorageMock.deleteAll()); }); }); @@ -169,13 +170,13 @@ void main() { reason: "Check the authentication is successful"); // Verify the secureStorage is used - verify(secureStorage.write( + verify(secureStorageMock.write( key: UserRepository.usernameSecureKey, value: user.username)); - verify(secureStorage.write( + verify(secureStorageMock.write( key: UserRepository.passwordSecureKey, value: "")); // Verify the user id is set in the analytics - verify(analyticsService.setUserProperties( + verify(analyticsServiceMock.setUserProperties( userId: user.username, domain: user.domain)); }); @@ -197,17 +198,17 @@ void main() { reason: "The authentication failed so the result should be false"); // Verify the user id isn't set in the analytics - verify(analyticsService.logError(UserRepository.tag, any, any, any)) + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)) .called(1); // Verify the secureStorage isn't used - verifyNever(secureStorage.write( + verifyNever(secureStorageMock.write( key: UserRepository.usernameSecureKey, value: username)); - verifyNever(secureStorage.write( + verifyNever(secureStorageMock.write( key: UserRepository.passwordSecureKey, value: "")); // Verify the user id is set in the analytics - verifyNever(analyticsService.setUserProperties( + verifyNever(analyticsServiceMock.setUserProperties( userId: username, domain: anyNamed("domain"))); expect(manager.monETSUser, null, @@ -224,9 +225,9 @@ void main() { final MonETSUser user = MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); MonETSAPIClientMock.stubAuthenticate( @@ -236,10 +237,10 @@ void main() { reason: "Result should be true"); verifyInOrder([ - secureStorage.read(key: UserRepository.usernameSecureKey), - secureStorage.read(key: UserRepository.passwordSecureKey), + secureStorageMock.read(key: UserRepository.usernameSecureKey), + secureStorageMock.read(key: UserRepository.passwordSecureKey), monETSApi.authenticate(username: username, password: password), - analyticsService.setUserProperties( + analyticsServiceMock.setUserProperties( userId: username, domain: user.domain) ]); @@ -251,9 +252,9 @@ void main() { const String username = "username"; const String password = "password"; - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); MonETSAPIClientMock.stubAuthenticateException( @@ -263,10 +264,10 @@ void main() { reason: "Result should be false"); verifyInOrder([ - secureStorage.read(key: UserRepository.usernameSecureKey), - secureStorage.read(key: UserRepository.passwordSecureKey), + secureStorageMock.read(key: UserRepository.usernameSecureKey), + secureStorageMock.read(key: UserRepository.passwordSecureKey), monETSApi.authenticate(username: username, password: password), - analyticsService.logError(UserRepository.tag, any, any, any) + analyticsServiceMock.logError(UserRepository.tag, any, any, any) ]); expect(manager.monETSUser, null, @@ -275,20 +276,20 @@ void main() { test('credentials are not saved so the authentication should not be done', () async { - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: null); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: null); expect(await manager.silentAuthenticate(), isFalse, reason: "Result should be false"); verifyInOrder( - [secureStorage.read(key: UserRepository.usernameSecureKey)]); + [secureStorageMock.read(key: UserRepository.usernameSecureKey)]); - verifyNoMoreInteractions(secureStorage); + verifyNoMoreInteractions(secureStorageMock); verifyZeroInteractions(monETSApi); - verifyZeroInteractions(analyticsService); + verifyZeroInteractions(analyticsServiceMock); expect(manager.monETSUser, null, reason: @@ -302,7 +303,7 @@ void main() { MonETSAPIClientMock.stubAuthenticate( monETSApi as MonETSAPIClientMock, user); - FlutterSecureStorageMock.stubReadException(secureStorage, + FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -311,9 +312,9 @@ void main() { reason: "Result should be false"); verifyInOrder([ - secureStorage.read(key: UserRepository.usernameSecureKey), - secureStorage.deleteAll(), - analyticsService.logError(UserRepository.tag, any, any, any) + secureStorageMock.read(key: UserRepository.usernameSecureKey), + secureStorageMock.deleteAll(), + analyticsServiceMock.logError(UserRepository.tag, any, any, any) ]); }); }); @@ -325,16 +326,16 @@ void main() { expect(manager.monETSUser, null, reason: "The user shouldn't be available after a logout"); - verify(secureStorage.delete(key: UserRepository.usernameSecureKey)); - verify(secureStorage.delete(key: UserRepository.passwordSecureKey)); + verify(secureStorageMock.delete(key: UserRepository.usernameSecureKey)); + verify(secureStorageMock.delete(key: UserRepository.passwordSecureKey)); verifyNever( - analyticsService.logError(UserRepository.tag, any, any, any)); + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); test('Verify that localstorage is safely deleted if an exception occurs', () async { - FlutterSecureStorageMock.stubDeleteException(secureStorage, + FlutterSecureStorageMock.stubDeleteException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -343,9 +344,9 @@ void main() { expect(manager.monETSUser, null, reason: "The user shouldn't be available after a logout"); - verify(secureStorage.delete(key: UserRepository.usernameSecureKey)); - verify(secureStorage.deleteAll()); - verify(analyticsService.logError(UserRepository.tag, any, any, any)); + verify(secureStorageMock.delete(key: UserRepository.usernameSecureKey)); + verify(secureStorageMock.deleteAll()); + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); }); @@ -364,9 +365,9 @@ void main() { MonETSAPIClientMock.stubAuthenticate( monETSApi as MonETSAPIClientMock, user); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); expect(await manager.silentAuthenticate(), isTrue); @@ -375,10 +376,10 @@ void main() { reason: "Result should be 'password'"); verifyInOrder([ - secureStorage.read(key: UserRepository.usernameSecureKey), - secureStorage.read(key: UserRepository.passwordSecureKey), + secureStorageMock.read(key: UserRepository.usernameSecureKey), + secureStorageMock.read(key: UserRepository.passwordSecureKey), monETSApi.authenticate(username: username, password: password), - analyticsService.setUserProperties( + analyticsServiceMock.setUserProperties( userId: username, domain: user.domain) ]); }); @@ -394,20 +395,20 @@ void main() { MonETSAPIClientMock.stubAuthenticate( monETSApi as MonETSAPIClientMock, user); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); expect(await manager.getPassword(), password, reason: "Result should be 'password'"); verifyInOrder([ - analyticsService.logEvent(UserRepository.tag, any), - secureStorage.read(key: UserRepository.usernameSecureKey), - secureStorage.read(key: UserRepository.passwordSecureKey), + analyticsServiceMock.logEvent(UserRepository.tag, any), + secureStorageMock.read(key: UserRepository.usernameSecureKey), + secureStorageMock.read(key: UserRepository.passwordSecureKey), monETSApi.authenticate(username: username, password: password), - analyticsService.setUserProperties( + analyticsServiceMock.setUserProperties( userId: username, domain: user.domain) ]); }); @@ -420,9 +421,9 @@ void main() { MonETSAPIClientMock.stubAuthenticateException( monETSApi as MonETSAPIClientMock, username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); await manager.silentAuthenticate(); @@ -432,9 +433,9 @@ void main() { 'The authentication failed so an ApiException should be raised.'); await untilCalled( - analyticsService.logError(UserRepository.tag, any, any, any)); + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verify(analyticsService.logError(UserRepository.tag, any, any, any)) + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)) .called(1); }); @@ -448,7 +449,7 @@ void main() { MonETSAPIClientMock.stubAuthenticate( monETSApi as MonETSAPIClientMock, user); - FlutterSecureStorageMock.stubReadException(secureStorage, + FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.passwordSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -458,10 +459,10 @@ void main() { reason: "localStorage failed, should sent out a custom exception"); await untilCalled( - analyticsService.logError(UserRepository.tag, any, any, any)); + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verify(secureStorage.deleteAll()); - verify(analyticsService.logError(UserRepository.tag, any, any, any)); + verify(secureStorageMock.deleteAll()); + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); }); @@ -486,7 +487,7 @@ void main() { setUp(() async { // Stub to simulate presence of programs cache - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.programsCacheKey, jsonEncode(programs)); MonETSAPIClientMock.stubAuthenticate( @@ -503,7 +504,7 @@ void main() { signetsApi as SignetsAPIClientMock, username, []); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("Programs are loaded from cache", () async { @@ -515,16 +516,16 @@ void main() { expect(manager.programs, programs, reason: 'The programs list should now be loaded.'); - verify(cacheManager.get(UserRepository.programsCacheKey)); - verifyNoMoreInteractions(cacheManager); + verify(cacheManagerMock.get(UserRepository.programsCacheKey)); + verifyNoMoreInteractions(cacheManagerMock); }); test("Trying to load programs from cache but cache doesn't exist", () async { // Stub to simulate an exception when trying to get the programs from the cache - reset(cacheManager as CacheManagerMock); + reset(cacheManagerMock); CacheManagerMock.stubGetException( - cacheManager as CacheManagerMock, UserRepository.programsCacheKey); + cacheManagerMock, UserRepository.programsCacheKey); expect(manager.programs, isNull); final results = await manager.getPrograms(); @@ -533,16 +534,16 @@ void main() { expect(results, []); expect(manager.programs, []); - verify(cacheManager.get(UserRepository.programsCacheKey)); + verify(cacheManagerMock.get(UserRepository.programsCacheKey)); verify(manager.getPassword()); - verifyNever(cacheManager.update( + verifyNever(cacheManagerMock.update( UserRepository.programsCacheKey, jsonEncode(programs))); }); test("SignetsAPI return another program", () async { // Stub to simulate presence of program cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving @@ -558,16 +559,16 @@ void main() { expect(manager.programs, programs, reason: 'The programs list should now be loaded.'); - verify(cacheManager.get(UserRepository.programsCacheKey)); + verify(cacheManagerMock.get(UserRepository.programsCacheKey)); verify(manager.getPassword()); - verify(cacheManager.update( + verify(cacheManagerMock.update( UserRepository.programsCacheKey, jsonEncode(programs))); }); test("SignetsAPI return an exception", () async { // Stub to simulate presence of program cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving @@ -577,29 +578,29 @@ void main() { expect(manager.programs, isNull); expect(manager.getPrograms(), throwsA(isInstanceOf())); - await untilCalled(networkingService.hasConnectivity()); + await untilCalled(networkingServiceMock.hasConnectivity()); expect(manager.programs, [], reason: 'The programs list should be empty'); await untilCalled( - analyticsService.logError(UserRepository.tag, any, any, any)); + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verify(cacheManager.get(UserRepository.programsCacheKey)); + verify(cacheManagerMock.get(UserRepository.programsCacheKey)); verify(manager.getPassword()); - verify(analyticsService.logError(UserRepository.tag, any, any, any)); + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verifyNever(cacheManager.update(UserRepository.programsCacheKey, any)); + verifyNever(cacheManagerMock.update(UserRepository.programsCacheKey, any)); }); test("Cache update fail", () async { // Stub to simulate presence of program cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); // Stub to simulate exception when updating cache CacheManagerMock.stubUpdateException( - cacheManager as CacheManagerMock, UserRepository.programsCacheKey); + cacheManagerMock, UserRepository.programsCacheKey); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetPrograms( @@ -618,8 +619,8 @@ void main() { test("Should force fromCacheOnly mode when user has no connectivity", () async { //Stub the networkingService to return no connectivity - reset(networkingService); - NetworkingServiceMock.stubHasConnectivity(networkingService, + reset(networkingServiceMock); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock, hasConnectivity: false); final programsCache = await manager.getPrograms(); @@ -641,7 +642,7 @@ void main() { setUp(() async { // Stub to simulate presence of info cache - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); MonETSAPIClientMock.stubAuthenticate( @@ -658,7 +659,7 @@ void main() { signetsApi as SignetsAPIClientMock, username, null); // Stub to simulate that the user has an active internet connection - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); }); test("Info are loaded from cache", () async { @@ -669,16 +670,16 @@ void main() { expect(results, info); expect(manager.info, info, reason: 'The info should now be loaded.'); - verify(cacheManager.get(UserRepository.infoCacheKey)); - verifyNoMoreInteractions(cacheManager as CacheManagerMock); + verify(cacheManagerMock.get(UserRepository.infoCacheKey)); + verifyNoMoreInteractions(cacheManagerMock); verifyNoMoreInteractions(signetsApi as SignetsAPIClientMock); }); test("Trying to load info from cache but cache doesn't exist", () async { // Stub to simulate an exception when trying to get the info from the cache - reset(cacheManager as CacheManagerMock); + reset(cacheManagerMock); CacheManagerMock.stubGetException( - cacheManager as CacheManagerMock, UserRepository.infoCacheKey); + cacheManagerMock, UserRepository.infoCacheKey); expect(manager.info, isNull); final results = await manager.getInfo(); @@ -686,16 +687,16 @@ void main() { expect(results, isNull); expect(manager.info, isNull); - verify(cacheManager.get(UserRepository.infoCacheKey)); + verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(manager.getPassword()); verifyNever( - cacheManager.update(UserRepository.infoCacheKey, jsonEncode(info))); + cacheManagerMock.update(UserRepository.infoCacheKey, jsonEncode(info))); }); test("SignetsAPI return another info", () async { // Stub to simulate presence of info cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); // Stub SignetsApi answer to test only the cache retrieving @@ -716,9 +717,9 @@ void main() { expect(manager.info, anotherInfo, reason: 'The new info should now be loaded.'); - verify(cacheManager.get(UserRepository.infoCacheKey)); + verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(manager.getPassword()); - verify(cacheManager.update( + verify(cacheManagerMock.update( UserRepository.infoCacheKey, jsonEncode(anotherInfo))); }); @@ -736,16 +737,16 @@ void main() { expect(manager.info, info, reason: 'The info should not have any duplicata..'); - verify(cacheManager.get(UserRepository.infoCacheKey)); + verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(manager.getPassword()); verifyNever( - cacheManager.update(UserRepository.infoCacheKey, jsonEncode(info))); + cacheManagerMock.update(UserRepository.infoCacheKey, jsonEncode(info))); }); test("SignetsAPI return an exception", () async { // Stub to simulate presence of info cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); // Stub SignetsApi answer to test only the cache retrieving @@ -757,24 +758,24 @@ void main() { expect(manager.info, null, reason: 'The info should be empty'); await untilCalled( - analyticsService.logError(UserRepository.tag, any, any, any)); + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verify(cacheManager.get(UserRepository.infoCacheKey)); + verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(manager.getPassword()); - verify(analyticsService.logError(UserRepository.tag, any, any, any)); + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verifyNever(cacheManager.update(UserRepository.infoCacheKey, any)); + verifyNever(cacheManagerMock.update(UserRepository.infoCacheKey, any)); }); test("Cache update fail", () async { // Stub to simulate presence of session cache - reset(cacheManager as CacheManagerMock); - CacheManagerMock.stubGet(cacheManager as CacheManagerMock, + reset(cacheManagerMock); + CacheManagerMock.stubGet(cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); // Stub to simulate exception when updating cache CacheManagerMock.stubUpdateException( - cacheManager as CacheManagerMock, UserRepository.infoCacheKey); + cacheManagerMock, UserRepository.infoCacheKey); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetInfo( @@ -792,8 +793,8 @@ void main() { test("Should force fromCacheOnly mode when user has no connectivity", () async { //Stub the networkingService to return no connectivity - reset(networkingService); - NetworkingServiceMock.stubHasConnectivity(networkingService, + reset(networkingServiceMock); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock, hasConnectivity: false); final infoCache = await manager.getInfo(); @@ -807,9 +808,9 @@ void main() { const String username = "username"; const String password = "password"; - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); expect(await manager.wasPreviouslyLoggedIn(), isTrue); @@ -819,9 +820,9 @@ void main() { const String username = "username"; const String password = ""; - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); expect(await manager.wasPreviouslyLoggedIn(), isFalse); @@ -831,15 +832,15 @@ void main() { () async { const String username = "username"; - FlutterSecureStorageMock.stubRead(secureStorage, + FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); - FlutterSecureStorageMock.stubReadException(secureStorage, + FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.passwordSecureKey, exceptionToThrow: PlatformException(code: "bad key")); expect(await manager.wasPreviouslyLoggedIn(), isFalse); - verify(secureStorage.deleteAll()); - verify(analyticsService.logError(UserRepository.tag, any, any, any)); + verify(secureStorageMock.deleteAll()); + verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); }); }); diff --git a/test/mock/services/flutter_secure_storage_mock.dart b/test/mock/services/flutter_secure_storage_mock.dart index b1b961bc8..a3723bf4b 100644 --- a/test/mock/services/flutter_secure_storage_mock.dart +++ b/test/mock/services/flutter_secure_storage_mock.dart @@ -10,7 +10,7 @@ import 'flutter_secure_storage_mock.mocks.dart'; class FlutterSecureStorageMock extends MockFlutterSecureStorage { /// Stub the read function of [FlutterSecureStorage] static void stubRead(FlutterSecureStorageMock mock, - {required String key, required String valueToReturn}) { + {required String key, required String? valueToReturn}) { when(mock.read(key: key)).thenAnswer((_) async => valueToReturn); } diff --git a/test/viewmodels/choose_language_viewmodel_test.dart b/test/viewmodels/choose_language_viewmodel_test.dart index 0e02c4368..3132704da 100644 --- a/test/viewmodels/choose_language_viewmodel_test.dart +++ b/test/viewmodels/choose_language_viewmodel_test.dart @@ -73,16 +73,6 @@ void main() { expect(['English', 'Français'], languages); }); - - test('returns the languages with an exception', () async { - const AppIntl intlNull = null; - final ChooseLanguageViewModel viewModelWithInvalidIntl = - ChooseLanguageViewModel(intl: intlNull); - - expect( - () => viewModelWithInvalidIntl.languages, throwsNoSuchMethodError, - reason: "The getter 'settings_english' was called on null"); - }); }); }); } From 62008cc9572aa084b8d7908c624a136d2915f19e Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 17:38:38 -0500 Subject: [PATCH 18/62] Migrate ViewModel tests to null safety --- test/helpers.dart | 20 +- test/managers/user_repository_test.dart | 3 +- .../choose_language_viewmodel_test.dart | 27 +- test/viewmodels/dashboard_viewmodel_test.dart | 408 +++++++++--------- test/viewmodels/faq_viewmodel_test.dart | 6 +- test/viewmodels/feedback_viewmodel_test.dart | 12 +- .../grades_details_viewmodel_test.dart | 22 +- test/viewmodels/grades_viewmodel_test.dart | 64 +-- test/viewmodels/login_viewmodel_test.dart | 9 +- test/viewmodels/more_viewmodel_test.dart | 75 ++-- test/viewmodels/not_found_viewmodel_test.dart | 32 +- test/viewmodels/profile_viewmodel_test.dart | 69 +-- .../quick_links_viewmodel_test.dart | 19 +- .../schedule_settings_viewmodel_test.dart | 100 +++-- test/viewmodels/schedule_viewmodel_test.dart | 195 ++++----- test/viewmodels/settings_viewmodel_test.dart | 40 +- test/viewmodels/startup_viewmodel_test.dart | 39 +- .../web_link_card_viewmodel_test.dart | 37 +- 18 files changed, 584 insertions(+), 593 deletions(-) diff --git a/test/helpers.dart b/test/helpers.dart index bf5c2048f..66ed4d55d 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -119,7 +119,7 @@ AnalyticsServiceMock setupAnalyticsServiceMock() { } /// Load a mock of the [RiveAnimationService] -RiveAnimationService setupRiveAnimationServiceMock() { +RiveAnimationServiceMock setupRiveAnimationServiceMock() { unregister(); final service = RiveAnimationServiceMock(); @@ -129,7 +129,7 @@ RiveAnimationService setupRiveAnimationServiceMock() { } /// Load a mock of the [InternalInfoService] -InternalInfoService setupInternalInfoServiceMock() { +InternalInfoServiceMock setupInternalInfoServiceMock() { unregister(); final service = InternalInfoServiceMock(); @@ -179,7 +179,7 @@ AppWidgetService setupAppWidgetServiceMock() { } /// Load a mock of the [NavigationService] -NavigationService setupNavigationServiceMock() { +NavigationServiceMock setupNavigationServiceMock() { unregister(); final service = NavigationServiceMock(); @@ -189,7 +189,7 @@ NavigationService setupNavigationServiceMock() { } /// Load a mock of the [GithubApi] -GithubApi setupGithubApiMock() { +GithubApiMock setupGithubApiMock() { unregister(); final service = GithubApiMock(); @@ -209,7 +209,7 @@ FlutterSecureStorageMock setupFlutterSecureStorageMock() { } /// Load a mock of the [UserRepository] -UserRepository setupUserRepositoryMock() { +UserRepositoryMock setupUserRepositoryMock() { unregister(); final service = UserRepositoryMock(); @@ -255,7 +255,7 @@ PreferencesServiceMock setupPreferencesServiceMock() { } /// Load a mock of the [SettingsManager] -SettingsManager setupSettingsManagerMock() { +SettingsManagerMock setupSettingsManagerMock() { unregister(); final service = SettingsManagerMock(); @@ -265,7 +265,7 @@ SettingsManager setupSettingsManagerMock() { } /// Load a mock of the [CourseRepository] -CourseRepository setupCourseRepositoryMock() { +CourseRepositoryMock setupCourseRepositoryMock() { unregister(); final service = CourseRepositoryMock(); @@ -309,7 +309,7 @@ void setupInAppReviewMock([WidgetTester? tester]) { } /// Load a mock of the [LaunchUrlService] -LaunchUrlService setupLaunchUrlServiceMock() { +LaunchUrlServiceMock setupLaunchUrlServiceMock() { unregister(); final service = LaunchUrlServiceMock(); @@ -319,7 +319,7 @@ LaunchUrlService setupLaunchUrlServiceMock() { } /// Load a mock of the [RemoteConfigService] -RemoteConfigService setupRemoteConfigServiceMock() { +RemoteConfigServiceMock setupRemoteConfigServiceMock() { unregister(); final service = RemoteConfigServiceMock(); @@ -329,7 +329,7 @@ RemoteConfigService setupRemoteConfigServiceMock() { } /// Load a mock of the [QuickLinkRepository] -QuickLinkRepository setupQuickLinkRepositoryMock() { +QuickLinkRepositoryMock setupQuickLinkRepositoryMock() { unregister(); final repository = QuickLinkRepositoryMock(); diff --git a/test/managers/user_repository_test.dart b/test/managers/user_repository_test.dart index 0c6e78ff6..d96a5bc7f 100644 --- a/test/managers/user_repository_test.dart +++ b/test/managers/user_repository_test.dart @@ -656,7 +656,8 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetInfo( - signetsApi as SignetsAPIClientMock, username, null); + // ignore: cast_nullable_to_non_nullable + signetsApi as SignetsAPIClientMock, username, any as ProfileStudent); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); diff --git a/test/viewmodels/choose_language_viewmodel_test.dart b/test/viewmodels/choose_language_viewmodel_test.dart index 3132704da..8cf5407e6 100644 --- a/test/viewmodels/choose_language_viewmodel_test.dart +++ b/test/viewmodels/choose_language_viewmodel_test.dart @@ -11,18 +11,19 @@ import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/core/viewmodels/choose_language_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/settings_manager_mock.dart'; +import '../mock/services/navigation_service_mock.dart'; late ChooseLanguageViewModel viewModel; void main() { - late NavigationService navigationService; - late SettingsManager settingsManager; + late NavigationServiceMock navigationServiceMock; + late SettingsManagerMock settingsManagerMock; group("ChooseLanguageViewModel - ", () { setUp(() async { // Setting up mocks - navigationService = setupNavigationServiceMock(); - settingsManager = setupSettingsManagerMock(); + navigationServiceMock = setupNavigationServiceMock(); + settingsManagerMock = setupSettingsManagerMock(); final AppIntl intl = await setupAppIntl(); viewModel = ChooseLanguageViewModel(intl: intl); @@ -36,31 +37,31 @@ void main() { group("changeLanguage - ", () { test('can set language english', () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, PreferencesFlag.theme); + settingsManagerMock, PreferencesFlag.theme); viewModel.changeLanguage(0); - verify(settingsManager + verify(settingsManagerMock .setLocale(AppIntl.supportedLocales.first.languageCode)); - verify(navigationService.pop()); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.login)); + verify(navigationServiceMock.pop()); + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.login)); }); test('can set language français', () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, PreferencesFlag.theme); + settingsManagerMock, PreferencesFlag.theme); viewModel.changeLanguage(1); - verify(settingsManager + verify(settingsManagerMock .setLocale(AppIntl.supportedLocales.last.languageCode)); - verify(navigationService.pop()); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.login)); + verify(navigationServiceMock.pop()); + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.login)); }); test('throws an error when index does not exist', () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, PreferencesFlag.theme); + settingsManagerMock, PreferencesFlag.theme); expect(() => viewModel.changeLanguage(-1), throwsException, reason: "No valid language for the index -1 passed in parameters"); diff --git a/test/viewmodels/dashboard_viewmodel_test.dart b/test/viewmodels/dashboard_viewmodel_test.dart index d5548719a..748c7ff36 100644 --- a/test/viewmodels/dashboard_viewmodel_test.dart +++ b/test/viewmodels/dashboard_viewmodel_test.dart @@ -6,28 +6,26 @@ import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/constants/progress_bar_text_options.dart'; -import 'package:notredame/core/managers/course_repository.dart'; import 'package:notredame/core/managers/settings_manager.dart'; -import 'package:notredame/core/services/analytics_service.dart'; -import 'package:notredame/core/services/preferences_service.dart'; -import 'package:notredame/core/services/remote_config_service.dart'; import 'package:notredame/core/viewmodels/dashboard_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/course_repository_mock.dart'; import '../mock/managers/settings_manager_mock.dart'; +import '../mock/services/analytics_service_mock.dart'; import '../mock/services/in_app_review_service_mock.dart'; import '../mock/services/preferences_service_mock.dart'; import '../mock/services/remote_config_service_mock.dart'; void main() { - late PreferencesService preferenceService; - late SettingsManager settingsManager; - late DashboardViewModel viewModel; - late CourseRepository courseRepository; - late RemoteConfigService remoteConfigService; + late PreferencesServiceMock preferenceServiceMock; + late SettingsManagerMock settingsManagerMock; + late CourseRepositoryMock courseRepositoryMock; + late RemoteConfigServiceMock remoteConfigServiceMock; late PreferencesServiceMock preferencesServiceMock; late InAppReviewServiceMock inAppReviewServiceMock; - late AnalyticsService analyticsService; + late AnalyticsServiceMock analyticsServiceMock; + + late DashboardViewModel viewModel; final gen101 = CourseActivity( courseGroup: "GEN101", @@ -195,39 +193,36 @@ void main() { group("DashboardViewModel - ", () { setUp(() async { // Setting up mocks - courseRepository = setupCourseRepositoryMock(); - remoteConfigService = setupRemoteConfigServiceMock(); - settingsManager = setupSettingsManagerMock(); - preferenceService = setupPreferencesServiceMock(); - analyticsService = setupAnalyticsServiceMock(); + courseRepositoryMock = setupCourseRepositoryMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); + settingsManagerMock = setupSettingsManagerMock(); + preferenceServiceMock = setupPreferencesServiceMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); setupAppWidgetServiceMock(); - courseRepository = setupCourseRepositoryMock(); - preferencesServiceMock = - setupPreferencesServiceMock() as PreferencesServiceMock; + preferencesServiceMock = setupPreferencesServiceMock(); viewModel = DashboardViewModel(intl: await setupAppIntl()); CourseRepositoryMock.stubGetSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(2020)); RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastEn( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: ""); inAppReviewServiceMock = @@ -242,111 +237,110 @@ void main() { test('first load from cache than call SignetsAPI to get the courses', () async { CourseRepositoryMock.stubSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubGetSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); expect(await viewModel.futureToRunGrades(), courses); - await untilCalled(courseRepository.sessions); - await untilCalled(courseRepository.sessions); + await untilCalled(courseRepositoryMock.sessions); + await untilCalled(courseRepositoryMock.sessions); expect(viewModel.courses, courses); verifyInOrder([ - courseRepository.sessions, - courseRepository.sessions, - courseRepository.activeSessions, - courseRepository.activeSessions, - courseRepository.getCourses(fromCacheOnly: true), - courseRepository.getCourses(), + courseRepositoryMock.sessions, + courseRepositoryMock.sessions, + courseRepositoryMock.activeSessions, + courseRepositoryMock.activeSessions, + courseRepositoryMock.getCourses(fromCacheOnly: true), + courseRepositoryMock.getCourses(), ]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); test('Signets throw an error while trying to get courses', () async { setupFlutterToastMock(); CourseRepositoryMock.stubSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubGetSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesException( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); expect(await viewModel.futureToRunGrades(), courses, reason: "Even if SignetsAPI call fails, should return the cache contents"); - await untilCalled(courseRepository.sessions); - await untilCalled(courseRepository.sessions); + await untilCalled(courseRepositoryMock.sessions); + await untilCalled(courseRepositoryMock.sessions); expect(viewModel.courses, courses); verifyInOrder([ - courseRepository.sessions, - courseRepository.sessions, - courseRepository.activeSessions, - courseRepository.activeSessions, - courseRepository.getCourses(fromCacheOnly: true), - courseRepository.getCourses(), + courseRepositoryMock.sessions, + courseRepositoryMock.sessions, + courseRepositoryMock.activeSessions, + courseRepositoryMock.activeSessions, + courseRepositoryMock.getCourses(fromCacheOnly: true), + courseRepositoryMock.getCourses(), ]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); test('There is no session active', () async { CourseRepositoryMock.stubSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: []); CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: []); expect(await viewModel.futureToRunGrades(), [], reason: "Should return empty if there is no session active."); - await untilCalled(courseRepository.sessions); + await untilCalled(courseRepositoryMock.sessions); expect(viewModel.courses, []); verifyInOrder([ - courseRepository.sessions, - courseRepository.sessions, - courseRepository.getSessions(), - courseRepository.activeSessions, + courseRepositoryMock.sessions, + courseRepositoryMock.sessions, + courseRepositoryMock.getSessions(), + courseRepositoryMock.activeSessions, ]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); }); @@ -354,24 +348,24 @@ void main() { test("The initial cards are correctly loaded", () async { setupFlutterToastMock(); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesException( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetSessions( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await viewModel.futureToRun(); @@ -383,173 +377,171 @@ void main() { PreferencesFlag.progressBarCard ]); - verify(settingsManager.getDashboard()).called(1); - verify(settingsManager.getString(PreferencesFlag.progressBarText)) + verify(settingsManagerMock.getDashboard()).called(1); + verify(settingsManagerMock.getString(PreferencesFlag.progressBarText)) .called(1); - verify(settingsManager.dateTimeNow).called(2); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.dateTimeNow).called(2); + verifyNoMoreInteractions(settingsManagerMock); }); test("build the list todays activities sorted by time", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 8)); await viewModel.futureToRun(); - await untilCalled(courseRepository.getCoursesActivities()); + await untilCalled(courseRepositoryMock.getCoursesActivities()); expect(viewModel.todayDateEvents, todayActivities); - verify(courseRepository.getCoursesActivities()).called(1); + verify(courseRepositoryMock.getCoursesActivities()).called(1); - verify(courseRepository.getCoursesActivities(fromCacheOnly: true)) + verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepository.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(1); - verify(settingsManager.getDashboard()).called(1); + verify(settingsManagerMock.getDashboard()).called(1); }); test( "build the list todays activities (doesnt remove activity when pending completion)", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 11, 59)); await viewModel.futureToRun(); - await untilCalled(courseRepository.getCoursesActivities()); + await untilCalled(courseRepositoryMock.getCoursesActivities()); expect(viewModel.todayDateEvents, todayActivities); - verify(courseRepository.getCoursesActivities()).called(1); + verify(courseRepositoryMock.getCoursesActivities()).called(1); - verify(courseRepository.getCoursesActivities(fromCacheOnly: true)) + verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepository.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(1); - verify(settingsManager.getDashboard()).called(1); + verify(settingsManagerMock.getDashboard()).called(1); }); test("build the list todays activities (remove activity when finished)", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 12, 01)); await viewModel.futureToRun(); - await untilCalled(courseRepository.getCoursesActivities()); + await untilCalled(courseRepositoryMock.getCoursesActivities()); final activitiesFinishedCourse = List.from(todayActivities)..remove(gen101); expect(viewModel.todayDateEvents, activitiesFinishedCourse); - verify(courseRepository.getCoursesActivities()).called(1); + verify(courseRepositoryMock.getCoursesActivities()).called(1); - verify(courseRepository.getCoursesActivities(fromCacheOnly: true)) + verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepository.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(1); - verify(settingsManager.getDashboard()).called(1); + verify(settingsManagerMock.getDashboard()).called(1); }); test("build the list tomorrow activities sorted by time", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 8)); await viewModel.futureToRun(); - await untilCalled(courseRepository.getCoursesActivities()); + await untilCalled(courseRepositoryMock.getCoursesActivities()); expect(viewModel.tomorrowDateEvents, tomorrowActivities); - verify(courseRepository.getCoursesActivities()).called(1); + verify(courseRepositoryMock.getCoursesActivities()).called(1); - verify(courseRepository.getCoursesActivities(fromCacheOnly: true)) + verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepository.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(1); - verify(settingsManager.getDashboard()).called(1); + verify(settingsManagerMock.getDashboard()).called(1); }); test( "build the list todays activities with the right course activities (should not have labo A)", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesWithLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN101", - toReturn: null); + "GEN101"); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN102", - toReturn: null); + "GEN102"); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupB); @@ -566,25 +558,23 @@ void main() { "build the list todays activities with the right course activities (should not have labo B)", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesWithLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN101", - toReturn: null); + "GEN101"); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN102", - toReturn: null); + "GEN102"); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); @@ -601,28 +591,25 @@ void main() { "build the list todays activities with the right course activities (should have both labs)", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesWithLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN101", - toReturn: null); + "GEN101"); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN102", - toReturn: null); + "GEN102"); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", - toReturn: null); + "GEN103"); expect(await viewModel.removeLaboratoryGroup(activitiesWithLabs), activitiesWithLabs); @@ -632,42 +619,42 @@ void main() { () async { setupFlutterToastMock(); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); PreferencesServiceMock.stubException( - preferenceService as PreferencesServiceMock, + preferenceServiceMock, PreferencesFlag.broadcastCard); PreferencesServiceMock.stubException( - preferenceService as PreferencesServiceMock, + preferenceServiceMock, PreferencesFlag.aboutUsCard); PreferencesServiceMock.stubException( - preferenceService as PreferencesServiceMock, + preferenceServiceMock, PreferencesFlag.scheduleCard); PreferencesServiceMock.stubException( - preferenceService as PreferencesServiceMock, + preferenceServiceMock, PreferencesFlag.progressBarCard); await viewModel.futureToRun(); expect(viewModel.cardsToDisplay, []); - verify(settingsManager.getDashboard()).called(1); + verify(settingsManagerMock.getDashboard()).called(1); }); }); group("futureToRunSessionProgressBar - ", () { test("There is an active session", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(2020)); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, 0.5); @@ -676,13 +663,13 @@ void main() { test("Invalid date (Superior limit)", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(2020, 1, 20)); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, 1); @@ -691,13 +678,13 @@ void main() { test("Invalid date (Lower limit)", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime(2019, 12, 31)); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, 0); @@ -706,7 +693,7 @@ void main() { test("Active session is null", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, -1.0); @@ -717,10 +704,10 @@ void main() { "currentProgressBarText should be set to ProgressBarText.percentage when it is the first time changeProgressBarText is called", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); viewModel.changeProgressBarText(); - verify(settingsManager.setString(PreferencesFlag.progressBarText, + verify(settingsManagerMock.setString(PreferencesFlag.progressBarText, ProgressBarText.values[1].toString())) .called(1); }); @@ -729,11 +716,11 @@ void main() { "currentProgressBarText flag should be set to ProgressBarText.remainingDays when it is the second time changeProgressBarText is called", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); viewModel.changeProgressBarText(); viewModel.changeProgressBarText(); - verify(settingsManager.setString(PreferencesFlag.progressBarText, + verify(settingsManagerMock.setString(PreferencesFlag.progressBarText, ProgressBarText.values[2].toString())) .called(1); }); @@ -742,13 +729,13 @@ void main() { "currentProgressBarText flag should be set to ProgressBarText.daysElapsedWithTotalDays when it is the third time changeProgressBarText is called", () async { CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); viewModel.changeProgressBarText(); viewModel.changeProgressBarText(); viewModel.changeProgressBarText(); - verify(settingsManager.setString(PreferencesFlag.progressBarText, + verify(settingsManagerMock.setString(PreferencesFlag.progressBarText, ProgressBarText.values[0].toString())) .called(1); }); @@ -756,20 +743,20 @@ void main() { group("interact with cards - ", () { test("can hide a card and reset cards to default layout", () async { - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.progressBarCard); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); await viewModel.futureToRun(); @@ -777,7 +764,7 @@ void main() { viewModel.hideCard(PreferencesFlag.scheduleCard); await untilCalled( - settingsManager.setInt(PreferencesFlag.scheduleCard, -1)); + settingsManagerMock.setInt(PreferencesFlag.scheduleCard, -1)); expect(viewModel.cards, hiddenCardDashboard); expect(viewModel.cardsToDisplay, [ @@ -786,22 +773,22 @@ void main() { PreferencesFlag.progressBarCard ]); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "DashboardViewModel", "Deleting scheduleCard")); - verify(settingsManager.setInt(PreferencesFlag.scheduleCard, -1)) + verify(settingsManagerMock.setInt(PreferencesFlag.scheduleCard, -1)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.broadcastCard, 0)) + verify(settingsManagerMock.setInt(PreferencesFlag.broadcastCard, 0)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.aboutUsCard, 1)) + verify(settingsManagerMock.setInt(PreferencesFlag.aboutUsCard, 1)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.progressBarCard, 2)) + verify(settingsManagerMock.setInt(PreferencesFlag.progressBarCard, 2)) .called(1); // Call the setter. viewModel.setAllCardsVisible(); await untilCalled( - settingsManager.setInt(PreferencesFlag.progressBarCard, 3)); + settingsManagerMock.setInt(PreferencesFlag.progressBarCard, 3)); expect(viewModel.cards, dashboard); expect(viewModel.cardsToDisplay, [ @@ -812,41 +799,41 @@ void main() { ]); verify( - analyticsService.logEvent("DashboardViewModel", "Restoring cards")); - verify(settingsManager.getDashboard()).called(1); - verify(settingsManager.setInt(PreferencesFlag.broadcastCard, 0)) + analyticsServiceMock.logEvent("DashboardViewModel", "Restoring cards")); + verify(settingsManagerMock.getDashboard()).called(1); + verify(settingsManagerMock.setInt(PreferencesFlag.broadcastCard, 0)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.aboutUsCard, 1)) + verify(settingsManagerMock.setInt(PreferencesFlag.aboutUsCard, 1)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.scheduleCard, 2)) + verify(settingsManagerMock.setInt(PreferencesFlag.scheduleCard, 2)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.progressBarCard, 3)) + verify(settingsManagerMock.setInt(PreferencesFlag.progressBarCard, 3)) .called(1); - verify(settingsManager.getString(PreferencesFlag.progressBarText)) + verify(settingsManagerMock.getString(PreferencesFlag.progressBarText)) .called(2); - verify(settingsManager.dateTimeNow).called(3); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.dateTimeNow).called(3); + verifyNoMoreInteractions(settingsManagerMock); }); test("can set new order for cards", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.progressBarCard); await viewModel.futureToRun(); @@ -863,7 +850,7 @@ void main() { viewModel.setOrder(PreferencesFlag.progressBarCard, 0); await untilCalled( - settingsManager.setInt(PreferencesFlag.progressBarCard, 0)); + settingsManagerMock.setInt(PreferencesFlag.progressBarCard, 0)); expect(viewModel.cards, reorderedDashboard); expect(viewModel.cardsToDisplay, [ @@ -873,21 +860,21 @@ void main() { PreferencesFlag.scheduleCard ]); - verify(analyticsService.logEvent( + verify(analyticsServiceMock.logEvent( "DashboardViewModel", "Reordoring progressBarCard")); - verify(settingsManager.getDashboard()).called(1); - verify(settingsManager.setInt(PreferencesFlag.progressBarCard, 0)) + verify(settingsManagerMock.getDashboard()).called(1); + verify(settingsManagerMock.setInt(PreferencesFlag.progressBarCard, 0)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.broadcastCard, 1)) + verify(settingsManagerMock.setInt(PreferencesFlag.broadcastCard, 1)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.aboutUsCard, 2)) + verify(settingsManagerMock.setInt(PreferencesFlag.aboutUsCard, 2)) .called(1); - verify(settingsManager.setInt(PreferencesFlag.scheduleCard, 3)) + verify(settingsManagerMock.setInt(PreferencesFlag.scheduleCard, 3)) .called(1); - verify(settingsManager.getString(PreferencesFlag.progressBarText)) + verify(settingsManagerMock.getString(PreferencesFlag.progressBarText)) .called(1); - verify(settingsManager.dateTimeNow).called(2); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.dateTimeNow).called(2); + verifyNoMoreInteractions(settingsManagerMock); }); }); @@ -939,8 +926,7 @@ void main() { preferencesServiceMock, PreferencesFlag.ratingTimer, toReturn: day); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, PreferencesFlag.hasRatingBeenRequested, - toReturn: null); + preferencesServiceMock, PreferencesFlag.hasRatingBeenRequested); expect(await DashboardViewModel.launchInAppReview(), true); diff --git a/test/viewmodels/faq_viewmodel_test.dart b/test/viewmodels/faq_viewmodel_test.dart index 2f433fe8c..7f39739dc 100644 --- a/test/viewmodels/faq_viewmodel_test.dart +++ b/test/viewmodels/faq_viewmodel_test.dart @@ -13,13 +13,13 @@ import '../helpers.dart'; import '../mock/services/launch_url_service_mock.dart'; void main() { - late LaunchUrlServiceMock launchUrlService; + late LaunchUrlServiceMock launchUrlServiceMock; late FaqViewModel viewModel; group('FaqViewModel - ', () { setUp(() async { - launchUrlService = setupLaunchUrlServiceMock() as LaunchUrlServiceMock; + launchUrlServiceMock = setupLaunchUrlServiceMock(); setupSettingsManagerMock(); viewModel = FaqViewModel(); @@ -42,7 +42,7 @@ void main() { test('Calls launchInBrowser', () { viewModel.launchWebsite("https://clubapplets.ca/", Brightness.light); - verify(launchUrlService.launchInBrowser( + verify(launchUrlServiceMock.launchInBrowser( "https://clubapplets.ca/", Brightness.light)) .called(1); }); diff --git a/test/viewmodels/feedback_viewmodel_test.dart b/test/viewmodels/feedback_viewmodel_test.dart index e90d70035..0b1370b9d 100644 --- a/test/viewmodels/feedback_viewmodel_test.dart +++ b/test/viewmodels/feedback_viewmodel_test.dart @@ -28,11 +28,11 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); late GithubApiMock githubApiMock; - late PreferencesServiceMock preferencesServiceMock; - late AppIntl appIntl; late FeedbackViewModel viewModel; + + late AppIntl appIntl; const feedBackText = 'Notre-Dame bug report'; final file = File('bugReportTest.png'); final filePath = file.path.split('/').last; @@ -45,9 +45,9 @@ void main() { group('FeedbackViewModel - ', () { setUp(() async { setupNavigationServiceMock(); - githubApiMock = setupGithubApiMock() as GithubApiMock; + githubApiMock = setupGithubApiMock(); preferencesServiceMock = - setupPreferencesServiceMock() as PreferencesServiceMock; + setupPreferencesServiceMock(); appIntl = await setupAppIntl(); setupLogger(); @@ -60,7 +60,7 @@ void main() { }); group('sendFeedback - ', () { - Uint8List screenshotData; + late Uint8List screenshotData; setUp(() async { final ByteData bytes = await rootBundle @@ -73,7 +73,7 @@ void main() { setupFlutterToastMock(); await file.writeAsBytes(image.encodePng( - image.copyResize(image.decodeImage(screenshotData), width: 307))); + image.copyResize(image.decodeImage(screenshotData)!, width: 307))); await viewModel.sendFeedback( UserFeedback( diff --git a/test/viewmodels/grades_details_viewmodel_test.dart b/test/viewmodels/grades_details_viewmodel_test.dart index 83bfaab4e..7353835ad 100644 --- a/test/viewmodels/grades_details_viewmodel_test.dart +++ b/test/viewmodels/grades_details_viewmodel_test.dart @@ -14,8 +14,10 @@ import '../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); late AppIntl intl; + + late CourseRepositoryMock courseRepositoryMock; + late GradesDetailsViewModel viewModel; - late CourseRepository courseRepository; final CourseSummary courseSummary = CourseSummary( currentMark: 5, @@ -30,7 +32,7 @@ void main() { courseGroup: "02", title: "Laboratoire 1", weight: 10, - teacherMessage: null, + teacherMessage: '', ignore: false, mark: 24, correctedEvaluationOutOf: "35", @@ -45,7 +47,7 @@ void main() { courseGroup: "02", title: "Laboratoire 2", weight: 10, - teacherMessage: null, + teacherMessage: '', ignore: false, mark: 24, correctedEvaluationOutOf: "30", @@ -80,7 +82,7 @@ void main() { group("GradesDetailsViewModel - ", () { setUp(() async { // Setting up mocks - courseRepository = setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); intl = await setupAppIntl(); setupSettingsManagerMock(); @@ -96,7 +98,7 @@ void main() { group('FutureToRun - -', () { test('SignetsAPI gets the summary', () async { CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: courseWithSummary); await viewModel.futureToRun(); @@ -108,7 +110,7 @@ void main() { () async { setupFlutterToastMock(); CourseRepositoryMock.stubGetCourseSummaryException( - courseRepository as CourseRepositoryMock, courseWithoutSummary); + courseRepositoryMock, courseWithoutSummary); await viewModel.futureToRun(); expect(viewModel.course, courseWithoutSummary); @@ -120,7 +122,7 @@ void main() { () async { setupFlutterToastMock(); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: courseWithSummary); await viewModel.refresh(); @@ -130,15 +132,15 @@ void main() { test('Signets throw an error', () async { CourseRepositoryMock.stubGetCourseSummaryException( - courseRepository as CourseRepositoryMock, courseWithoutSummary); + courseRepositoryMock, courseWithoutSummary); setupFlutterToastMock(); await viewModel.refresh(); expect(viewModel.course, courseWithoutSummary); - verify(courseRepository.getCourseSummary(viewModel.course)); + verify(courseRepositoryMock.getCourseSummary(viewModel.course)); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); }); }); diff --git a/test/viewmodels/grades_viewmodel_test.dart b/test/viewmodels/grades_viewmodel_test.dart index ee07175e2..00ce7877d 100644 --- a/test/viewmodels/grades_viewmodel_test.dart +++ b/test/viewmodels/grades_viewmodel_test.dart @@ -14,8 +14,11 @@ import '../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - late CourseRepository courseRepository; late AppIntl intl; + + late CourseRepositoryMock courseRepositoryMock; + + late GradesViewModel viewModel; final Course courseSummer = Course( @@ -83,7 +86,7 @@ void main() { group('GradesViewModel -', () { setUp(() async { - courseRepository = setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); intl = await setupAppIntl(); setupSettingsManagerMock(); setupNavigationServiceMock(); @@ -101,42 +104,41 @@ void main() { test('first load from cache than call SignetsAPI to get the courses', () async { CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); expect(await viewModel.futureToRun(), coursesBySession); - await untilCalled(courseRepository.courses); + await untilCalled(courseRepositoryMock.courses); expect(viewModel.coursesBySession, coursesBySession); expect(viewModel.sessionOrder, sessionOrder); verifyInOrder([ - courseRepository.getCourses(fromCacheOnly: true), - courseRepository.getCourses(), - courseRepository.courses + courseRepositoryMock.getCourses(fromCacheOnly: true), + courseRepositoryMock.getCourses(), + courseRepositoryMock.courses ]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); test('Signets throw an error while trying to get courses', () async { CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesException( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); setupFlutterToastMock(); @@ -144,17 +146,17 @@ void main() { reason: "Even if SignetsAPI call fails, should return the cache contents"); - await untilCalled(courseRepository.getCourses()); + await untilCalled(courseRepositoryMock.getCourses()); expect(viewModel.coursesBySession, coursesBySession); expect(viewModel.sessionOrder, sessionOrder); verifyInOrder([ - courseRepository.getCourses(fromCacheOnly: true), - courseRepository.getCourses() + courseRepositoryMock.getCourses(fromCacheOnly: true), + courseRepositoryMock.getCourses() ]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); }); @@ -163,10 +165,10 @@ void main() { 'Call SignetsAPI to get the courses than reload the coursesBySession', () async { CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); await viewModel.refresh(); @@ -175,21 +177,20 @@ void main() { expect(viewModel.sessionOrder, sessionOrder); verifyInOrder( - [courseRepository.getCourses(), courseRepository.courses]); + [courseRepositoryMock.getCourses(), courseRepositoryMock.courses]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); test('Signets throw an error', () async { CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); setupFlutterToastMock(); @@ -198,13 +199,12 @@ void main() { expect(viewModel.coursesBySession, coursesBySession); expect(viewModel.sessionOrder, sessionOrder); - reset(courseRepository); + reset(courseRepositoryMock); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubGetCoursesException( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); await viewModel.refresh(); @@ -214,9 +214,9 @@ void main() { expect(viewModel.sessionOrder, sessionOrder); verifyInOrder( - [courseRepository.getCourses(), courseRepository.courses]); + [courseRepositoryMock.getCourses(), courseRepositoryMock.courses]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); }); }); diff --git a/test/viewmodels/login_viewmodel_test.dart b/test/viewmodels/login_viewmodel_test.dart index df2532840..0ee6b4302 100644 --- a/test/viewmodels/login_viewmodel_test.dart +++ b/test/viewmodels/login_viewmodel_test.dart @@ -10,6 +10,7 @@ import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/core/viewmodels/login_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/user_repository_mock.dart'; +import '../mock/services/navigation_service_mock.dart'; void main() { // Needed to support FlutterToast. @@ -20,7 +21,7 @@ void main() { const String passwordCodeValid = "password"; const String passwordCodeInvalid = ""; - late NavigationService navigationService; + late NavigationServiceMock navigationServiceMock; late UserRepositoryMock userRepositoryMock; late AppIntl appIntl; @@ -29,9 +30,9 @@ void main() { group('LoginViewModel - ', () { setUp(() async { - navigationService = setupNavigationServiceMock(); + navigationServiceMock = setupNavigationServiceMock(); setupFlutterSecureStorageMock(); - userRepositoryMock = setupUserRepositoryMock() as UserRepositoryMock; + userRepositoryMock = setupUserRepositoryMock(); setupLogger(); setupPreferencesServiceMock(); appIntl = await setupAppIntl(); @@ -110,7 +111,7 @@ void main() { await viewModel.authenticate(); verify( - navigationService.pushNamedAndRemoveUntil(RouterPaths.dashboard)); + navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.dashboard)); }); test( diff --git a/test/viewmodels/more_viewmodel_test.dart b/test/viewmodels/more_viewmodel_test.dart index f43b5cbac..c472256c2 100644 --- a/test/viewmodels/more_viewmodel_test.dart +++ b/test/viewmodels/more_viewmodel_test.dart @@ -12,13 +12,14 @@ import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/core/managers/user_repository.dart'; import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/core/services/preferences_service.dart'; -import 'package:notredame/core/services/remote_config_service.dart'; import 'package:notredame/core/viewmodels/more_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/cache_manager_mock.dart'; import '../mock/managers/course_repository_mock.dart'; import '../mock/managers/settings_manager_mock.dart'; import '../mock/managers/user_repository_mock.dart'; +import '../mock/services/navigation_service_mock.dart'; +import '../mock/services/preferences_service_mock.dart'; import '../mock/services/remote_config_service_mock.dart'; void main() { @@ -28,29 +29,31 @@ void main() { late CacheManagerMock cacheManagerMock; late SettingsManagerMock settingsManagerMock; late CourseRepositoryMock courseRepositoryMock; - late PreferencesService preferenceService; - late RemoteConfigService remoteConfigService; + late PreferencesServiceMock preferenceServiceMock; + late RemoteConfigServiceMock remoteConfigServiceMock; late UserRepositoryMock userRepositoryMock; - late NavigationService navigationService; + late NavigationServiceMock navigationServiceMock; - AppIntl appIntl; - MoreViewModel viewModel; + late AppIntl appIntl; + late MoreViewModel viewModel; + + final DateTime now = DateTime.now(); final List sessions = [ Session( name: 'Hivers 2XXX', shortName: 'H1', - deadlineCancellationASEQ: null, - deadlineCancellationWithoutRefundNewStudent: null, - deadlineCancellationWithRefund: null, - deadlineCancellationWithRefundNewStudent: null, - deadlineRegistration: null, - startDate: null, - startDateCancellationWithoutRefundNewStudent: null, - startDateCancellationWithRefund: null, - startDateRegistration: null, - endDate: null, - endDateCourses: null), + deadlineCancellationASEQ: now, + deadlineCancellationWithoutRefundNewStudent: now, + deadlineCancellationWithRefund: now, + deadlineCancellationWithRefundNewStudent: now, + deadlineRegistration: now, + startDate: now, + startDateCancellationWithoutRefundNewStudent: now, + startDateCancellationWithRefund: now, + startDateRegistration: now, + endDate: now, + endDateCourses: now), ]; final List coursesActivities = [ @@ -60,8 +63,8 @@ void main() { activityName: '', activityDescription: '', activityLocation: '', - startDateTime: null, - endDateTime: null), + startDateTime: now, + endDateTime: now.add(const Duration(hours: 1))), ]; final List courses = [ @@ -80,44 +83,44 @@ void main() { // Check if the cacheManager has been emptied out cacheManagerMock.empty(), // Check if preference manager is clear - preferenceService.clearWithoutPersistentKey(), + preferenceServiceMock.clearWithoutPersistentKey(), // Check if user repository logOut is called userRepositoryMock.logOut(), // Check if the settings manager has reset lang and theme and notified his listener settingsManagerMock.resetLanguageAndThemeMode(), ]); verifyNoMoreInteractions(cacheManagerMock); - verifyNoMoreInteractions(preferenceService); + verifyNoMoreInteractions(preferenceServiceMock); verifyNoMoreInteractions(userRepositoryMock); verifyNoMoreInteractions(settingsManagerMock); // Make sure that the registered cache - expect(courseRepositoryMock.sessions.length, 0, + expect(courseRepositoryMock.sessions!.length, 0, reason: 'has emptied out the sessions list'); - expect(courseRepositoryMock.coursesActivities.length, 0, + expect(courseRepositoryMock.coursesActivities!.length, 0, reason: 'has emptied out the courseActivities list'); - expect(courseRepositoryMock.courses.length, 0, + expect(courseRepositoryMock.courses!.length, 0, reason: 'has emptied out the courses list'); // Check if navigation has been rerouted to login page verifyInOrder([ - navigationService.pushNamedAndRemoveUntil( + navigationServiceMock.pushNamedAndRemoveUntil( RouterPaths.login, RouterPaths.chooseLanguage) ]); - verifyNoMoreInteractions(navigationService); + verifyNoMoreInteractions(navigationServiceMock); } group('MoreViewModel - ', () { setUp(() async { - cacheManagerMock = setupCacheManagerMock() as CacheManagerMock; - settingsManagerMock = setupSettingsManagerMock() as SettingsManagerMock; + cacheManagerMock = setupCacheManagerMock(); + settingsManagerMock = setupSettingsManagerMock(); courseRepositoryMock = - setupCourseRepositoryMock() as CourseRepositoryMock; - remoteConfigService = setupRemoteConfigServiceMock(); - preferenceService = setupPreferencesServiceMock(); - userRepositoryMock = setupUserRepositoryMock() as UserRepositoryMock; - navigationService = setupNavigationServiceMock(); + setupCourseRepositoryMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); + preferenceServiceMock = setupPreferencesServiceMock(); + userRepositoryMock = setupUserRepositoryMock(); + navigationServiceMock = setupNavigationServiceMock(); appIntl = await setupAppIntl(); setupLogger(); @@ -129,7 +132,7 @@ void main() { CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: coursesActivities); RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); }); tearDown(() { @@ -145,7 +148,7 @@ void main() { test('If the correct function have been called when logout occur', () async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); setupFlutterToastMock(); UserRepositoryMock.stubLogOut(userRepositoryMock); @@ -159,7 +162,7 @@ void main() { 'If an error occur from the cache manager that the logout function finishes out', () async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); setupFlutterToastMock(); CacheManagerMock.stubEmptyException(cacheManagerMock); diff --git a/test/viewmodels/not_found_viewmodel_test.dart b/test/viewmodels/not_found_viewmodel_test.dart index b0ba10a91..8c676beb8 100644 --- a/test/viewmodels/not_found_viewmodel_test.dart +++ b/test/viewmodels/not_found_viewmodel_test.dart @@ -10,12 +10,14 @@ import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/core/services/rive_animation_service.dart'; import 'package:notredame/core/viewmodels/not_found_viewmodel.dart'; import '../helpers.dart'; +import '../mock/services/analytics_service_mock.dart'; +import '../mock/services/navigation_service_mock.dart'; import '../mock/services/rive_animation_service_mock.dart'; void main() { - late NavigationService navigationService; - late RiveAnimationService riveAnimationService; - late AnalyticsService analyticsService; + late NavigationServiceMock navigationServiceMock; + late RiveAnimationServiceMock riveAnimationServiceMock; + late AnalyticsServiceMock analyticsServiceMock; late NotFoundViewModel viewModel; @@ -24,9 +26,9 @@ void main() { const String riveFileName = 'dot_jumping'; setUp(() async { - navigationService = setupNavigationServiceMock(); - riveAnimationService = setupRiveAnimationServiceMock(); - analyticsService = setupAnalyticsServiceMock(); + navigationServiceMock = setupNavigationServiceMock(); + riveAnimationServiceMock = setupRiveAnimationServiceMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); setupLogger(); viewModel = NotFoundViewModel(pageName: pageNotFoundPassed); @@ -43,7 +45,7 @@ void main() { const String pageTestCtor = "\testctor"; NotFoundViewModel(pageName: pageTestCtor); - verify(analyticsService.logEvent(NotFoundViewModel.tag, + verify(analyticsServiceMock.logEvent(NotFoundViewModel.tag, "An unknown page ($pageTestCtor) has been access from the app.")); }); }); @@ -53,7 +55,7 @@ void main() { viewModel.navigateToDashboard(); verify( - navigationService.pushNamedAndRemoveUntil(RouterPaths.dashboard)); + navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.dashboard)); }); }); @@ -76,7 +78,7 @@ void main() { final expectedArtboard = Artboard(); RiveAnimationServiceMock.stubLoadRiveFile( - riveAnimationService as RiveAnimationServiceMock, + riveAnimationServiceMock, 'dot_jumping', expectedArtboard); @@ -91,16 +93,16 @@ void main() { test('load the dot_jumping Rive animation successfuly', () async { await viewModel.loadRiveAnimation(); - verify(riveAnimationService.loadRiveFile(riveFileName: riveFileName)); + verify(riveAnimationServiceMock.loadRiveFile(riveFileName: riveFileName)); }); test('load file Rive animation with error', () async { RiveAnimationServiceMock.stubLoadRiveFileException( - riveAnimationService as RiveAnimationServiceMock); + riveAnimationServiceMock); await viewModel.loadRiveAnimation(); - verify(analyticsService.logError( + verify(analyticsServiceMock.logError( NotFoundViewModel.tag, "An Error has occurred during rive animation $riveFileName loading.", RiveAnimationServiceMock.loadException, @@ -113,17 +115,17 @@ void main() { final artboard = Artboard(); RiveAnimationServiceMock.stubLoadRiveFile( - riveAnimationService as RiveAnimationServiceMock, + riveAnimationServiceMock, 'dot_jumping', artboard); RiveAnimationServiceMock.stubAddControllerToAnimationException( - riveAnimationService as RiveAnimationServiceMock, artboard); + riveAnimationServiceMock, artboard); await viewModel.loadRiveAnimation(); viewModel.startRiveAnimation(); - verify(analyticsService.logError( + verify(analyticsServiceMock.logError( NotFoundViewModel.tag, "An Error has occured during rive animation start.", RiveAnimationServiceMock.startException, diff --git a/test/viewmodels/profile_viewmodel_test.dart b/test/viewmodels/profile_viewmodel_test.dart index 6c83462b2..4ff16acc6 100644 --- a/test/viewmodels/profile_viewmodel_test.dart +++ b/test/viewmodels/profile_viewmodel_test.dart @@ -5,14 +5,15 @@ import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/constants/programs_credits.dart'; -import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/core/managers/user_repository.dart'; import 'package:notredame/core/viewmodels/profile_viewmodel.dart'; import '../helpers.dart'; +import '../mock/managers/settings_manager_mock.dart'; import '../mock/managers/user_repository_mock.dart'; -late UserRepository userRepository; -late SettingsManager settingsManager; +late UserRepositoryMock userRepositoryMock; +late SettingsManagerMock settingsManagerMock; + late ProfileViewModel viewModel; void main() { @@ -60,7 +61,7 @@ void main() { group("ProfileViewModel - ", () { setUp(() async { // Setting up mocks - userRepository = setupUserRepositoryMock(); + userRepositoryMock = setupUserRepositoryMock(); setupAnalyticsServiceMock(); viewModel = ProfileViewModel(intl: await setupAppIntl()); @@ -74,71 +75,71 @@ void main() { test( "first load from cache then call SignetsAPI to get the latest events", () async { - UserRepositoryMock.stubGetInfo(userRepository as UserRepositoryMock); + UserRepositoryMock.stubGetInfo(userRepositoryMock); UserRepositoryMock.stubGetPrograms( - userRepository as UserRepositoryMock); + userRepositoryMock); expect(await viewModel.futureToRun(), []); verifyInOrder([ - userRepository.getInfo(fromCacheOnly: true), - userRepository.getPrograms(fromCacheOnly: true), - userRepository.getInfo(), + userRepositoryMock.getInfo(fromCacheOnly: true), + userRepositoryMock.getPrograms(fromCacheOnly: true), + userRepositoryMock.getInfo(), ]); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test("Signets throw an error while trying to get new events", () async { setupFlutterToastMock(); - UserRepositoryMock.stubGetInfo(userRepository as UserRepositoryMock, + UserRepositoryMock.stubGetInfo(userRepositoryMock, fromCacheOnly: true); UserRepositoryMock.stubGetInfoException( - userRepository as UserRepositoryMock, + userRepositoryMock, fromCacheOnly: false); - UserRepositoryMock.stubGetPrograms(userRepository as UserRepositoryMock, + UserRepositoryMock.stubGetPrograms(userRepositoryMock, fromCacheOnly: true); UserRepositoryMock.stubGetProgramsException( - userRepository as UserRepositoryMock, + userRepositoryMock, fromCacheOnly: false); expect(await viewModel.futureToRun(), [], reason: "Even if SignetsAPI fails we should receives a list."); verifyInOrder([ - userRepository.getInfo(fromCacheOnly: true), - userRepository.getPrograms(fromCacheOnly: true), - userRepository.getInfo(), + userRepositoryMock.getInfo(fromCacheOnly: true), + userRepositoryMock.getPrograms(fromCacheOnly: true), + userRepositoryMock.getInfo(), ]); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); }); group("info - ", () { test("build the info", () async { UserRepositoryMock.stubProfileStudent( - userRepository as UserRepositoryMock, + userRepositoryMock, toReturn: info); expect(viewModel.profileStudent, info); - verify(userRepository.info).called(1); + verify(userRepositoryMock.info).called(1); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); }); group("programs - ", () { test("build the list of programs", () async { - UserRepositoryMock.stubPrograms(userRepository as UserRepositoryMock, + UserRepositoryMock.stubPrograms(userRepositoryMock, toReturn: programs); expect(viewModel.programList, programs); - verify(userRepository.programs).called(2); + verify(userRepositoryMock.programs).called(2); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); }); @@ -170,7 +171,7 @@ void main() { ), ]; - UserRepositoryMock.stubPrograms(userRepository as UserRepositoryMock, + UserRepositoryMock.stubPrograms(userRepositoryMock, toReturn: testPrograms); // Create an instance of ProgramCredits @@ -181,7 +182,7 @@ void main() { // Calculate the expected progression based on the defined ProgramCredits final double expectedProgression = - (45 / programCredits.programsCredits['7694'] * 100).roundToDouble(); + (45 / programCredits.programsCredits['7694']! * 100).roundToDouble(); // Verify that the calculated progression matches the expected value expect(progression, expectedProgression); @@ -204,7 +205,7 @@ void main() { ), ]; - UserRepositoryMock.stubPrograms(userRepository as UserRepositoryMock, + UserRepositoryMock.stubPrograms(userRepositoryMock, toReturn: testPrograms); // Calculate the program progression @@ -218,24 +219,24 @@ void main() { group('refresh -', () { test('Call SignetsAPI to get the user info and programs', () async { UserRepositoryMock.stubProfileStudent( - userRepository as UserRepositoryMock, + userRepositoryMock, toReturn: info); - UserRepositoryMock.stubGetInfo(userRepository as UserRepositoryMock, + UserRepositoryMock.stubGetInfo(userRepositoryMock, toReturn: info); UserRepositoryMock.stubGetPrograms( - userRepository as UserRepositoryMock); + userRepositoryMock); await viewModel.refresh(); expect(viewModel.profileStudent, info); verifyInOrder([ - userRepository.getInfo(), - userRepository.getPrograms(), - userRepository.info, + userRepositoryMock.getInfo(), + userRepositoryMock.getPrograms(), + userRepositoryMock.info, ]); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); }); }); diff --git a/test/viewmodels/quick_links_viewmodel_test.dart b/test/viewmodels/quick_links_viewmodel_test.dart index 61d17c88a..71abbb2b1 100644 --- a/test/viewmodels/quick_links_viewmodel_test.dart +++ b/test/viewmodels/quick_links_viewmodel_test.dart @@ -12,18 +12,19 @@ import '../helpers.dart'; import '../mock/managers/quick_links_repository_mock.dart'; void main() { - late AppIntl intl; + late QuickLinkRepositoryMock quickLinkRepositoryMock; + late QuickLinksViewModel viewModel; - late QuickLinkRepository quickLinkRepository; // Sample data for tests + late AppIntl intl; late QuickLinkData quickLinkDataSample; late QuickLink quickLinkSample; group("QuickLinksViewModel - ", () { setUp(() async { // Setting up mocks - quickLinkRepository = setupQuickLinkRepositoryMock(); + quickLinkRepositoryMock = setupQuickLinkRepositoryMock(); intl = await setupAppIntl(); viewModel = QuickLinksViewModel(intl); @@ -38,11 +39,11 @@ void main() { group('getQuickLinks -', () { test('Should get quick links from cache', () async { QuickLinkRepositoryMock.stubGetQuickLinkDataFromCache( - quickLinkRepository as QuickLinkRepositoryMock, + quickLinkRepositoryMock, toReturn: [quickLinkDataSample]); QuickLinkRepositoryMock.stubGetDefaultQuickLinks( - quickLinkRepository as QuickLinkRepositoryMock, + quickLinkRepositoryMock, toReturn: [quickLinkSample]); final result = await viewModel.getQuickLinks(); @@ -53,10 +54,10 @@ void main() { test('Should return default quick links if cache is not initialized', () async { QuickLinkRepositoryMock.stubGetQuickLinkDataFromCacheException( - quickLinkRepository as QuickLinkRepositoryMock); + quickLinkRepositoryMock); QuickLinkRepositoryMock.stubGetDefaultQuickLinks( - quickLinkRepository as QuickLinkRepositoryMock, + quickLinkRepositoryMock, toReturn: [quickLinkSample]); final result = await viewModel.getQuickLinks(); @@ -101,11 +102,11 @@ void main() { group('futureToRun -', () { test('Should fetch and set quick links', () async { QuickLinkRepositoryMock.stubGetQuickLinkDataFromCache( - quickLinkRepository as QuickLinkRepositoryMock, + quickLinkRepositoryMock, toReturn: [quickLinkDataSample]); QuickLinkRepositoryMock.stubGetDefaultQuickLinks( - quickLinkRepository as QuickLinkRepositoryMock, + quickLinkRepositoryMock, toReturn: [quickLinkSample]); final result = await viewModel.futureToRun(); diff --git a/test/viewmodels/schedule_settings_viewmodel_test.dart b/test/viewmodels/schedule_settings_viewmodel_test.dart index aa47527a0..3a6216135 100644 --- a/test/viewmodels/schedule_settings_viewmodel_test.dart +++ b/test/viewmodels/schedule_settings_viewmodel_test.dart @@ -7,15 +7,15 @@ import 'package:table_calendar/table_calendar.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; -import 'package:notredame/core/managers/course_repository.dart'; import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/core/viewmodels/schedule_settings_viewmodel.dart'; import '../helpers.dart'; import '../mock/managers/course_repository_mock.dart'; import '../mock/managers/settings_manager_mock.dart'; -late SettingsManager settingsManager; -late CourseRepository courseRepository; +late SettingsManagerMock settingsManagerMock; +late CourseRepositoryMock courseRepositoryMock; + late ScheduleSettingsViewModel viewModel; void main() { @@ -110,8 +110,8 @@ void main() { []; group("ScheduleSettingsViewModel - ", () { setUp(() { - settingsManager = setupSettingsManagerMock(); - courseRepository = setupCourseRepositoryMock(); + settingsManagerMock = setupSettingsManagerMock(); + courseRepositoryMock = setupCourseRepositoryMock(); viewModel = ScheduleSettingsViewModel(); twoClassesWithLaboratoryABscheduleActivities @@ -129,11 +129,11 @@ void main() { "The settings are correctly loaded and sets (if no schedule activities present to use)", () async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: []); expect(await viewModel.futureToRun(), settings); @@ -144,32 +144,31 @@ void main() { expect(viewModel.showTodayBtn, settings[PreferencesFlag.scheduleShowTodayBtn]); - verify(settingsManager.getScheduleSettings()).called(1); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.getScheduleSettings()).called(1); + verifyNoMoreInteractions(settingsManagerMock); - verify(courseRepository.getScheduleActivities()).called(1); - verifyNoMoreInteractions(courseRepository); + verify(courseRepositoryMock.getScheduleActivities()).called(1); + verifyNoMoreInteractions(courseRepositoryMock); }); test( "If there is one valid class which has grouped laboratory, we parse it and store it (None selected)", () async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); final courseAcronymWithLaboratory = classOneWithLaboratoryABscheduleActivities.first.courseAcronym; SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - courseAcronymWithLaboratory, - toReturn: null); + courseAcronymWithLaboratory); expect(await viewModel.futureToRun(), settings); expect( @@ -178,27 +177,27 @@ void main() { true); expect( viewModel - .scheduleActivitiesByCourse[courseAcronymWithLaboratory].length, + .scheduleActivitiesByCourse[courseAcronymWithLaboratory]!.length, 2); expect( viewModel.selectedScheduleActivity .containsKey(courseAcronymWithLaboratory), false); - verify(courseRepository.getScheduleActivities()).called(1); - verifyNoMoreInteractions(courseRepository); + verify(courseRepositoryMock.getScheduleActivities()).called(1); + verifyNoMoreInteractions(courseRepositoryMock); - verify(settingsManager.getDynamicString(any, any)).called(1); + verify(settingsManagerMock.getDynamicString(any, any)).called(1); }); test( "If there is two valid class which has grouped laboratory, we store both (First => none selected, Second => group A selected)", () async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: twoClassesWithLaboratoryABscheduleActivities); final firstCourseAcronymWithLab = @@ -208,12 +207,11 @@ void main() { classTwoWithLaboratoryABscheduleActivities.first.courseAcronym; SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - firstCourseAcronymWithLab, - toReturn: null); + firstCourseAcronymWithLab); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, secondCourseAcronymWithLab, toReturn: ActivityCode.labGroupA); @@ -222,11 +220,11 @@ void main() { expect(viewModel.scheduleActivitiesByCourse.keys.length, 2); expect( viewModel - .scheduleActivitiesByCourse[firstCourseAcronymWithLab].length, + .scheduleActivitiesByCourse[firstCourseAcronymWithLab]!.length, 2); expect( viewModel - .scheduleActivitiesByCourse[secondCourseAcronymWithLab].length, + .scheduleActivitiesByCourse[secondCourseAcronymWithLab]!.length, 2); expect( viewModel.selectedScheduleActivity @@ -241,39 +239,39 @@ void main() { classTwoWithLaboratoryABscheduleActivities.firstWhere( (element) => element.activityCode == ActivityCode.labGroupA)); - verify(courseRepository.getScheduleActivities()).called(1); - verifyNoMoreInteractions(courseRepository); + verify(courseRepositoryMock.getScheduleActivities()).called(1); + verifyNoMoreInteractions(courseRepositoryMock); - verify(settingsManager.getDynamicString(any, any)).called(2); + verify(settingsManagerMock.getDynamicString(any, any)).called(2); }); }); group("setter calendarFormat - ", () { test("calendarFormat is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleCalendarFormat); // Call the setter. viewModel.calendarFormat = CalendarFormat.twoWeeks; - await untilCalled(settingsManager.setString( + await untilCalled(settingsManagerMock.setString( PreferencesFlag.scheduleCalendarFormat, any)); expect(viewModel.calendarFormat, CalendarFormat.twoWeeks); expect(viewModel.isBusy, false); - verify(settingsManager.setString( + verify(settingsManagerMock.setString( PreferencesFlag.scheduleCalendarFormat, any)) .called(1); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("setter calendarView - ", () { test("calendarView is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleListView); const expected = true; @@ -282,21 +280,21 @@ void main() { viewModel.toggleCalendarView = expected; await untilCalled( - settingsManager.setBool(PreferencesFlag.scheduleListView, any)); + settingsManagerMock.setBool(PreferencesFlag.scheduleListView, any)); expect(viewModel.toggleCalendarView, true); expect(viewModel.isBusy, false); - verify(settingsManager.setBool(PreferencesFlag.scheduleListView, any)) + verify(settingsManagerMock.setBool(PreferencesFlag.scheduleListView, any)) .called(1); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("setter scheduleShowWeekendDays - ", () { test("scheduleShowWeekendDays is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleShowWeekendDays); const expected = true; @@ -305,45 +303,45 @@ void main() { viewModel.showWeekendDays = expected; - await untilCalled(settingsManager.setBool( + await untilCalled(settingsManagerMock.setBool( PreferencesFlag.scheduleShowWeekendDays, any)); expect(viewModel.showWeekendDays, true); expect(viewModel.isBusy, false); - verify(settingsManager.setBool( + verify(settingsManagerMock.setBool( PreferencesFlag.scheduleShowWeekendDays, any)) .called(1); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("setter startingDayOfWeek - ", () { test("startingDayOfWeek is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleStartWeekday); // Call the setter. viewModel.startingDayOfWeek = StartingDayOfWeek.friday; - await untilCalled(settingsManager.setString( + await untilCalled(settingsManagerMock.setString( PreferencesFlag.scheduleStartWeekday, any)); expect(viewModel.startingDayOfWeek, StartingDayOfWeek.friday); expect(viewModel.isBusy, false); - verify(settingsManager.setString( + verify(settingsManagerMock.setString( PreferencesFlag.scheduleStartWeekday, any)) .called(1); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("setter showTodayBtn - ", () { test("showTodayBtn is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleStartWeekday); const expected = false; @@ -352,15 +350,15 @@ void main() { viewModel.showTodayBtn = expected; await untilCalled( - settingsManager.setBool(PreferencesFlag.scheduleShowTodayBtn, any)); + settingsManagerMock.setBool(PreferencesFlag.scheduleShowTodayBtn, any)); expect(viewModel.showTodayBtn, expected); expect(viewModel.isBusy, false); - verify(settingsManager.setBool( + verify(settingsManagerMock.setBool( PreferencesFlag.scheduleShowTodayBtn, any)) .called(1); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(settingsManagerMock); }); }); }); diff --git a/test/viewmodels/schedule_viewmodel_test.dart b/test/viewmodels/schedule_viewmodel_test.dart index f5baa1631..6a4adc63a 100644 --- a/test/viewmodels/schedule_viewmodel_test.dart +++ b/test/viewmodels/schedule_viewmodel_test.dart @@ -14,8 +14,9 @@ import '../helpers.dart'; import '../mock/managers/course_repository_mock.dart'; import '../mock/managers/settings_manager_mock.dart'; -late CourseRepository courseRepository; -late SettingsManager settingsManager; +late CourseRepositoryMock courseRepositoryMock; +late SettingsManagerMock settingsManagerMock; + late ScheduleViewModel viewModel; void main() { @@ -242,8 +243,8 @@ void main() { group("ScheduleViewModel - ", () { setUp(() async { // Setting up mocks - courseRepository = setupCourseRepositoryMock(); - settingsManager = setupSettingsManagerMock(); + courseRepositoryMock = setupCourseRepositoryMock(); + settingsManagerMock = setupSettingsManagerMock(); viewModel = ScheduleViewModel(intl: await setupAppIntl()); }); @@ -258,68 +259,65 @@ void main() { "first load from cache than call SignetsAPI to get the latest events", () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); expect(await viewModel.futureToRun(), []); verifyInOrder([ - courseRepository.getCoursesActivities(fromCacheOnly: true), - courseRepository.getCoursesActivities() + courseRepositoryMock.getCoursesActivities(fromCacheOnly: true), + courseRepositoryMock.getCoursesActivities() ]); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); test("Signets throw an error while trying to get new events", () async { setupFlutterToastMock(); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivitiesException( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); expect(await viewModel.futureToRun(), [], reason: "Even if SignetsAPI fails we should receives a list."); // Await until the call to get the activities from signets is sent - await untilCalled(courseRepository.getCoursesActivities()); + await untilCalled(courseRepositoryMock.getCoursesActivities()); verifyInOrder([ - courseRepository.getCoursesActivities(fromCacheOnly: true), - courseRepository.getCoursesActivities() + courseRepositoryMock.getCoursesActivities(fromCacheOnly: true), + courseRepositoryMock.getCoursesActivities() ]); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("coursesActivities - ", () { test("build the list of activities sort by date", () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); final expected = { @@ -329,21 +327,21 @@ void main() { expect(viewModel.coursesActivities, expected); - verify(courseRepository.coursesActivities).called(2); + verify(courseRepositoryMock.coursesActivities).called(2); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); test( 'scheduleActivityIsSelected returns true when activityDescription is not labA or labB', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); @@ -370,14 +368,13 @@ void main() { 'scheduleActivityIsSelected returns true when the course does not have an activity', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - classOneWithLaboratoryABscheduleActivities.first.courseAcronym, - toReturn: null); + classOneWithLaboratoryABscheduleActivities.first.courseAcronym); await viewModel.assignScheduleActivities([]); @@ -388,7 +385,7 @@ void main() { 'scheduleActivityIsSelected returns false when there is no activity selected', () async { SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, classOneWithLaboratoryABscheduleActivities.first.courseAcronym, toReturn: ActivityCode.labGroupA); @@ -403,7 +400,7 @@ void main() { 'scheduleActivityIsSelected returns true when the courseGroup has an activity selected', () async { SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, classOneWithLaboratoryABscheduleActivities.first.courseAcronym, toReturn: ActivityCode.labGroupA); @@ -418,38 +415,38 @@ void main() { group("coursesActivitiesFor - ", () { test("Get the correct list of activities for the specified day", () { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); final expected = [gen102, gen103]; expect(viewModel.coursesActivitiesFor(DateTime(2020, 1, 2)), expected); - verify(courseRepository.coursesActivities).called(2); + verify(courseRepositoryMock.coursesActivities).called(2); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); test("If the day doesn't have any events, return an empty list.", () { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); expect(viewModel.coursesActivitiesFor(DateTime(2020, 1, 3)), isEmpty, reason: "There is no events for the 3rd Jan on activities"); - verify(courseRepository.coursesActivities).called(2); + verify(courseRepositoryMock.coursesActivities).called(2); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("selectedDateEvents", () { test("The events of the date currently selected are return", () { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); final expected = [gen102, gen103]; @@ -457,17 +454,17 @@ void main() { // Setting up the viewmodel viewModel.coursesActivities; viewModel.selectedDate = DateTime(2020, 1, 2); - clearInteractions(courseRepository); + clearInteractions(courseRepositoryMock); expect(viewModel.selectedDateEvents(viewModel.selectedDate), expected); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); test("The events of the date currently selected are return", () { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); final expected = []; @@ -475,12 +472,12 @@ void main() { // Setting up the viewmodel viewModel.coursesActivities; viewModel.selectedDate = DateTime(2020, 1, 3); - clearInteractions(courseRepository); + clearInteractions(courseRepositoryMock); expect(viewModel.selectedDateEvents(viewModel.selectedDate), expected); - verifyNoMoreInteractions(courseRepository); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(courseRepositoryMock); + verifyNoMoreInteractions(settingsManagerMock); }); }); @@ -494,7 +491,7 @@ void main() { test('selectedWeekEvents for starting day sunday', () { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: weekOfActivities); final expected = { @@ -510,17 +507,17 @@ void main() { // Setting up the viewmodel viewModel.coursesActivities; viewModel.selectedDate = DateTime(2020, 1, 8); - clearInteractions(courseRepository); + clearInteractions(courseRepositoryMock); expect(viewModel.selectedWeekEvents(), expected); }); test('selectedWeekEvents for starting day monday', () async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settingsStartingDayMonday); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: weekOfActivities); final expected = { @@ -536,17 +533,17 @@ void main() { viewModel.coursesActivities; viewModel.selectedDate = DateTime(2020, 1, 7); await viewModel.loadSettings(); - clearInteractions(courseRepository); + clearInteractions(courseRepositoryMock); expect(viewModel.selectedWeekEvents(), expected); }); test('selectedWeekEvents for starting day saturday', () async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settingsStartingDaySaturday); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: weekOfActivities); final expected = { @@ -562,7 +559,7 @@ void main() { viewModel.coursesActivities; viewModel.selectedDate = DateTime(2020, 1, 7); await viewModel.loadSettings(); - clearInteractions(courseRepository); + clearInteractions(courseRepositoryMock); expect(viewModel.selectedWeekEvents(), expected); }); @@ -573,7 +570,7 @@ void main() { 'Call SignetsAPI to get the coursesActivities than reload the coursesActivities', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); await viewModel.refresh(); @@ -586,19 +583,19 @@ void main() { expect(viewModel.coursesActivities, expected); verifyInOrder([ - courseRepository.getCoursesActivities(), - courseRepository.coursesActivities, - courseRepository.coursesActivities + courseRepositoryMock.getCoursesActivities(), + courseRepositoryMock.coursesActivities, + courseRepositoryMock.coursesActivities ]); - verifyNoMoreInteractions(courseRepository); + verifyNoMoreInteractions(courseRepositoryMock); }); }); group('loadSettings -', () { test('calendarFormat changing', () async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month }); @@ -606,15 +603,11 @@ void main() { await viewModel.loadSettings(); expect(viewModel.calendarFormat, CalendarFormat.month); - verify(settingsManager.getScheduleSettings()).called(1); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.getScheduleSettings()).called(1); + verifyNoMoreInteractions(settingsManagerMock); }); test('assignScheduleActivities - format the schedule activities in a map', () async { - // Test if null, return without doing any change to the schedule list - await viewModel.assignScheduleActivities(null); - expect(viewModel.scheduleActivitiesByCourse.entries.length, 0); - // Test if empty list is passed, do nothing await viewModel.assignScheduleActivities([]); expect(viewModel.scheduleActivitiesByCourse.entries.length, 0); @@ -640,7 +633,7 @@ void main() { // Test normal cases, with laboratory SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, classOneWithLaboratoryABscheduleActivities.first.courseAcronym, toReturn: ActivityCode.labGroupA); @@ -654,27 +647,26 @@ void main() { 'loadSettingsScheduleActivities - test when one is selected from one group', () async { CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true, toReturn: courses); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month }); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, classOneWithLaboratoryABscheduleActivities.first.courseAcronym, toReturn: ActivityCode.labGroupA); @@ -682,19 +674,19 @@ void main() { expect(await viewModel.futureToRun(), activities, reason: "Even if SignetsAPI fails we should receives a list."); - List listScheduleActivities; - await courseRepository.getScheduleActivities().then((value) { + late List listScheduleActivities; + await courseRepositoryMock.getScheduleActivities().then((value) { listScheduleActivities = value; }); await viewModel.assignScheduleActivities(listScheduleActivities); - await untilCalled(courseRepository.getCoursesActivities()); - await untilCalled(courseRepository.getScheduleActivities()); + await untilCalled(courseRepositoryMock.getCoursesActivities()); + await untilCalled(courseRepositoryMock.getScheduleActivities()); verifyInOrder([ - courseRepository.getCoursesActivities(fromCacheOnly: true), - courseRepository.getCoursesActivities(), - courseRepository.getScheduleActivities( + courseRepositoryMock.getCoursesActivities(fromCacheOnly: true), + courseRepositoryMock.getCoursesActivities(), + courseRepositoryMock.getScheduleActivities( fromCacheOnly: anyNamed("fromCacheOnly")) ]); @@ -707,18 +699,18 @@ void main() { classOneWithLaboratoryABscheduleActivities.first.courseAcronym], "Laboratoire (Groupe A)"); - verify(settingsManager.getDynamicString(any, any)).called(2); + verify(settingsManagerMock.getDynamicString(any, any)).called(2); }); test( 'coursesActivities - should fill coursesActivities with the activities', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); @@ -747,11 +739,11 @@ void main() { 'coursesActivities - should fill coursesActivities with the activities with no LabB for GEN103', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); @@ -780,11 +772,11 @@ void main() { 'coursesActivities - should fill coursesActivities with the activities with no LabA for GEN103', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupB); @@ -813,14 +805,13 @@ void main() { 'coursesActivities - should fill coursesActivities with all the activities if none are selected', () async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", - toReturn: null); + "GEN103"); await viewModel.assignScheduleActivities([]); diff --git a/test/viewmodels/settings_viewmodel_test.dart b/test/viewmodels/settings_viewmodel_test.dart index eec9b07d0..d00afe0a9 100644 --- a/test/viewmodels/settings_viewmodel_test.dart +++ b/test/viewmodels/settings_viewmodel_test.dart @@ -16,12 +16,12 @@ import '../mock/managers/settings_manager_mock.dart'; late SettingsViewModel viewModel; void main() { - late SettingsManager settingsManager; + late SettingsManagerMock settingsManagerMock; group("SettingsViewModel - ", () { setUp(() async { // Setting up mocks - settingsManager = setupSettingsManagerMock(); + settingsManagerMock = setupSettingsManagerMock(); final AppIntl intl = await setupAppIntl(); viewModel = SettingsViewModel(intl: intl); @@ -33,71 +33,71 @@ void main() { group("futureToRun - ", () { test("The settings are correctly loaded and sets", () async { - SettingsManagerMock.stubLocale(settingsManager as SettingsManagerMock); + SettingsManagerMock.stubLocale(settingsManagerMock); SettingsManagerMock.stubThemeMode( - settingsManager as SettingsManagerMock); + settingsManagerMock); await viewModel.futureToRun(); expect(viewModel.currentLocale, 'English'); expect(viewModel.selectedTheme, ThemeMode.system); verifyInOrder([ - settingsManager.fetchLanguageAndThemeMode(), - settingsManager.locale, - settingsManager.themeMode + settingsManagerMock.fetchLanguageAndThemeMode(), + settingsManagerMock.locale, + settingsManagerMock.themeMode ]); - verifyNoMoreInteractions(settingsManager); + verifyNoMoreInteractions(settingsManagerMock); }); }); group("setter theme - ", () { test("can set system theme option", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, PreferencesFlag.theme); + settingsManagerMock, PreferencesFlag.theme); // Call the setter. viewModel.selectedTheme = ThemeMode.system; - await untilCalled(settingsManager.setThemeMode(ThemeMode.system)); + await untilCalled(settingsManagerMock.setThemeMode(ThemeMode.system)); expect(viewModel.selectedTheme, ThemeMode.system); expect(viewModel.isBusy, false); - verify(settingsManager.setThemeMode(ThemeMode.system)).called(1); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.setThemeMode(ThemeMode.system)).called(1); + verifyNoMoreInteractions(settingsManagerMock); }); test("can set dark theme option", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, PreferencesFlag.theme); + settingsManagerMock, PreferencesFlag.theme); // Call the setter. viewModel.selectedTheme = ThemeMode.dark; - await untilCalled(settingsManager.setThemeMode(ThemeMode.dark)); + await untilCalled(settingsManagerMock.setThemeMode(ThemeMode.dark)); expect(viewModel.selectedTheme, ThemeMode.dark); expect(viewModel.isBusy, false); - verify(settingsManager.setThemeMode(ThemeMode.dark)).called(1); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.setThemeMode(ThemeMode.dark)).called(1); + verifyNoMoreInteractions(settingsManagerMock); }); test("can set light theme option", () async { SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, PreferencesFlag.theme); + settingsManagerMock, PreferencesFlag.theme); // Call the setter. viewModel.selectedTheme = ThemeMode.light; - await untilCalled(settingsManager.setThemeMode(ThemeMode.light)); + await untilCalled(settingsManagerMock.setThemeMode(ThemeMode.light)); expect(viewModel.selectedTheme, ThemeMode.light); expect(viewModel.isBusy, false); - verify(settingsManager.setThemeMode(ThemeMode.light)).called(1); - verifyNoMoreInteractions(settingsManager); + verify(settingsManagerMock.setThemeMode(ThemeMode.light)).called(1); + verifyNoMoreInteractions(settingsManagerMock); }); }); }); diff --git a/test/viewmodels/startup_viewmodel_test.dart b/test/viewmodels/startup_viewmodel_test.dart index baebdea9e..6f32df692 100644 --- a/test/viewmodels/startup_viewmodel_test.dart +++ b/test/viewmodels/startup_viewmodel_test.dart @@ -17,16 +17,17 @@ import '../helpers.dart'; import '../mock/managers/settings_manager_mock.dart'; import '../mock/managers/user_repository_mock.dart'; import '../mock/services/internal_info_service_mock.dart'; +import '../mock/services/navigation_service_mock.dart'; import '../mock/services/networking_service_mock.dart'; import '../mock/services/preferences_service_mock.dart'; import '../mock/services/siren_flutter_service_mock.dart'; void main() { - late NavigationService navigationService; + late NavigationServiceMock navigationServiceMock; late UserRepositoryMock userRepositoryMock; late SettingsManagerMock settingsManagerMock; late PreferencesServiceMock preferencesServiceMock; - late NetworkingServiceMock networkingService; + late NetworkingServiceMock networkingServiceMock; late InternalInfoServiceMock internalInfoServiceMock; late SirenFlutterServiceMock sirenFlutterServiceMock; @@ -35,12 +36,12 @@ void main() { group('StartupViewModel - ', () { setUp(() async { setupAnalyticsServiceMock(); - navigationService = setupNavigationServiceMock(); - settingsManagerMock = setupSettingsManagerMock() as SettingsManagerMock; + navigationServiceMock = setupNavigationServiceMock(); + settingsManagerMock = setupSettingsManagerMock(); preferencesServiceMock = - setupPreferencesServiceMock() as PreferencesServiceMock; - userRepositoryMock = setupUserRepositoryMock() as UserRepositoryMock; - networkingService = setupNetworkingServiceMock() as NetworkingServiceMock; + setupPreferencesServiceMock(); + userRepositoryMock = setupUserRepositoryMock(); + networkingServiceMock = setupNetworkingServiceMock(); internalInfoServiceMock = setupInternalInfoServiceMock() as InternalInfoServiceMock; sirenFlutterServiceMock = @@ -64,7 +65,7 @@ void main() { test('sign in successful', () async { UserRepositoryMock.stubSilentAuthenticate(userRepositoryMock); UserRepositoryMock.stubWasPreviouslyLoggedIn(userRepositoryMock); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); InternalInfoServiceMock.stubGetPackageInfo(internalInfoServiceMock, version: "4.0.0"); SettingsManagerMock.stubGetString( @@ -73,7 +74,7 @@ void main() { await viewModel.handleStartUp(); - verify(navigationService.pushNamedAndRemoveUntil( + verify(navigationServiceMock.pushNamedAndRemoveUntil( RouterPaths.dashboard, RouterPaths.dashboard, UpdateCode.none)); }); @@ -83,7 +84,7 @@ void main() { UserRepositoryMock.stubSilentAuthenticate(userRepositoryMock, toReturn: false); UserRepositoryMock.stubWasPreviouslyLoggedIn(userRepositoryMock); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); InternalInfoServiceMock.stubGetPackageInfo(internalInfoServiceMock, version: "4.0.0"); SettingsManagerMock.stubGetString( @@ -98,11 +99,11 @@ void main() { verifyInOrder([ settingsManagerMock.getBool(PreferencesFlag.languageChoice), - navigationService.pop(), - navigationService.pushNamed(RouterPaths.login) + navigationServiceMock.pop(), + navigationServiceMock.pushNamed(RouterPaths.login) ]); - verifyNoMoreInteractions(navigationService); + verifyNoMoreInteractions(navigationServiceMock); }); test( @@ -111,7 +112,7 @@ void main() { UserRepositoryMock.stubSilentAuthenticate(userRepositoryMock, toReturn: false); UserRepositoryMock.stubWasPreviouslyLoggedIn(userRepositoryMock); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); InternalInfoServiceMock.stubGetPackageInfo(internalInfoServiceMock, version: "4.0.0"); SettingsManagerMock.stubGetString( @@ -122,18 +123,18 @@ void main() { verifyInOrder([ settingsManagerMock.getBool(PreferencesFlag.languageChoice), - navigationService.pushNamed(RouterPaths.chooseLanguage), + navigationServiceMock.pushNamed(RouterPaths.chooseLanguage), settingsManagerMock.setBool(PreferencesFlag.languageChoice, true) ]); - verifyNoMoreInteractions(navigationService); + verifyNoMoreInteractions(navigationServiceMock); }); test('verify discovery flags are bool if version mismatch', () async { const String versionToSave = "4.1.0"; UserRepositoryMock.stubSilentAuthenticate(userRepositoryMock); UserRepositoryMock.stubWasPreviouslyLoggedIn(userRepositoryMock); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); InternalInfoServiceMock.stubGetPackageInfo(internalInfoServiceMock, version: versionToSave); SettingsManagerMock.stubGetString( @@ -186,7 +187,7 @@ void main() { test('verify discovery flags are not changed for same version', () async { UserRepositoryMock.stubSilentAuthenticate(userRepositoryMock); UserRepositoryMock.stubWasPreviouslyLoggedIn(userRepositoryMock); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); InternalInfoServiceMock.stubGetPackageInfo(internalInfoServiceMock, version: "4.0.0"); SettingsManagerMock.stubGetString( @@ -205,7 +206,7 @@ void main() { () async { UserRepositoryMock.stubSilentAuthenticate(userRepositoryMock); UserRepositoryMock.stubWasPreviouslyLoggedIn(userRepositoryMock); - NetworkingServiceMock.stubHasConnectivity(networkingService); + NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); InternalInfoServiceMock.stubGetPackageInfo(internalInfoServiceMock, version: "4.0.0"); SettingsManagerMock.stubSetString( diff --git a/test/viewmodels/web_link_card_viewmodel_test.dart b/test/viewmodels/web_link_card_viewmodel_test.dart index dbf350b3c..e50d0e3df 100644 --- a/test/viewmodels/web_link_card_viewmodel_test.dart +++ b/test/viewmodels/web_link_card_viewmodel_test.dart @@ -11,18 +11,21 @@ import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/core/models/quick_link.dart'; import 'package:notredame/core/services/analytics_service.dart'; import 'package:notredame/core/services/internal_info_service.dart'; -import 'package:notredame/core/services/launch_url_service.dart'; import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/core/viewmodels/web_link_card_viewmodel.dart'; import '../helpers.dart'; +import '../mock/services/analytics_service_mock.dart'; import '../mock/services/internal_info_service_mock.dart'; +import '../mock/services/launch_url_service_mock.dart'; +import '../mock/services/navigation_service_mock.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); - late NavigationService navigationService; - late AnalyticsService analyticsService; - late InternalInfoService internalInfoService; - late LaunchUrlService launchUrlService; + + late NavigationServiceMock navigationServiceMock; + late AnalyticsServiceMock analyticsServiceMock; + late InternalInfoServiceMock internalInfoServiceMock; + late LaunchUrlServiceMock launchUrlServiceMock; late WebLinkCardViewModel viewModel; @@ -33,10 +36,10 @@ void main() { group('WebLinkCardViewModel - ', () { setUp(() async { - navigationService = setupNavigationServiceMock(); - analyticsService = setupAnalyticsServiceMock(); - internalInfoService = setupInternalInfoServiceMock(); - launchUrlService = setupLaunchUrlServiceMock(); + navigationServiceMock = setupNavigationServiceMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); + internalInfoServiceMock = setupInternalInfoServiceMock(); + launchUrlServiceMock = setupLaunchUrlServiceMock(); setupSettingsManagerMock(); setupLogger(); @@ -46,8 +49,8 @@ void main() { tearDown(() { unregister(); - clearInteractions(analyticsService); - clearInteractions(launchUrlService); + clearInteractions(analyticsServiceMock); + clearInteractions(launchUrlServiceMock); unregister(); unregister(); unregister(); @@ -58,20 +61,20 @@ void main() { await viewModel.onLinkClicked(securityQuickLink, Brightness.light); verify( - analyticsService.logEvent("QuickLink", "QuickLink clicked: test")); - verify(navigationService.pushNamed(RouterPaths.security)); - verifyNoMoreInteractions(navigationService); + analyticsServiceMock.logEvent("QuickLink", "QuickLink clicked: test")); + verify(navigationServiceMock.pushNamed(RouterPaths.security)); + verifyNoMoreInteractions(navigationServiceMock); }); test('navigate to web view if launchInBrowser throw', () async { InternalInfoServiceMock.stubGetDeviceInfoForErrorReporting( - internalInfoService as InternalInfoServiceMock); + internalInfoServiceMock); await viewModel.onLinkClicked(quickLink, Brightness.light); verify( - launchUrlService.launchInBrowser(quickLink.link, Brightness.light)); - verifyNoMoreInteractions(navigationService); + launchUrlServiceMock.launchInBrowser(quickLink.link, Brightness.light)); + verifyNoMoreInteractions(navigationServiceMock); }); }); }); From e71aa0573a86a072ae80012013a498582fdc21da Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 17:42:45 -0500 Subject: [PATCH 19/62] Managers use mocks for managers --- test/helpers.dart | 2 +- test/managers/course_repository_test.dart | 228 +++++++++--------- test/managers/quick_link_repository_test.dart | 17 +- test/managers/settings_manager_test.dart | 8 +- test/managers/user_repository_test.dart | 80 +++--- 5 files changed, 168 insertions(+), 167 deletions(-) diff --git a/test/helpers.dart b/test/helpers.dart index 66ed4d55d..b24b15063 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -99,7 +99,7 @@ InAppReviewService setupInAppReviewServiceMock() { } /// Load a mock of the [MonETSAPIClient] -MonETSAPIClient setupMonETSApiMock() { +MonETSAPIClientMock setupMonETSApiMock() { unregister(); final service = MonETSAPIClientMock(); diff --git a/test/managers/course_repository_test.dart b/test/managers/course_repository_test.dart index 042551c05..3480fe6ce 100644 --- a/test/managers/course_repository_test.dart +++ b/test/managers/course_repository_test.dart @@ -24,11 +24,11 @@ import '../mock/services/networking_service_mock.dart'; void main() { late AnalyticsServiceMock analyticsServiceMock; late NetworkingServiceMock networkingServiceMock; - late UserRepository userRepository; + late UserRepositoryMock userRepositoryMock; late CacheManagerMock cacheManagerMock; + late SignetsAPIClientMock signetsApiMock; late CourseRepository manager; - late SignetsAPIClientMock signetsApiMock; final Session session = Session( shortName: 'NOW', @@ -50,7 +50,7 @@ void main() { // Setup needed services and managers analyticsServiceMock = setupAnalyticsServiceMock(); signetsApiMock = setupSignetsApiMock(); - userRepository = setupUserRepositoryMock(); + userRepositoryMock = setupUserRepositoryMock(); cacheManagerMock = setupCacheManagerMock(); networkingServiceMock = setupNetworkingServiceMock(); setupLogger(); @@ -63,7 +63,7 @@ void main() { unregister(); clearInteractions(signetsApiMock); unregister(); - clearInteractions(userRepository); + clearInteractions(userRepositoryMock); unregister(); clearInteractions(cacheManagerMock); unregister(); @@ -87,10 +87,10 @@ void main() { setUp(() { // Stub a user - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, "password"); + userRepositoryMock, "password"); // Stub some sessions CacheManagerMock.stubGet(cacheManagerMock, @@ -143,7 +143,7 @@ void main() { ]); verifyNoMoreInteractions(signetsApiMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test( @@ -168,8 +168,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -195,7 +195,7 @@ void main() { await manager.getSessions(); expect(manager.sessions, isNotEmpty); clearInteractions(cacheManagerMock); - clearInteractions(userRepository); + clearInteractions(userRepositoryMock); clearInteractions(signetsApiMock); expect(manager.coursesActivities, isNull); @@ -209,8 +209,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -248,8 +248,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); }); @@ -265,9 +265,9 @@ void main() { clearInteractions(signetsApiMock); // Stub an authentication error - reset(userRepository); + reset(userRepositoryMock); UserRepositoryMock.stubGetPasswordException( - userRepository as UserRepositoryMock); + userRepositoryMock); expect(manager.getCoursesActivities(), throwsA(isInstanceOf())); @@ -282,12 +282,12 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), + userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); verifyNoMoreInteractions(signetsApiMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test( @@ -323,8 +323,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -356,8 +356,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -378,7 +378,7 @@ void main() { await manager.getSessions(); expect(manager.sessions, isNotEmpty); clearInteractions(cacheManagerMock); - clearInteractions(userRepository); + clearInteractions(userRepositoryMock); clearInteractions(signetsApiMock); final changedActivity = CourseActivity( @@ -407,8 +407,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -441,8 +441,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -476,8 +476,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCoursesActivities( username: username, password: anyNamed("password"), @@ -536,10 +536,10 @@ void main() { setUp(() { // Stub a user - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, "password"); + userRepositoryMock, "password"); // Stub some sessions CacheManagerMock.stubGet(cacheManagerMock, @@ -573,8 +573,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), @@ -604,7 +604,7 @@ void main() { ]); verifyNoMoreInteractions(signetsApiMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test( @@ -629,8 +629,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), @@ -658,7 +658,7 @@ void main() { await manager.getSessions(); expect(manager.sessions, isNotEmpty); clearInteractions(cacheManagerMock); - clearInteractions(userRepository); + clearInteractions(userRepositoryMock); clearInteractions(signetsApiMock); expect(manager.scheduleActivities, isNull); @@ -672,8 +672,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), @@ -713,8 +713,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); }); @@ -730,9 +730,9 @@ void main() { clearInteractions(signetsApiMock); // Stub an authentication error - reset(userRepository); + reset(userRepositoryMock); UserRepositoryMock.stubGetPasswordException( - userRepository as UserRepositoryMock); + userRepositoryMock); expect(manager.getScheduleActivities(), throwsA(isInstanceOf())); @@ -747,12 +747,12 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), + userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); verifyNoMoreInteractions(signetsApiMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test( @@ -781,8 +781,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), @@ -815,8 +815,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getScheduleActivities( username: username, password: anyNamed("password"), @@ -858,9 +858,9 @@ void main() { SignetsAPIClientMock.stubGetSessions( signetsApiMock, username, []); UserRepositoryMock.stubMonETSUser( - userRepository as UserRepositoryMock, user); + userRepositoryMock, user); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, password); + userRepositoryMock, password); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -877,8 +877,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password), cacheManagerMock.update( CourseRepository.sessionsCacheKey, jsonEncode(sessions)) @@ -901,8 +901,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password), cacheManagerMock.update(CourseRepository.sessionsCacheKey, jsonEncode([])) ]); @@ -929,8 +929,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password), cacheManagerMock.update( CourseRepository.sessionsCacheKey, jsonEncode(sessions)) @@ -953,8 +953,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password), cacheManagerMock.update( CourseRepository.sessionsCacheKey, jsonEncode(sessions)) @@ -981,8 +981,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); @@ -1016,8 +1016,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password) ]); }); @@ -1030,7 +1030,7 @@ void main() { // Stub UserRepository to throw a exception UserRepositoryMock.stubGetPasswordException( - userRepository as UserRepositoryMock); + userRepositoryMock); expect(manager.sessions, isNull); expect(manager.getSessions(), throwsA(isInstanceOf())); @@ -1042,7 +1042,7 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.sessionsCacheKey), - userRepository.getPassword(), + userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); @@ -1109,10 +1109,10 @@ void main() { SignetsAPIClientMock.stubGetSessions( signetsApiMock, username, sessions); - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, password); + userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1143,10 +1143,10 @@ void main() { SignetsAPIClientMock.stubGetSessions( signetsApiMock, username, sessions); - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, password); + userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1177,10 +1177,10 @@ void main() { SignetsAPIClientMock.stubGetSessions( signetsApiMock, username, sessions); - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, password); + userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1193,10 +1193,10 @@ void main() { test("there is no session", () async { SignetsAPIClientMock.stubGetSessions( signetsApiMock, username, []); - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, password); + userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1275,10 +1275,10 @@ void main() { setUp(() { // Stub a user - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, "password"); + userRepositoryMock, "password"); // Stub some sessions SignetsAPIClientMock.stubGetSessions( @@ -1309,8 +1309,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])) @@ -1348,7 +1348,7 @@ void main() { verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(cacheManagerMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test("Signets return a updated version of a course", () async { @@ -1381,8 +1381,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), cacheManagerMock.update(CourseRepository.coursesCacheKey, jsonEncode([courseFetched, courseWithGradeDuplicate])) @@ -1431,15 +1431,15 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(cacheManagerMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test("Student dropped out of a course, the course should disappear", @@ -1461,15 +1461,15 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(cacheManagerMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test("Courses don't have grade so getCourseSummary is called", () async { @@ -1519,8 +1519,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), signetsApiMock.getCourseSummary( username: username, password: password, course: courseFetched), @@ -1558,8 +1558,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), signetsApiMock.getCourseSummary( username: username, password: password, course: courseFetched), @@ -1591,8 +1591,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), cacheManagerMock.update( CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])) @@ -1607,7 +1607,7 @@ void main() { // Stub UserRepository to throw a exception UserRepositoryMock.stubGetPasswordException( - userRepository as UserRepositoryMock); + userRepositoryMock); expect(manager.sessions, isNull); expect(manager.getCourses(), throwsA(isInstanceOf())); @@ -1620,7 +1620,7 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), + userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); @@ -1673,8 +1673,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), signetsApiMock.getCourseReviews( username: username, password: password, session: session), @@ -1732,8 +1732,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), signetsApiMock.getCourseReviews( username: username, password: password, session: session), @@ -1771,8 +1771,8 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), signetsApiMock.getCourseReviews( username: username, password: password, session: session), @@ -1792,10 +1792,10 @@ void main() { setUp(() { // Stub a user - UserRepositoryMock.stubMonETSUser(userRepository as UserRepositoryMock, + UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); UserRepositoryMock.stubGetPassword( - userRepository as UserRepositoryMock, "password"); + userRepositoryMock, "password"); // Reset models course = Course( @@ -1849,8 +1849,8 @@ void main() { reason: 'The courses list should now be loaded.'); verifyInOrder([ - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourseSummary( username: username, password: password, course: course), cacheManagerMock.update( @@ -1870,7 +1870,7 @@ void main() { clearInteractions(cacheManagerMock); clearInteractions(signetsApiMock); - clearInteractions(userRepository); + clearInteractions(userRepositoryMock); expect(manager.courses, [course]); @@ -1882,8 +1882,8 @@ void main() { reason: 'The courses list should now be updated.'); verifyInOrder([ - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourseSummary( username: username, password: password, course: course), cacheManagerMock.update( @@ -1906,8 +1906,8 @@ void main() { analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourseSummary( username: username, password: password, course: course), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) @@ -1915,7 +1915,7 @@ void main() { verifyNoMoreInteractions(signetsApiMock); verifyNoMoreInteractions(cacheManagerMock); - verifyNoMoreInteractions(userRepository); + verifyNoMoreInteractions(userRepositoryMock); }); test( @@ -1937,8 +1937,8 @@ void main() { 'The courses list should now be loaded even if the caching fails.'); verifyInOrder([ - userRepository.getPassword(), - userRepository.monETSUser, + userRepositoryMock.getPassword(), + userRepositoryMock.monETSUser, signetsApiMock.getCourseSummary( username: username, password: password, course: course), cacheManagerMock.update( @@ -1954,7 +1954,7 @@ void main() { // Stub UserRepository to throw a exception UserRepositoryMock.stubGetPasswordException( - userRepository as UserRepositoryMock); + userRepositoryMock); expect(manager.sessions, isNull); expect(manager.getCourseSummary(course), @@ -1965,7 +1965,7 @@ void main() { analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ - userRepository.getPassword(), + userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); diff --git a/test/managers/quick_link_repository_test.dart b/test/managers/quick_link_repository_test.dart index 070c5fba5..47f728d6b 100644 --- a/test/managers/quick_link_repository_test.dart +++ b/test/managers/quick_link_repository_test.dart @@ -17,19 +17,20 @@ import '../helpers.dart'; import '../mock/managers/cache_manager_mock.dart'; void main() { - late CacheManager cacheManager; + late CacheManagerMock cacheManagerMock; + late QuickLinkRepository quickLinkRepository; group("QuickLinkRepository - ", () { setUp(() { // Setup needed services and managers - cacheManager = setupCacheManagerMock(); + cacheManagerMock = setupCacheManagerMock(); quickLinkRepository = QuickLinkRepository(); }); tearDown(() { - clearInteractions(cacheManager); + clearInteractions(cacheManagerMock); unregister(); }); @@ -38,7 +39,7 @@ void main() { // Stub the cache to return some QuickLinkData final quickLinkData = QuickLinkData(id: 1, index: 0); CacheManagerMock.stubGet( - cacheManager as CacheManagerMock, + cacheManagerMock, QuickLinkRepository.quickLinksCacheKey, jsonEncode([quickLinkData])); @@ -49,7 +50,7 @@ void main() { expect(results[0].id, quickLinkData.id); expect(results[0].index, quickLinkData.index); - verify(cacheManager.get(QuickLinkRepository.quickLinksCacheKey)) + verify(cacheManagerMock.get(QuickLinkRepository.quickLinksCacheKey)) .called(1); }); @@ -57,7 +58,7 @@ void main() { "Trying to recover QuickLinkData from cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubGetException(cacheManager as CacheManagerMock, + CacheManagerMock.stubGetException(cacheManagerMock, QuickLinkRepository.quickLinksCacheKey); expect(quickLinkRepository.getQuickLinkDataFromCache(), @@ -74,7 +75,7 @@ void main() { await quickLinkRepository.updateQuickLinkDataToCache([quickLink]); - verify(cacheManager.update(QuickLinkRepository.quickLinksCacheKey, + verify(cacheManagerMock.update(QuickLinkRepository.quickLinksCacheKey, jsonEncode([quickLinkData]))).called(1); }); @@ -82,7 +83,7 @@ void main() { "Trying to update QuickLinkData to cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubUpdateException(cacheManager as CacheManagerMock, + CacheManagerMock.stubUpdateException(cacheManagerMock, QuickLinkRepository.quickLinksCacheKey); final quickLink = diff --git a/test/managers/settings_manager_test.dart b/test/managers/settings_manager_test.dart index 4a3348d1a..5767c6ec4 100644 --- a/test/managers/settings_manager_test.dart +++ b/test/managers/settings_manager_test.dart @@ -13,7 +13,6 @@ import 'package:table_calendar/table_calendar.dart'; import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/core/services/preferences_service.dart'; -import 'package:notredame/core/services/remote_config_service.dart'; import '../helpers.dart'; import '../mock/services/analytics_service_mock.dart'; import '../mock/services/preferences_service_mock.dart'; @@ -21,8 +20,9 @@ import '../mock/services/remote_config_service_mock.dart'; void main() { late AnalyticsServiceMock analyticsServiceMock; - late RemoteConfigService remoteConfigService; + late RemoteConfigServiceMock remoteConfigServiceMock; late PreferencesServiceMock preferencesServiceMock; + late SettingsManager manager; group("SettingsManager - ", () { @@ -31,7 +31,7 @@ void main() { setupLogger(); analyticsServiceMock = setupAnalyticsServiceMock(); preferencesServiceMock = setupPreferencesServiceMock(); - remoteConfigService = setupRemoteConfigServiceMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); await setupAppIntl(); @@ -64,7 +64,7 @@ void main() { preferencesServiceMock, PreferencesFlag.scheduleShowWeekEvents); RemoteConfigServiceMock.stubGetCalendarViewEnabled( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); final expected = { PreferencesFlag.scheduleOtherWeekday: WeekDays.monday, diff --git a/test/managers/user_repository_test.dart b/test/managers/user_repository_test.dart index d96a5bc7f..bffd1c724 100644 --- a/test/managers/user_repository_test.dart +++ b/test/managers/user_repository_test.dart @@ -26,10 +26,10 @@ import '../mock/services/networking_service_mock.dart'; void main() { late AnalyticsServiceMock analyticsServiceMock; - late MonETSAPIClient monETSApi; + late MonETSAPIClientMock monETSApiMock; late FlutterSecureStorageMock secureStorageMock; late CacheManagerMock cacheManagerMock; - late SignetsAPIClient signetsApi; + late SignetsAPIClientMock signetsApiMock; late NetworkingServiceMock networkingServiceMock; late UserRepository manager; @@ -38,16 +38,16 @@ void main() { setUp(() { // Setup needed service analyticsServiceMock = setupAnalyticsServiceMock(); - monETSApi = setupMonETSApiMock(); + monETSApiMock = setupMonETSApiMock(); secureStorageMock = setupFlutterSecureStorageMock(); cacheManagerMock = setupCacheManagerMock(); - signetsApi = setupSignetsApiMock(); + signetsApiMock = setupSignetsApiMock(); networkingServiceMock = setupNetworkingServiceMock(); setupLogger(); manager = UserRepository(); - SignetsAPIClientMock.stubAuthenticate(signetsApi as SignetsAPIClientMock); + SignetsAPIClientMock.stubAuthenticate(signetsApiMock); }); tearDown(() { @@ -56,7 +56,7 @@ void main() { unregister(); clearInteractions(cacheManagerMock); unregister(); - clearInteractions(signetsApi); + clearInteractions(signetsApiMock); unregister(); unregister(); }); @@ -67,7 +67,7 @@ void main() { domain: "ENS", typeUsagerId: 1, username: "right credentials"); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); // Result is true expect( @@ -92,7 +92,7 @@ void main() { test('An exception is throw during the MonETSApi call', () async { const String username = "exceptionUser"; MonETSAPIClientMock.stubException( - monETSApi as MonETSAPIClientMock, username); + monETSApiMock, username); expect(await manager.authenticate(username: username, password: ""), isFalse, @@ -122,7 +122,7 @@ void main() { domain: "ENS", typeUsagerId: 1, username: "right credentials"); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); FlutterSecureStorageMock.stubWriteException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -153,14 +153,14 @@ void main() { MonETSUser(domain: "ENS", typeUsagerId: 1, username: "AAXXXXXX"); MonETSAPIClientMock.stubException( - monETSApi as MonETSAPIClientMock, user.username, + monETSApiMock, user.username, exception: HttpException( prefix: "MonETSAPI", code: 415, message: "{ \"Message\": \"The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.\"}")); SignetsAPIClientMock.stubAuthenticate( - signetsApi as SignetsAPIClientMock, + signetsApiMock, connected: true); // Result is true @@ -184,14 +184,14 @@ void main() { const String username = "exceptionUser"; MonETSAPIClientMock.stubException( - monETSApi as MonETSAPIClientMock, username, + monETSApiMock, username, exception: HttpException( prefix: "MonETSAPI", code: 415, message: "{ \"Message\": \"The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.\"}")); SignetsAPIClientMock.stubAuthenticate( - signetsApi as SignetsAPIClientMock); + signetsApiMock); expect(await manager.authenticate(username: username, password: ""), isFalse, @@ -231,7 +231,7 @@ void main() { key: UserRepository.passwordSecureKey, valueToReturn: password); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); expect(await manager.silentAuthenticate(), isTrue, reason: "Result should be true"); @@ -239,7 +239,7 @@ void main() { verifyInOrder([ secureStorageMock.read(key: UserRepository.usernameSecureKey), secureStorageMock.read(key: UserRepository.passwordSecureKey), - monETSApi.authenticate(username: username, password: password), + monETSApiMock.authenticate(username: username, password: password), analyticsServiceMock.setUserProperties( userId: username, domain: user.domain) ]); @@ -258,7 +258,7 @@ void main() { key: UserRepository.passwordSecureKey, valueToReturn: password); MonETSAPIClientMock.stubAuthenticateException( - monETSApi as MonETSAPIClientMock, username); + monETSApiMock, username); expect(await manager.silentAuthenticate(), isFalse, reason: "Result should be false"); @@ -266,7 +266,7 @@ void main() { verifyInOrder([ secureStorageMock.read(key: UserRepository.usernameSecureKey), secureStorageMock.read(key: UserRepository.passwordSecureKey), - monETSApi.authenticate(username: username, password: password), + monETSApiMock.authenticate(username: username, password: password), analyticsServiceMock.logError(UserRepository.tag, any, any, any) ]); @@ -288,7 +288,7 @@ void main() { [secureStorageMock.read(key: UserRepository.usernameSecureKey)]); verifyNoMoreInteractions(secureStorageMock); - verifyZeroInteractions(monETSApi); + verifyZeroInteractions(monETSApiMock); verifyZeroInteractions(analyticsServiceMock); expect(manager.monETSUser, null, @@ -302,7 +302,7 @@ void main() { domain: "ENS", typeUsagerId: 1, username: "right credentials"); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -364,7 +364,7 @@ void main() { MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); FlutterSecureStorageMock.stubRead(secureStorageMock, @@ -378,7 +378,7 @@ void main() { verifyInOrder([ secureStorageMock.read(key: UserRepository.usernameSecureKey), secureStorageMock.read(key: UserRepository.passwordSecureKey), - monETSApi.authenticate(username: username, password: password), + monETSApiMock.authenticate(username: username, password: password), analyticsServiceMock.setUserProperties( userId: username, domain: user.domain) ]); @@ -394,7 +394,7 @@ void main() { MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); FlutterSecureStorageMock.stubRead(secureStorageMock, @@ -407,7 +407,7 @@ void main() { analyticsServiceMock.logEvent(UserRepository.tag, any), secureStorageMock.read(key: UserRepository.usernameSecureKey), secureStorageMock.read(key: UserRepository.passwordSecureKey), - monETSApi.authenticate(username: username, password: password), + monETSApiMock.authenticate(username: username, password: password), analyticsServiceMock.setUserProperties( userId: username, domain: user.domain) ]); @@ -420,7 +420,7 @@ void main() { const String password = "password"; MonETSAPIClientMock.stubAuthenticateException( - monETSApi as MonETSAPIClientMock, username); + monETSApiMock, username); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); FlutterSecureStorageMock.stubRead(secureStorageMock, @@ -448,7 +448,7 @@ void main() { MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.passwordSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -491,7 +491,7 @@ void main() { UserRepository.programsCacheKey, jsonEncode(programs)); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); // Result is true expect( @@ -501,7 +501,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetPrograms( - signetsApi as SignetsAPIClientMock, username, []); + signetsApiMock, username, []); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -547,9 +547,9 @@ void main() { UserRepository.programsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving - reset(signetsApi as SignetsAPIClientMock); + reset(signetsApiMock); SignetsAPIClientMock.stubGetPrograms( - signetsApi as SignetsAPIClientMock, username, programs); + signetsApiMock, username, programs); expect(manager.programs, isNull); final results = await manager.getPrograms(); @@ -573,7 +573,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetProgramsException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); expect(manager.programs, isNull); expect(manager.getPrograms(), throwsA(isInstanceOf())); @@ -604,7 +604,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetPrograms( - signetsApi as SignetsAPIClientMock, username, programs); + signetsApiMock, username, programs); expect(manager.programs, isNull); final results = await manager.getPrograms(); @@ -646,7 +646,7 @@ void main() { UserRepository.infoCacheKey, jsonEncode(info)); MonETSAPIClientMock.stubAuthenticate( - monETSApi as MonETSAPIClientMock, user); + monETSApiMock, user); // Result is true expect( @@ -657,7 +657,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetInfo( // ignore: cast_nullable_to_non_nullable - signetsApi as SignetsAPIClientMock, username, any as ProfileStudent); + signetsApiMock, username, any as ProfileStudent); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -673,7 +673,7 @@ void main() { verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verifyNoMoreInteractions(cacheManagerMock); - verifyNoMoreInteractions(signetsApi as SignetsAPIClientMock); + verifyNoMoreInteractions(signetsApiMock); }); test("Trying to load info from cache but cache doesn't exist", () async { @@ -706,9 +706,9 @@ void main() { firstName: 'Johnny', lastName: 'Doe', permanentCode: 'DOEJ00000000'); - reset(signetsApi as SignetsAPIClientMock); + reset(signetsApiMock); SignetsAPIClientMock.stubGetInfo( - signetsApi as SignetsAPIClientMock, username, anotherInfo); + signetsApiMock, username, anotherInfo); expect(manager.info, isNull); final results = await manager.getInfo(); @@ -726,9 +726,9 @@ void main() { test("SignetsAPI return a info that already exists", () async { // Stub SignetsApi answer to test only the cache retrieving - reset(signetsApi as SignetsAPIClientMock); + reset(signetsApiMock); SignetsAPIClientMock.stubGetInfo( - signetsApi as SignetsAPIClientMock, username, info); + signetsApiMock, username, info); expect(manager.info, isNull); final results = await manager.getInfo(); @@ -752,7 +752,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetInfoException( - signetsApi as SignetsAPIClientMock, username); + signetsApiMock, username); expect(manager.info, isNull); expect(manager.getInfo(), throwsA(isInstanceOf())); @@ -780,7 +780,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetInfo( - signetsApi as SignetsAPIClientMock, username, info); + signetsApiMock, username, info); expect(manager.info, isNull); final results = await manager.getInfo(); From 0c2e22205efaeec7c49d8f0d3c1664ee075d2e42 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 18:03:12 -0500 Subject: [PATCH 20/62] Migrate widget tests to null safety --- test/services/app_widget_service_test.dart | 3 +- test/ui/widgets/bottom_bar_test.dart | 17 ++++--- test/ui/widgets/grade_button_test.dart | 37 +++++++------- .../widgets/grade_circular_progress_test.dart | 2 +- .../widgets/grade_evaluation_tile_test.dart | 10 ++-- test/ui/widgets/grade_not_available_test.dart | 2 +- test/ui/widgets/password_text_field_test.dart | 13 +++-- test/ui/widgets/schedule_settings_test.dart | 51 +++++++++---------- test/ui/widgets/student_program_test.dart | 2 +- test/ui/widgets/web_link_card_test.dart | 15 +++--- 10 files changed, 80 insertions(+), 72 deletions(-) diff --git a/test/services/app_widget_service_test.dart b/test/services/app_widget_service_test.dart index 785c8e0ae..348b40a71 100644 --- a/test/services/app_widget_service_test.dart +++ b/test/services/app_widget_service_test.dart @@ -12,9 +12,10 @@ import '../mock/services/home_widget_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - late AppWidgetService service; late HomeWidgetMock homeWidgetMock; + late AppWidgetService service; + group("AppWidgetServiceTest - ", () { setUp(() { setupAnalyticsServiceMock(); diff --git a/test/ui/widgets/bottom_bar_test.dart b/test/ui/widgets/bottom_bar_test.dart index b3aa81f7d..179a240da 100644 --- a/test/ui/widgets/bottom_bar_test.dart +++ b/test/ui/widgets/bottom_bar_test.dart @@ -13,13 +13,14 @@ import 'package:notredame/core/services/networking_service.dart'; import 'package:notredame/ui/widgets/bottom_bar.dart'; import '../../helpers.dart'; import '../../mock/services/analytics_service_mock.dart'; +import '../../mock/services/navigation_service_mock.dart'; -NavigationService navigationService; +late NavigationServiceMock navigationServiceMock; void main() { group('BottomBar - ', () { setUp(() { - navigationService = setupNavigationServiceMock(); + navigationServiceMock = setupNavigationServiceMock(); setupNetworkingServiceMock(); setupAnalyticsServiceMock(); }); @@ -57,7 +58,7 @@ void main() { await tester.tap(find.byIcon(Icons.school)); await tester.tap(find.byIcon(Icons.school)); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.student)) + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.student)) .called(1); }); @@ -71,7 +72,7 @@ void main() { await tester.tap(find.byIcon(Icons.dashboard)); verify( - navigationService.pushNamedAndRemoveUntil(RouterPaths.dashboard)); + navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.dashboard)); }); testWidgets('schedule', (WidgetTester tester) async { @@ -81,7 +82,7 @@ void main() { await tester.tap(find.byIcon(Icons.schedule)); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.schedule)); + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.schedule)); }); testWidgets('student', (WidgetTester tester) async { @@ -91,7 +92,7 @@ void main() { await tester.tap(find.byIcon(Icons.school)); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.student)); + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.student)); }); testWidgets('ets', (WidgetTester tester) async { @@ -101,7 +102,7 @@ void main() { await tester.tap(find.byIcon(Icons.account_balance)); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.ets)); + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.ets)); }); testWidgets('more', (WidgetTester tester) async { @@ -111,7 +112,7 @@ void main() { await tester.tap(find.byIcon(Icons.dehaze)); - verify(navigationService.pushNamedAndRemoveUntil(RouterPaths.more)); + verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.more)); }); }); }); diff --git a/test/ui/widgets/grade_button_test.dart b/test/ui/widgets/grade_button_test.dart index 8ba846668..3ba4dafe1 100644 --- a/test/ui/widgets/grade_button_test.dart +++ b/test/ui/widgets/grade_button_test.dart @@ -12,11 +12,12 @@ import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/ui/widgets/grade_button.dart'; import '../../helpers.dart'; import '../../mock/managers/settings_manager_mock.dart'; +import '../../mock/services/navigation_service_mock.dart'; void main() { - AppIntl intl; - NavigationService navigationService; - SettingsManager settingsManager; + late AppIntl intl; + late NavigationServiceMock navigationServiceMock; + late SettingsManagerMock settingsManagerMock; final Course courseWithGrade = Course( acronym: 'GEN101', @@ -54,10 +55,10 @@ void main() { group("GradeButton -", () { setUp(() async { - settingsManager = setupSettingsManagerMock(); + settingsManagerMock = setupSettingsManagerMock(); intl = await setupAppIntl(); setupNavigationServiceMock(); - navigationService = setupNavigationServiceMock(); + navigationServiceMock = setupNavigationServiceMock(); }); tearDown(() { @@ -69,33 +70,33 @@ void main() { testWidgets("Display acronym of the course and the current grade", (WidgetTester tester) async { SettingsManagerMock.stubGetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: 'true'); await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithGrade, showDiscovery: false))); + child: GradeButton(courseWithGrade))); await tester.pumpAndSettle(); expect(find.text(courseWithGrade.acronym), findsOneWidget); - expect(find.text(courseWithGrade.grade), findsOneWidget); + expect(find.text(courseWithGrade.grade!), findsOneWidget); }); testWidgets("Grade not available and summary is loaded.", (WidgetTester tester) async { SettingsManagerMock.stubGetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: 'true'); await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithSummary, showDiscovery: false))); + child: GradeButton(courseWithSummary))); await tester.pumpAndSettle(); expect(find.text(courseWithGrade.acronym), findsOneWidget); expect( find.text(intl.grades_grade_in_percentage( - courseWithSummary.summary.currentMarkInPercent.round())), + courseWithSummary.summary!.currentMarkInPercent.round())), findsOneWidget, reason: 'There is no grade available and the course summary exists so the ' @@ -105,12 +106,12 @@ void main() { testWidgets("Grade and summary not available.", (WidgetTester tester) async { SettingsManagerMock.stubGetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: 'true'); await tester.pumpWidget(localizedWidget( - child: GradeButton(gradesNotAvailable, showDiscovery: false))); + child: GradeButton(gradesNotAvailable))); await tester.pumpAndSettle(); expect(find.text(courseWithGrade.acronym), findsOneWidget); @@ -124,16 +125,16 @@ void main() { group('Interactions - ', () { testWidgets('Grade button redirects to grades view when tapped ', (WidgetTester tester) async { - SettingsManagerMock.stubGetBool(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubGetBool(settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: true); await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithGrade, showDiscovery: false))); + child: GradeButton(courseWithGrade))); await tester.pumpAndSettle(); await tester.tap(find.text(courseWithGrade.acronym)); - verify(navigationService.pushNamed(RouterPaths.gradeDetails, + verify(navigationServiceMock.pushNamed(RouterPaths.gradeDetails, arguments: courseWithGrade)); }); @@ -141,12 +142,12 @@ void main() { 'Grade button does not redirect to grades view if the grades discovery did not already launch', (WidgetTester tester) async { await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithGrade, showDiscovery: false))); + child: GradeButton(courseWithGrade))); await tester.pumpAndSettle(); await tester.tap(find.text(courseWithGrade.acronym)); - verifyNever(navigationService.pushNamed(RouterPaths.gradeDetails, + verifyNever(navigationServiceMock.pushNamed(RouterPaths.gradeDetails, arguments: courseWithGrade)); }); }); diff --git a/test/ui/widgets/grade_circular_progress_test.dart b/test/ui/widgets/grade_circular_progress_test.dart index 2e5f4ff49..94e3322bc 100644 --- a/test/ui/widgets/grade_circular_progress_test.dart +++ b/test/ui/widgets/grade_circular_progress_test.dart @@ -8,7 +8,7 @@ import 'package:notredame/ui/widgets/grade_circular_progress.dart'; import '../../helpers.dart'; void main() { - AppIntl intl; + late AppIntl intl; group("GradeCircularProgress -", () { setUp(() async { diff --git a/test/ui/widgets/grade_evaluation_tile_test.dart b/test/ui/widgets/grade_evaluation_tile_test.dart index 400237fbb..5d171876d 100644 --- a/test/ui/widgets/grade_evaluation_tile_test.dart +++ b/test/ui/widgets/grade_evaluation_tile_test.dart @@ -13,7 +13,7 @@ import 'package:notredame/ui/widgets/grade_evaluation_tile.dart'; import '../../helpers.dart'; void main() { - AppIntl intl; + late AppIntl intl; final CourseSummary courseSummary = CourseSummary( currentMark: 5, @@ -28,7 +28,7 @@ void main() { courseGroup: "02", title: "Laboratoire 1", weight: 10, - teacherMessage: null, + teacherMessage: '', ignore: false, mark: 24, correctedEvaluationOutOf: "35", @@ -43,7 +43,7 @@ void main() { courseGroup: "02", title: "Laboratoire 2", weight: 15, - teacherMessage: null, + teacherMessage: '', ignore: false, correctedEvaluationOutOf: "30", published: true, @@ -66,7 +66,7 @@ void main() { await tester.pumpWidget(localizedWidget( child: FeatureDiscovery( child: GradeEvaluationTile(evaluation, - completed: true, isFirstEvaluation: false)))); + completed: true)))); await tester.pumpAndSettle(); final circularPercentIndicator = find.byType(GradeCircularProgress); @@ -86,7 +86,7 @@ void main() { final widget = localizedWidget( child: FeatureDiscovery( child: GradeEvaluationTile(evaluation, - completed: true, isFirstEvaluation: false))); + completed: true))); await tester.pumpWidget(widget); diff --git a/test/ui/widgets/grade_not_available_test.dart b/test/ui/widgets/grade_not_available_test.dart index d24ed5e38..1abd31268 100644 --- a/test/ui/widgets/grade_not_available_test.dart +++ b/test/ui/widgets/grade_not_available_test.dart @@ -10,7 +10,7 @@ import 'package:notredame/ui/widgets/grade_not_available.dart'; import '../../helpers.dart'; void main() { - AppIntl intl; + late AppIntl intl; group("GradeNotAvailableTest -", () { setUp(() async { diff --git a/test/ui/widgets/password_text_field_test.dart b/test/ui/widgets/password_text_field_test.dart index 1378b228f..31a31d8a6 100644 --- a/test/ui/widgets/password_text_field_test.dart +++ b/test/ui/widgets/password_text_field_test.dart @@ -10,17 +10,22 @@ import 'package:notredame/ui/widgets/password_text_field.dart'; import '../../helpers.dart'; void main() { - AppIntl intl; + late AppIntl intl; + late PasswordFormField passwordFormField; group('PasswordFormField - ', () { setUpAll(() async { intl = await setupAppIntl(); + passwordFormField = PasswordFormField( + validator: (value) {}, + onEditionComplete: () {}, + ); }); testWidgets('has a label, the visibility icon and obscure text', (WidgetTester tester) async { await tester - .pumpWidget(localizedWidget(child: const PasswordFormField())); + .pumpWidget(localizedWidget(child: passwordFormField)); await tester.pumpAndSettle(); final icon = find.byIcon(Icons.visibility); @@ -35,7 +40,7 @@ void main() { 'toggling the visibility button should disable the obscureText property', (WidgetTester tester) async { await tester - .pumpWidget(localizedWidget(child: const PasswordFormField())); + .pumpWidget(localizedWidget(child: passwordFormField)); await tester.pumpAndSettle(); await tester.tap(find.byIcon(Icons.visibility)); @@ -54,7 +59,7 @@ void main() { 'toggling the visibility button two times should enable the obscureText property', (WidgetTester tester) async { await tester - .pumpWidget(localizedWidget(child: const PasswordFormField())); + .pumpWidget(localizedWidget(child: passwordFormField)); await tester.pumpAndSettle(); await tester.tap(find.byIcon(Icons.visibility)); diff --git a/test/ui/widgets/schedule_settings_test.dart b/test/ui/widgets/schedule_settings_test.dart index 937294fa3..da1389fd5 100644 --- a/test/ui/widgets/schedule_settings_test.dart +++ b/test/ui/widgets/schedule_settings_test.dart @@ -14,7 +14,6 @@ import 'package:table_calendar/table_calendar.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; -import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/ui/widgets/schedule_settings.dart'; import '../../helpers.dart'; import '../../mock/managers/course_repository_mock.dart'; @@ -22,10 +21,10 @@ import '../../mock/managers/settings_manager_mock.dart'; import '../../mock/services/remote_config_service_mock.dart'; void main() { - SettingsManager settingsManager; - RemoteConfigServiceMock remoteConfigService; - CourseRepositoryMock courseRepositoryMock; - AppIntl intl; + late SettingsManagerMock settingsManagerMock; + late RemoteConfigServiceMock remoteConfigServiceMock; + late CourseRepositoryMock courseRepositoryMock; + late AppIntl intl; // Some settings final Map settings = { @@ -76,21 +75,21 @@ void main() { group("ScheduleSettings - ", () { setUp(() async { - settingsManager = setupSettingsManagerMock(); + settingsManagerMock = setupSettingsManagerMock(); courseRepositoryMock = - setupCourseRepositoryMock() as CourseRepositoryMock; - remoteConfigService = - setupRemoteConfigServiceMock() as RemoteConfigServiceMock; + setupCourseRepositoryMock(); + remoteConfigServiceMock = + setupRemoteConfigServiceMock(); intl = await setupAppIntl(); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock); - RemoteConfigServiceMock.stubGetCalendarViewEnabled(remoteConfigService); + RemoteConfigServiceMock.stubGetCalendarViewEnabled(remoteConfigServiceMock); }); group("ui - ", () { testWidgets("With handle", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester .pumpWidget(localizedWidget(child: const ScheduleSettings())); @@ -100,7 +99,7 @@ void main() { expect( find.byWidgetPredicate((widget) => widget is Container && - (widget.decoration as BoxDecoration).color == Colors.grey), + (widget.decoration! as BoxDecoration).color == Colors.grey), findsOneWidget, reason: "The handle should be grey"); @@ -177,7 +176,7 @@ void main() { testWidgets("Without handle", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget( @@ -187,7 +186,7 @@ void main() { expect( find.byWidgetPredicate((widget) => widget is Container && - (widget.decoration as BoxDecoration).color == Colors.grey), + (widget.decoration! as BoxDecoration).color == Colors.grey), findsNothing, reason: "There should not have a handle."); @@ -267,7 +266,7 @@ void main() { "Should display activity selection section when a course has activities", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); @@ -304,13 +303,13 @@ void main() { "When a settings laboratory is already selected, verify that it is in fact preselected", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); // preselect the laboB SettingsManagerMock.stubGetDynamicString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleLaboratoryGroup, "GEN101", toReturn: ActivityCode.labGroupB); @@ -341,7 +340,7 @@ void main() { "if there is only a laboA (no labo b) the options should not appear on screen", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); final courseWithOnlyLabA = List.from( classOneWithLaboratoryABscheduleActivities); @@ -369,10 +368,10 @@ void main() { group("interactions - ", () { testWidgets("onChange calendarFormat", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); SettingsManagerMock.stubSetString( - settingsManager as SettingsManagerMock, + settingsManagerMock, PreferencesFlag.scheduleCalendarFormat); await tester.pumpWidget( @@ -383,7 +382,7 @@ void main() { ListTile, intl.schedule_settings_calendar_format_2_weeks)); await tester.pump(); - await untilCalled(settingsManager.setString( + await untilCalled(settingsManagerMock.setString( PreferencesFlag.scheduleCalendarFormat, any)); final formatTile = find.widgetWithText( @@ -398,9 +397,9 @@ void main() { testWidgets("onChange showTodayBtn", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); - SettingsManagerMock.stubSetBool(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetBool(settingsManagerMock, PreferencesFlag.scheduleShowTodayBtn); await tester.pumpWidget( @@ -415,12 +414,12 @@ void main() { // Currently the await tester.tap on a switch in a tile isn't working. Workaround: (find.byType(Switch, skipOffstage: false).evaluate().single.widget as Switch) - .onChanged(false); + .onChanged!(false); await tester.pumpAndSettle(); await untilCalled( - settingsManager.setBool(PreferencesFlag.scheduleShowTodayBtn, any)); + settingsManagerMock.setBool(PreferencesFlag.scheduleShowTodayBtn, any)); expect( tester.widget(find.descendant( @@ -437,7 +436,7 @@ void main() { "Should display activity selection section when a course has activities", (WidgetTester tester) async { SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); diff --git a/test/ui/widgets/student_program_test.dart b/test/ui/widgets/student_program_test.dart index 9e158962e..9143a7f2d 100644 --- a/test/ui/widgets/student_program_test.dart +++ b/test/ui/widgets/student_program_test.dart @@ -22,7 +22,7 @@ final _program = Program( failedCourses: '0'); void main() { - AppIntl intl; + late AppIntl intl; group('Student program - ', () { setUp(() async { diff --git a/test/ui/widgets/web_link_card_test.dart b/test/ui/widgets/web_link_card_test.dart index fe7113a01..a2db92117 100644 --- a/test/ui/widgets/web_link_card_test.dart +++ b/test/ui/widgets/web_link_card_test.dart @@ -9,30 +9,31 @@ import 'package:mockito/mockito.dart'; import 'package:notredame/core/models/quick_link.dart'; import 'package:notredame/core/services/analytics_service.dart'; import 'package:notredame/core/services/internal_info_service.dart'; -import 'package:notredame/core/services/launch_url_service.dart'; import 'package:notredame/core/services/navigation_service.dart'; import 'package:notredame/ui/widgets/web_link_card.dart'; import '../../helpers.dart'; +import '../../mock/services/analytics_service_mock.dart'; +import '../../mock/services/launch_url_service_mock.dart'; final _quickLink = QuickLink( id: 1, image: const Icon(Icons.ac_unit), name: 'test', link: 'testlink'); void main() { - AnalyticsService analyticsService; - LaunchUrlService launchUrlService; + late AnalyticsServiceMock analyticsServiceMock; + late LaunchUrlServiceMock launchUrlServiceMock; group('WebLinkCard - ', () { setUp(() { - analyticsService = setupAnalyticsServiceMock(); - launchUrlService = setupLaunchUrlServiceMock(); + analyticsServiceMock = setupAnalyticsServiceMock(); + launchUrlServiceMock = setupLaunchUrlServiceMock(); setupInternalInfoServiceMock(); setupNavigationServiceMock(); }); tearDown(() { unregister(); - clearInteractions(analyticsService); - clearInteractions(launchUrlService); + clearInteractions(analyticsServiceMock); + clearInteractions(launchUrlServiceMock); unregister(); unregister(); }); From 3e1f938b86d0a8bb76ba1fd856af7ab7ab31c6db Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 18:18:25 -0500 Subject: [PATCH 21/62] Migrate views tests to null safety --- lib/ui/views/faq_view.dart | 4 +- test/ui/views/choose_language_view_test.dart | 2 +- test/ui/views/dashboard_view_test.dart | 221 +++++++++---------- test/ui/views/faq_view_test.dart | 15 +- test/ui/views/grades_details_view_test.dart | 20 +- test/ui/views/grades_view_test.dart | 34 ++- test/ui/views/login_view_test.dart | 8 +- test/ui/views/more_view_test.dart | 49 ++-- test/ui/views/profile_view_test.dart | 15 +- test/ui/views/quick_links_view_test.dart | 10 +- test/ui/views/schedule_view_test.dart | 127 +++++------ test/ui/views/security_view_test.dart | 2 +- test/ui/views/settings_view_test.dart | 2 +- test/ui/views/student_view_test.dart | 11 +- 14 files changed, 242 insertions(+), 278 deletions(-) diff --git a/lib/ui/views/faq_view.dart b/lib/ui/views/faq_view.dart index 988971b9c..56261591d 100644 --- a/lib/ui/views/faq_view.dart +++ b/lib/ui/views/faq_view.dart @@ -12,9 +12,9 @@ import 'package:notredame/core/models/faq_actions.dart'; import 'package:notredame/core/viewmodels/faq_viewmodel.dart'; class FaqView extends StatefulWidget { - final Color backgroundColor; + final Color? backgroundColor; - const FaqView({required this.backgroundColor}); + const FaqView({this.backgroundColor}); @override State createState() => _FaqViewState(); diff --git a/test/ui/views/choose_language_view_test.dart b/test/ui/views/choose_language_view_test.dart index 23b9b0f14..56242af4a 100644 --- a/test/ui/views/choose_language_view_test.dart +++ b/test/ui/views/choose_language_view_test.dart @@ -15,7 +15,7 @@ import 'package:notredame/ui/views/choose_language_view.dart'; import '../../helpers.dart'; void main() { - AppIntl intl; + late AppIntl intl; group('SettingsView - ', () { setUp(() async { intl = await setupAppIntl(); diff --git a/test/ui/views/dashboard_view_test.dart b/test/ui/views/dashboard_view_test.dart index 211b4f834..ab1410a30 100644 --- a/test/ui/views/dashboard_view_test.dart +++ b/test/ui/views/dashboard_view_test.dart @@ -12,9 +12,7 @@ import 'package:flutter_test/flutter_test.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; -import 'package:notredame/core/managers/course_repository.dart'; -import 'package:notredame/core/managers/settings_manager.dart'; -import 'package:notredame/core/services/remote_config_service.dart'; +import 'package:notredame/core/constants/update_code.dart'; import 'package:notredame/ui/views/dashboard_view.dart'; import 'package:notredame/ui/widgets/course_activity_tile.dart'; import 'package:notredame/ui/widgets/grade_button.dart'; @@ -25,11 +23,12 @@ import '../../mock/services/in_app_review_service_mock.dart'; import '../../mock/services/remote_config_service_mock.dart'; void main() { - SettingsManager settingsManager; - CourseRepository courseRepository; - RemoteConfigService remoteConfigService; - AppIntl intl; - InAppReviewServiceMock inAppReviewServiceMock; + late SettingsManagerMock settingsManagerMock; + late CourseRepositoryMock courseRepositoryMock; + late RemoteConfigServiceMock remoteConfigServiceMock; + late InAppReviewServiceMock inAppReviewServiceMock; + + late AppIntl intl; // Activities for today final gen101 = CourseActivity( @@ -144,24 +143,23 @@ void main() { Future testDashboardSchedule(WidgetTester tester, DateTime now, List courses, int expected) async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); - SettingsManagerMock.stubGetDashboard(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubDateTimeNow(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: now); await tester.pumpWidget( - localizedWidget(child: FeatureDiscovery(child: const DashboardView()))); + localizedWidget(child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find schedule card in second position by its title @@ -174,11 +172,11 @@ void main() { group('DashboardView - ', () { setUp(() async { intl = await setupAppIntl(); - settingsManager = setupSettingsManagerMock(); - courseRepository = setupCourseRepositoryMock(); - remoteConfigService = setupRemoteConfigServiceMock(); + settingsManagerMock = setupSettingsManagerMock(); + courseRepositoryMock = setupCourseRepositoryMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); setupNavigationServiceMock(); - courseRepository = setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); setupNetworkingServiceMock(); setupAnalyticsServiceMock(); setupAppWidgetServiceMock(); @@ -190,69 +188,67 @@ void main() { toReturn: false); CourseRepositoryMock.stubSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubGetSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubActiveSessions( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [session]); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastColor( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastEn( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastFr( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastTitleEn( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastTitleFr( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastType( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); RemoteConfigServiceMock.stubGetBroadcastUrl( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); - SettingsManagerMock.stubGetBool(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubGetBool(settingsManagerMock, PreferencesFlag.discoveryDashboard, toReturn: true); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.broadcastCard); SettingsManagerMock.stubSetInt( - settingsManager as SettingsManagerMock, PreferencesFlag.aboutUsCard); + settingsManagerMock, PreferencesFlag.aboutUsCard); SettingsManagerMock.stubSetInt( - settingsManager as SettingsManagerMock, PreferencesFlag.scheduleCard); + settingsManagerMock, PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.progressBarCard); SettingsManagerMock.stubSetInt( - settingsManager as SettingsManagerMock, PreferencesFlag.gradesCard); + settingsManagerMock, PreferencesFlag.gradesCard); SettingsManagerMock.stubDateTimeNow( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: DateTime.now()); }); @@ -262,11 +258,11 @@ void main() { testWidgets('Has view title restore button and cards, displayed', (WidgetTester tester) async { SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dashboard Title @@ -288,22 +284,21 @@ void main() { testWidgets('Has card aboutUs displayed properly', (WidgetTester tester) async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: activities); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find aboutUs card @@ -388,36 +383,35 @@ void main() { testWidgets('AboutUsCard is dismissible and can be restored', (WidgetTester tester) async { CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.scheduleCard); SettingsManagerMock.stubSetInt( - settingsManager as SettingsManagerMock, PreferencesFlag.gradesCard); + settingsManagerMock, PreferencesFlag.gradesCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.progressBarCard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -449,35 +443,34 @@ void main() { testWidgets('AboutUsCard is reorderable and can be restored', (WidgetTester tester) async { SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.scheduleCard); SettingsManagerMock.stubSetInt( - settingsManager as SettingsManagerMock, PreferencesFlag.gradesCard); + settingsManagerMock, PreferencesFlag.gradesCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.progressBarCard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -512,7 +505,7 @@ void main() { of: find.byType(Dismissible, skipOffstage: false).last, matching: find.byType(Text), )); - expect((text as Text).data, intl.card_applets_title); + expect(text.data, intl.card_applets_title); // Tap the restoreCards button await tester.tap(find.byIcon(Icons.restore)); @@ -528,17 +521,17 @@ void main() { findsNWidgets(numberOfCards)); // Check that the first card is now AboutUs - expect((text as Text).data, intl.card_applets_title); + expect(text.data, intl.card_applets_title); }); testWidgets('ScheduleCard is dismissible and can be restored', (WidgetTester tester) async { SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -575,11 +568,11 @@ void main() { testWidgets('Has card grades displayed - with no courses', (WidgetTester tester) async { SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find grades card @@ -601,23 +594,22 @@ void main() { testWidgets('Has card grades displayed - with courses', (WidgetTester tester) async { CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true, toReturn: courses); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false, + courseRepositoryMock, toReturn: courses); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find grades card @@ -636,26 +628,26 @@ void main() { testWidgets('gradesCard is dismissible and can be restored', (WidgetTester tester) async { - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.progressBarCard); - SettingsManagerMock.stubSetInt(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubSetInt(settingsManagerMock, PreferencesFlag.gradesCard); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -693,11 +685,11 @@ void main() { testWidgets('Has card progressBar displayed', (WidgetTester tester) async { SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find progress card @@ -716,11 +708,11 @@ void main() { testWidgets('progressCard is dismissible and can be restored', (WidgetTester tester) async { SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -754,11 +746,11 @@ void main() { (WidgetTester tester) async { InAppReviewServiceMock.stubIsAvailable(inAppReviewServiceMock); SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -793,7 +785,7 @@ void main() { of: find.widgetWithText(Dismissible, intl.progress_bar_title).last, matching: find.byType(Text), )); - expect((text as Text).data, intl.progress_bar_title); + expect(text.data, intl.progress_bar_title); // Tap the restoreCards button await tester.tap(find.byIcon(Icons.restore)); @@ -809,7 +801,7 @@ void main() { findsNWidgets(numberOfCards)); // Check that the first card is now AboutUs - expect((text as Text).data, intl.progress_bar_title); + expect(text.data, intl.progress_bar_title); }); }); @@ -820,7 +812,7 @@ void main() { testWidgets("Applets Card", (WidgetTester tester) async { RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -830,11 +822,11 @@ void main() { }; SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); await expectLater(find.byType(DashboardView), @@ -843,18 +835,17 @@ void main() { testWidgets("Schedule card", (WidgetTester tester) async { RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); dashboard = { PreferencesFlag.broadcastCard: 0, @@ -862,11 +853,11 @@ void main() { }; SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); await expectLater(find.byType(DashboardView), @@ -874,7 +865,7 @@ void main() { }); testWidgets("progressBar Card", (WidgetTester tester) async { RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -884,11 +875,11 @@ void main() { }; SettingsManagerMock.stubGetDashboard( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView()))); + child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); await expectLater( diff --git a/test/ui/views/faq_view_test.dart b/test/ui/views/faq_view_test.dart index 909c16b67..066a17ba5 100644 --- a/test/ui/views/faq_view_test.dart +++ b/test/ui/views/faq_view_test.dart @@ -8,20 +8,19 @@ import 'package:flutter_test/flutter_test.dart'; // Project imports: import 'package:notredame/core/constants/faq.dart'; -import 'package:notredame/core/managers/settings_manager.dart'; import 'package:notredame/ui/views/faq_view.dart'; import '../../helpers.dart'; import '../../mock/managers/settings_manager_mock.dart'; void main() { group('FaqView - ', () { - AppIntl appIntl; + late AppIntl appIntl; - SettingsManager settingsManager; + late SettingsManagerMock settingsManagerMock; setUp(() async { setupLaunchUrlServiceMock(); - settingsManager = setupSettingsManagerMock(); + settingsManagerMock = setupSettingsManagerMock(); appIntl = await setupAppIntl(); }); @@ -29,7 +28,7 @@ void main() { group('UI - ', () { testWidgets('has x ElevatedButton', (WidgetTester tester) async { - SettingsManagerMock.stubLocale(settingsManager as SettingsManagerMock); + SettingsManagerMock.stubLocale(settingsManagerMock); await tester.pumpWidget(localizedWidget(child: const FaqView())); await tester.pumpAndSettle(); @@ -42,7 +41,7 @@ void main() { }); testWidgets('has 2 subtitles', (WidgetTester tester) async { - SettingsManagerMock.stubLocale(settingsManager as SettingsManagerMock); + SettingsManagerMock.stubLocale(settingsManagerMock); await tester.pumpWidget(localizedWidget(child: const FaqView())); await tester.pumpAndSettle(); @@ -55,7 +54,7 @@ void main() { }); testWidgets('has 1 title', (WidgetTester tester) async { - SettingsManagerMock.stubLocale(settingsManager as SettingsManagerMock); + SettingsManagerMock.stubLocale(settingsManagerMock); await tester.pumpWidget(localizedWidget(child: const FaqView())); await tester.pumpAndSettle(); @@ -68,7 +67,7 @@ void main() { group("golden - ", () { testWidgets("default view", (WidgetTester tester) async { - SettingsManagerMock.stubLocale(settingsManager as SettingsManagerMock); + SettingsManagerMock.stubLocale(settingsManagerMock); tester.binding.window.physicalSizeTestValue = const Size(1800, 2410); await tester.pumpWidget(localizedWidget(child: const FaqView())); diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index 56a614bea..7a69effd0 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -19,7 +19,7 @@ import '../../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - CourseRepository courseRepository; + late CourseRepositoryMock courseRepositoryMock; final CourseSummary courseSummary = CourseSummary( currentMark: 5, @@ -34,7 +34,7 @@ void main() { courseGroup: "02", title: "Laboratoire 1", weight: 10, - teacherMessage: null, + teacherMessage: '', ignore: false, mark: 24, correctedEvaluationOutOf: "35", @@ -96,7 +96,7 @@ void main() { group('GradesDetailsView - ', () { setUp(() async { setupNavigationServiceMock(); - courseRepository = setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); setupSettingsManagerMock(); setupNetworkingServiceMock(); }); @@ -139,7 +139,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: course); await tester.pumpWidget(localizedWidget( @@ -160,7 +160,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: course); await tester.pumpWidget(localizedWidget( @@ -181,7 +181,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: courseWithoutSummary); await tester.pumpWidget(localizedWidget( @@ -197,7 +197,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, courseWithEvaluationNotCompleted, toReturn: courseWithEvaluationNotCompleted); @@ -215,7 +215,7 @@ void main() { testWidgets("default view", (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: course); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -232,7 +232,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: courseWithoutSummary); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -249,7 +249,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepository as CourseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, courseWithoutSummary, toReturn: courseWithEvaluationNotCompleted); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); diff --git a/test/ui/views/grades_view_test.dart b/test/ui/views/grades_view_test.dart index a1abdf0bd..250bb07a5 100644 --- a/test/ui/views/grades_view_test.dart +++ b/test/ui/views/grades_view_test.dart @@ -20,8 +20,8 @@ import '../../helpers.dart'; import '../../mock/managers/course_repository_mock.dart'; void main() { - CourseRepository courseRepository; - AppIntl intl; + late CourseRepositoryMock courseRepositoryMock; + late AppIntl intl; final Course courseSummer = Course( acronym: 'GEN101', @@ -65,7 +65,7 @@ void main() { setUp(() async { intl = await setupAppIntl(); setupNavigationServiceMock(); - courseRepository = setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); setupSettingsManagerMock(); setupAnalyticsServiceMock(); }); @@ -80,12 +80,11 @@ void main() { testWidgets("No grades available", (WidgetTester tester) async { // Mock the repository to have 0 courses available CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -102,13 +101,12 @@ void main() { (WidgetTester tester) async { // Mock the repository to have 0 courses available CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); @@ -129,12 +127,11 @@ void main() { (WidgetTester tester) async { // Mock the repository to have 0 courses available CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -151,13 +148,12 @@ void main() { (WidgetTester tester) async { // Mock the repository to have 4 courses available CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: courses, fromCacheOnly: true); diff --git a/test/ui/views/login_view_test.dart b/test/ui/views/login_view_test.dart index b7a7dda15..75e5c642a 100644 --- a/test/ui/views/login_view_test.dart +++ b/test/ui/views/login_view_test.dart @@ -15,11 +15,9 @@ import 'package:notredame/core/services/preferences_service.dart'; import 'package:notredame/ui/views/login_view.dart'; import 'package:notredame/ui/widgets/password_text_field.dart'; import '../../helpers.dart'; -import '../../mock/services/analytics_service_mock.dart'; -import '../../mock/services/launch_url_service_mock.dart'; void main() { - AppIntl intl; + late AppIntl intl; group('LoginView - ', () { setUp(() async { @@ -29,8 +27,8 @@ void main() { setupSettingsManagerMock(); setupFlutterSecureStorageMock(); setupPreferencesServiceMock(); - setupLaunchUrlServiceMock() as LaunchUrlServiceMock; - setupAnalyticsServiceMock() as AnalyticsServiceMock; + setupLaunchUrlServiceMock(); + setupAnalyticsServiceMock(); }); tearDown(() { diff --git a/test/ui/views/more_view_test.dart b/test/ui/views/more_view_test.dart index ba4fd5b48..5d74acb80 100644 --- a/test/ui/views/more_view_test.dart +++ b/test/ui/views/more_view_test.dart @@ -13,31 +13,30 @@ import 'package:mockito/mockito.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; import 'package:notredame/core/constants/router_paths.dart'; -import 'package:notredame/core/services/navigation_service.dart'; -import 'package:notredame/core/services/remote_config_service.dart'; import 'package:notredame/ui/views/more_view.dart'; import '../../helpers.dart'; import '../../mock/managers/settings_manager_mock.dart'; import '../../mock/services/in_app_review_service_mock.dart'; +import '../../mock/services/navigation_service_mock.dart'; import '../../mock/services/remote_config_service_mock.dart'; void main() { - AppIntl intl; - NavigationService navigation; - RemoteConfigService remoteConfigService; - InAppReviewServiceMock inAppReviewServiceMock; - SettingsManagerMock settingsManagerMock; + late AppIntl intl; + late NavigationServiceMock navigationServiceMock; + late RemoteConfigServiceMock remoteConfigServiceMock; + late InAppReviewServiceMock inAppReviewServiceMock; + late SettingsManagerMock settingsManagerMock; group('MoreView - ', () { setUp(() async { intl = await setupAppIntl(); - navigation = setupNavigationServiceMock(); - remoteConfigService = setupRemoteConfigServiceMock(); + navigationServiceMock = setupNavigationServiceMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); setupCourseRepositoryMock(); setupPreferencesServiceMock(); setupUserRepositoryMock(); setupCacheManagerMock(); - settingsManagerMock = setupSettingsManagerMock() as SettingsManagerMock; + settingsManagerMock = setupSettingsManagerMock(); setupGithubApiMock(); setupNetworkingServiceMock(); setupAnalyticsServiceMock(); @@ -49,14 +48,14 @@ void main() { toReturn: true); RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); }); group('UI - ', () { testWidgets('has 1 listView and 8 listTiles when privacy policy disabled', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -85,7 +84,7 @@ void main() { group('navigation - ', () { testWidgets('about', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -98,12 +97,12 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigation.pushNamed(RouterPaths.about)).called(1); + verify(navigationServiceMock.pushNamed(RouterPaths.about)).called(1); }); testWidgets('rate us is not available', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); InAppReviewServiceMock.stubIsAvailable(inAppReviewServiceMock, toReturn: false); @@ -125,7 +124,7 @@ void main() { testWidgets('rate us is available', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); InAppReviewServiceMock.stubIsAvailable(inAppReviewServiceMock); @@ -147,7 +146,7 @@ void main() { testWidgets('contributors', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -160,12 +159,12 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigation.pushNamed(RouterPaths.contributors)).called(1); + verify(navigationServiceMock.pushNamed(RouterPaths.contributors)).called(1); }); testWidgets('licenses', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -185,7 +184,7 @@ void main() { testWidgets('need help', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -197,13 +196,13 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigation.pushNamed(RouterPaths.faq, arguments: Colors.white)) + verify(navigationServiceMock.pushNamed(RouterPaths.faq, arguments: Colors.white)) .called(1); }); testWidgets('settings', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -215,12 +214,12 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigation.pushNamed(RouterPaths.settings)).called(1); + verify(navigationServiceMock.pushNamed(RouterPaths.settings)).called(1); }); testWidgets('logout', (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); await tester.pumpWidget( localizedWidget(child: FeatureDiscovery(child: MoreView()))); @@ -241,7 +240,7 @@ void main() { group("golden - ", () { testWidgets("default view", (WidgetTester tester) async { RemoteConfigServiceMock.stubGetPrivacyPolicyEnabled( - remoteConfigService as RemoteConfigServiceMock, + remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); diff --git a/test/ui/views/profile_view_test.dart b/test/ui/views/profile_view_test.dart index b1be87ae7..201063094 100644 --- a/test/ui/views/profile_view_test.dart +++ b/test/ui/views/profile_view_test.dart @@ -10,7 +10,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; // Project imports: -import 'package:notredame/core/managers/user_repository.dart'; import 'package:notredame/core/services/networking_service.dart'; import 'package:notredame/ui/views/profile_view.dart'; import '../../helpers.dart'; @@ -18,8 +17,8 @@ import '../../mock/managers/user_repository_mock.dart'; import '../../mock/services/analytics_service_mock.dart'; void main() { - AppIntl intl; - UserRepository userRepository; + late AppIntl intl; + late UserRepositoryMock userRepositoryMock; final profileStudent = ProfileStudent( firstName: "John", @@ -45,19 +44,19 @@ void main() { setUp(() async { intl = await setupAppIntl(); setupNavigationServiceMock(); - userRepository = setupUserRepositoryMock(); + userRepositoryMock = setupUserRepositoryMock(); setupAnalyticsServiceMock(); - UserRepositoryMock.stubGetInfo(userRepository as UserRepositoryMock, + UserRepositoryMock.stubGetInfo(userRepositoryMock, toReturn: profileStudent); UserRepositoryMock.stubProfileStudent( - userRepository as UserRepositoryMock, + userRepositoryMock, toReturn: profileStudent); - UserRepositoryMock.stubGetPrograms(userRepository as UserRepositoryMock, + UserRepositoryMock.stubGetPrograms(userRepositoryMock, toReturn: programList); - UserRepositoryMock.stubPrograms(userRepository as UserRepositoryMock, + UserRepositoryMock.stubPrograms(userRepositoryMock, toReturn: programList); }); diff --git a/test/ui/views/quick_links_view_test.dart b/test/ui/views/quick_links_view_test.dart index 9e6a08fb5..ccc1f5b79 100644 --- a/test/ui/views/quick_links_view_test.dart +++ b/test/ui/views/quick_links_view_test.dart @@ -23,9 +23,9 @@ import '../../mock/services/internal_info_service_mock.dart'; import '../../mock/services/navigation_service_mock.dart'; void main() { - AppIntl intl; + late AppIntl intl; - QuickLinkRepository quickLinkRepository; + QuickLinkRepositoryMock quickLinkRepositoryMock; group('QuickLinksView - ', () { setUp(() async { @@ -35,13 +35,13 @@ void main() { setupInternalInfoServiceMock(); setupNetworkingServiceMock(); setupLaunchUrlServiceMock(); - quickLinkRepository = setupQuickLinkRepositoryMock(); + quickLinkRepositoryMock = setupQuickLinkRepositoryMock(); QuickLinkRepositoryMock.stubGetDefaultQuickLinks( - quickLinkRepository as QuickLinkRepositoryMock, + quickLinkRepositoryMock, toReturn: quickLinks(intl)); QuickLinkRepositoryMock.stubGetQuickLinkDataFromCacheException( - quickLinkRepository as QuickLinkRepositoryMock); + quickLinkRepositoryMock); }); tearDown(() { diff --git a/test/ui/views/schedule_view_test.dart b/test/ui/views/schedule_view_test.dart index 9805ce502..eea0269b5 100644 --- a/test/ui/views/schedule_view_test.dart +++ b/test/ui/views/schedule_view_test.dart @@ -13,9 +13,6 @@ import 'package:table_calendar/table_calendar.dart'; // Project imports: import 'package:notredame/core/constants/preferences_flags.dart'; -import 'package:notredame/core/managers/course_repository.dart'; -import 'package:notredame/core/managers/settings_manager.dart'; -import 'package:notredame/core/services/remote_config_service.dart'; import 'package:notredame/ui/views/schedule_view.dart'; import 'package:notredame/ui/widgets/schedule_settings.dart'; import '../../helpers.dart'; @@ -24,14 +21,14 @@ import '../../mock/managers/settings_manager_mock.dart'; import '../../mock/services/remote_config_service_mock.dart'; void main() { - SettingsManager settingsManager; - CourseRepository courseRepository; - RemoteConfigService remoteConfigService; + late SettingsManagerMock settingsManagerMock; + late CourseRepositoryMock courseRepositoryMock; + late RemoteConfigServiceMock remoteConfigServiceMock; // Some activities - CourseActivity activityYesterday; - CourseActivity activityToday; - CourseActivity activityTomorrow; + late CourseActivity activityYesterday; + late CourseActivity activityToday; + late CourseActivity activityTomorrow; // Some settings Map settings = { @@ -80,13 +77,13 @@ void main() { setUp(() async { setupNavigationServiceMock(); - settingsManager = setupSettingsManagerMock(); - courseRepository = setupCourseRepositoryMock(); - remoteConfigService = setupRemoteConfigServiceMock(); + settingsManagerMock = setupSettingsManagerMock(); + courseRepositoryMock = setupCourseRepositoryMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); setupNetworkingServiceMock(); setupAnalyticsServiceMock(); - SettingsManagerMock.stubLocale(settingsManager as SettingsManagerMock); + SettingsManagerMock.stubLocale(settingsManagerMock); settings = { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.week, @@ -97,9 +94,9 @@ void main() { }; CourseRepositoryMock.stubGetScheduleActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); RemoteConfigServiceMock.stubGetCalendarViewEnabled( - remoteConfigService as RemoteConfigServiceMock); + remoteConfigServiceMock); }); group("golden - ", () { @@ -108,21 +105,19 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -136,28 +131,26 @@ void main() { testWidgets("default view (no events), showTodayButton disabled", (WidgetTester tester) async { - SettingsManagerMock.stubGetBool(settingsManager as SettingsManagerMock, + SettingsManagerMock.stubGetBool(settingsManagerMock, PreferencesFlag.discoverySchedule); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); settings[PreferencesFlag.scheduleShowTodayBtn] = false; CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -173,22 +166,20 @@ void main() { (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [activityYesterday, activityToday, activityTomorrow]); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -207,22 +198,20 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [activityYesterday, activityTomorrow]); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -239,22 +228,20 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [activityYesterday, activityTomorrow]); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); final testingDate = DateTime(2020); @@ -296,22 +283,20 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [activityToday]); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -351,22 +336,20 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); CourseRepositoryMock.stubCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, toReturn: [activityToday]); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivities( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); SettingsManagerMock.stubGetScheduleSettings( - settingsManager as SettingsManagerMock, + settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( diff --git a/test/ui/views/security_view_test.dart b/test/ui/views/security_view_test.dart index 2afa64f61..4a19a130c 100644 --- a/test/ui/views/security_view_test.dart +++ b/test/ui/views/security_view_test.dart @@ -12,7 +12,7 @@ import 'package:notredame/ui/views/security_view.dart'; import '../../helpers.dart'; void main() { - AppIntl intl; + late AppIntl intl; group('SecurityView - ', () { setUp(() async { diff --git a/test/ui/views/settings_view_test.dart b/test/ui/views/settings_view_test.dart index f90bc9647..e9e8abe2e 100644 --- a/test/ui/views/settings_view_test.dart +++ b/test/ui/views/settings_view_test.dart @@ -16,7 +16,7 @@ import '../../helpers.dart'; import '../../mock/services/analytics_service_mock.dart'; void main() { - AppIntl intl; + late AppIntl intl; group('SettingsView - ', () { setUp(() async { diff --git a/test/ui/views/student_view_test.dart b/test/ui/views/student_view_test.dart index 1cc8c7421..6bb1cf6e8 100644 --- a/test/ui/views/student_view_test.dart +++ b/test/ui/views/student_view_test.dart @@ -19,23 +19,22 @@ import '../../mock/managers/course_repository_mock.dart'; import '../../mock/services/analytics_service_mock.dart'; void main() { - CourseRepository courseRepository; + CourseRepositoryMock courseRepositoryMock; group('StudentView - ', () { setUp(() async { setupNavigationServiceMock(); setupNetworkingServiceMock(); - courseRepository = setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); setupSettingsManagerMock(); setupAnalyticsServiceMock(); CourseRepositoryMock.stubCourses( - courseRepository as CourseRepositoryMock); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, - fromCacheOnly: false); + courseRepositoryMock); CourseRepositoryMock.stubGetCourses( - courseRepository as CourseRepositoryMock, + courseRepositoryMock, fromCacheOnly: true); }); From 1ecb121e342560320095ce6e4151ada3bd10b219 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 21:04:36 -0500 Subject: [PATCH 22/62] Fix course_repository_test --- test/managers/course_repository_test.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/managers/course_repository_test.dart b/test/managers/course_repository_test.dart index 3480fe6ce..c712ce95c 100644 --- a/test/managers/course_repository_test.dart +++ b/test/managers/course_repository_test.dart @@ -268,6 +268,8 @@ void main() { reset(userRepositoryMock); UserRepositoryMock.stubGetPasswordException( userRepositoryMock); + UserRepositoryMock.stubMonETSUser( + userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); expect(manager.getCoursesActivities(), throwsA(isInstanceOf())); @@ -282,6 +284,7 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesActivitiesCacheKey), + userRepositoryMock.monETSUser, userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); @@ -733,6 +736,8 @@ void main() { reset(userRepositoryMock); UserRepositoryMock.stubGetPasswordException( userRepositoryMock); + UserRepositoryMock.stubMonETSUser( + userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); expect(manager.getScheduleActivities(), throwsA(isInstanceOf())); @@ -747,6 +752,7 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.scheduleActivitiesCacheKey), + userRepositoryMock.monETSUser, userRepositoryMock.getPassword(), analyticsServiceMock.logError(CourseRepository.tag, any, any, any) ]); @@ -1431,6 +1437,7 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), + userRepositoryMock.monETSUser, userRepositoryMock.getPassword(), userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), @@ -1461,6 +1468,7 @@ void main() { verifyInOrder([ cacheManagerMock.get(CourseRepository.coursesCacheKey), + userRepositoryMock.monETSUser, userRepositoryMock.getPassword(), userRepositoryMock.monETSUser, signetsApiMock.getCourses(username: username, password: password), @@ -1906,6 +1914,7 @@ void main() { analyticsServiceMock.logError(CourseRepository.tag, any, any, any)); verifyInOrder([ + userRepositoryMock.monETSUser, userRepositoryMock.getPassword(), userRepositoryMock.monETSUser, signetsApiMock.getCourseSummary( From bbb3f0581667107a23b486ceb33d7ab56fd813c3 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 21:23:50 -0500 Subject: [PATCH 23/62] Fix QuickLinkRepository tests --- lib/core/models/quick_link_data.dart | 3 --- test/mock/managers/cache_manager_mock.dart | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/core/models/quick_link_data.dart b/lib/core/models/quick_link_data.dart index bda323c9f..487e8c480 100644 --- a/lib/core/models/quick_link_data.dart +++ b/lib/core/models/quick_link_data.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - class QuickLinkData { final int id; final int index; diff --git a/test/mock/managers/cache_manager_mock.dart b/test/mock/managers/cache_manager_mock.dart index ca7a00826..33e4923f5 100644 --- a/test/mock/managers/cache_manager_mock.dart +++ b/test/mock/managers/cache_manager_mock.dart @@ -27,7 +27,7 @@ class CacheManagerMock extends MockCacheManager { static void stubUpdateException(CacheManagerMock mock, String key, {Exception exceptionToThrow = const CacheException(prefix: 'CacheException', message: '')}) { - when(mock.update(key, '')).thenThrow(exceptionToThrow); + when(mock.update(key, any)).thenThrow(exceptionToThrow); } /// Stub a exception while calling the delete function of [mock] when [key] is used. From e2982b6095fe902c74f1fd12172e173ff89f44dc Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 21:43:06 -0500 Subject: [PATCH 24/62] Fix SettingsManagerTests --- lib/core/managers/settings_manager.dart | 3 +- test/managers/settings_manager_test.dart | 30 ++++++++++++------- .../services/preferences_service_mock.dart | 8 ++--- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/lib/core/managers/settings_manager.dart b/lib/core/managers/settings_manager.dart index 699c05e31..b3c3dd177 100644 --- a/lib/core/managers/settings_manager.dart +++ b/lib/core/managers/settings_manager.dart @@ -166,7 +166,8 @@ class SettingsManager with ChangeNotifier { .getString(PreferencesFlag.scheduleCalendarFormat) .then((value) => value == null ? CalendarFormat.week - : EnumToString.fromString(CalendarFormat.values, value)); + : EnumToString.fromString(CalendarFormat.values, value) + ?? CalendarFormat.week); settings.putIfAbsent( PreferencesFlag.scheduleCalendarFormat, () => calendarFormat); diff --git a/test/managers/settings_manager_test.dart b/test/managers/settings_manager_test.dart index 5767c6ec4..4a4b136d2 100644 --- a/test/managers/settings_manager_test.dart +++ b/test/managers/settings_manager_test.dart @@ -47,22 +47,28 @@ void main() { // Stubs the answer of the preferences services PreferencesServiceMock.stubGetString( preferencesServiceMock, - PreferencesFlag.scheduleStartWeekday); + PreferencesFlag.scheduleStartWeekday, + toReturn: null); PreferencesServiceMock.stubGetString( preferencesServiceMock, - PreferencesFlag.scheduleOtherWeekday); + PreferencesFlag.scheduleOtherWeekday, + toReturn: null); PreferencesServiceMock.stubGetString( preferencesServiceMock, - PreferencesFlag.scheduleCalendarFormat); + PreferencesFlag.scheduleCalendarFormat, + toReturn: null); PreferencesServiceMock.stubGetBool( preferencesServiceMock, - PreferencesFlag.scheduleShowTodayBtn); + PreferencesFlag.scheduleShowTodayBtn, + toReturn: null); PreferencesServiceMock.stubGetBool( preferencesServiceMock, - PreferencesFlag.scheduleListView); + PreferencesFlag.scheduleListView, + toReturn: null); PreferencesServiceMock.stubGetBool( preferencesServiceMock, - PreferencesFlag.scheduleShowWeekEvents); + PreferencesFlag.scheduleShowWeekEvents, + toReturn: null); RemoteConfigServiceMock.stubGetCalendarViewEnabled( remoteConfigServiceMock); @@ -412,16 +418,20 @@ void main() { test("validate default behaviour", () async { PreferencesServiceMock.stubGetInt( preferencesServiceMock, - PreferencesFlag.aboutUsCard); + PreferencesFlag.aboutUsCard, + toReturn: null); PreferencesServiceMock.stubGetInt( preferencesServiceMock, - PreferencesFlag.scheduleCard); + PreferencesFlag.scheduleCard, + toReturn: null); PreferencesServiceMock.stubGetInt( preferencesServiceMock, - PreferencesFlag.progressBarCard); + PreferencesFlag.progressBarCard, + toReturn: null); PreferencesServiceMock.stubGetInt( preferencesServiceMock, - PreferencesFlag.gradesCard); + PreferencesFlag.gradesCard, + toReturn: null); // Cards final Map expected = { diff --git a/test/mock/services/preferences_service_mock.dart b/test/mock/services/preferences_service_mock.dart index f38d7c42a..c2b7fb0a5 100644 --- a/test/mock/services/preferences_service_mock.dart +++ b/test/mock/services/preferences_service_mock.dart @@ -31,19 +31,19 @@ class PreferencesServiceMock extends MockPreferencesService { /// Stub the answer of [getString] when the [flag] is used. static void stubGetString(PreferencesServiceMock mock, PreferencesFlag flag, - {String toReturn = "test"}) { + {String? toReturn = "test"}) { when(mock.getString(flag)).thenAnswer((_) async => toReturn); } /// Stub the answer of [getString] when the [flag] is used. static void stubGetInt(PreferencesServiceMock mock, PreferencesFlag flag, - {int toReturn = 1}) { + {int? toReturn = 1}) { when(mock.getInt(flag)).thenAnswer((_) async => toReturn); } /// Stub the answer of [getBool] when the [flag] is used. static void stubGetBool(PreferencesServiceMock mock, PreferencesFlag flag, - {bool toReturn = true}) { + {bool? toReturn = true}) { when(mock.getBool(flag)).thenAnswer((_) async => toReturn); } @@ -63,7 +63,7 @@ class PreferencesServiceMock extends MockPreferencesService { /// Stub to throw an [Exception] when the getInt /// will be called with this [flag] static void stubException(PreferencesServiceMock mock, PreferencesFlag flag, - {bool toReturn = true}) { + {bool? toReturn = true}) { when(mock.getInt(flag)).thenThrow(Exception()); } } From 06e1bab32acf432f535b6702f510ec7d5af3373f Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 4 Jan 2024 23:15:17 -0500 Subject: [PATCH 25/62] Fix user repository tests --- lib/core/managers/user_repository.dart | 5 +--- test/managers/user_repository_test.dart | 37 +++++++++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/core/managers/user_repository.dart b/lib/core/managers/user_repository.dart index fd2061d1a..f0da6fcf8 100644 --- a/lib/core/managers/user_repository.dart +++ b/lib/core/managers/user_repository.dart @@ -186,9 +186,6 @@ class UserRepository { try { final password = await _secureStorage.read(key: passwordSecureKey); if(password == null) { - await _secureStorage.deleteAll(); - _analyticsService.logError(tag, - "getPassword - $passwordSecureKey not found"); throw const ApiException(prefix: tag, message: "Not authenticated"); } return password; @@ -207,7 +204,7 @@ class UserRepository { // Force fromCacheOnly mode when user has no connectivity if (!(await _networkingService.hasConnectivity())) { // ignore: parameter_assignments - fromCacheOnly = true; + fromCacheOnly = !await _networkingService.hasConnectivity(); } // Load the programs from the cache if the list doesn't exist diff --git a/test/managers/user_repository_test.dart b/test/managers/user_repository_test.dart index bffd1c724..e55b8433f 100644 --- a/test/managers/user_repository_test.dart +++ b/test/managers/user_repository_test.dart @@ -526,6 +526,8 @@ void main() { reset(cacheManagerMock); CacheManagerMock.stubGetException( cacheManagerMock, UserRepository.programsCacheKey); + FlutterSecureStorageMock.stubRead(secureStorageMock, + key: UserRepository.passwordSecureKey, valueToReturn: ''); expect(manager.programs, isNull); final results = await manager.getPrograms(); @@ -535,7 +537,7 @@ void main() { expect(manager.programs, []); verify(cacheManagerMock.get(UserRepository.programsCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verifyNever(cacheManagerMock.update( UserRepository.programsCacheKey, jsonEncode(programs))); }); @@ -545,6 +547,8 @@ void main() { reset(cacheManagerMock); CacheManagerMock.stubGet(cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); + FlutterSecureStorageMock.stubRead(secureStorageMock, + key: UserRepository.passwordSecureKey, valueToReturn: ''); // Stub SignetsApi answer to test only the cache retrieving reset(signetsApiMock); @@ -560,7 +564,7 @@ void main() { reason: 'The programs list should now be loaded.'); verify(cacheManagerMock.get(UserRepository.programsCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verify(cacheManagerMock.update( UserRepository.programsCacheKey, jsonEncode(programs))); }); @@ -574,6 +578,8 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetProgramsException( signetsApiMock, username); + FlutterSecureStorageMock.stubRead(secureStorageMock, + key: UserRepository.passwordSecureKey, valueToReturn: ''); expect(manager.programs, isNull); expect(manager.getPrograms(), throwsA(isInstanceOf())); @@ -586,7 +592,7 @@ void main() { analyticsServiceMock.logError(UserRepository.tag, any, any, any)); verify(cacheManagerMock.get(UserRepository.programsCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); verifyNever(cacheManagerMock.update(UserRepository.programsCacheKey, any)); @@ -601,6 +607,8 @@ void main() { // Stub to simulate exception when updating cache CacheManagerMock.stubUpdateException( cacheManagerMock, UserRepository.programsCacheKey); + FlutterSecureStorageMock.stubRead(secureStorageMock, + key: UserRepository.passwordSecureKey, valueToReturn: ''); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetPrograms( @@ -634,6 +642,11 @@ void main() { firstName: 'John', lastName: 'Doe', permanentCode: 'DOEJ00000000'); + final ProfileStudent defaultInfo = ProfileStudent( + balance: '', + firstName: '', + lastName: '', + permanentCode: ''); const String username = "username"; @@ -647,6 +660,9 @@ void main() { MonETSAPIClientMock.stubAuthenticate( monETSApiMock, user); + + FlutterSecureStorageMock.stubRead(secureStorageMock, + key: UserRepository.passwordSecureKey, valueToReturn: ''); // Result is true expect( @@ -656,8 +672,7 @@ void main() { // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetInfo( - // ignore: cast_nullable_to_non_nullable - signetsApiMock, username, any as ProfileStudent); + signetsApiMock, username, defaultInfo); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -685,11 +700,11 @@ void main() { expect(manager.info, isNull); final results = await manager.getInfo(); - expect(results, isNull); - expect(manager.info, isNull); + expect(results, defaultInfo); + expect(manager.info, defaultInfo); verify(cacheManagerMock.get(UserRepository.infoCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verifyNever( cacheManagerMock.update(UserRepository.infoCacheKey, jsonEncode(info))); }); @@ -719,7 +734,7 @@ void main() { reason: 'The new info should now be loaded.'); verify(cacheManagerMock.get(UserRepository.infoCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verify(cacheManagerMock.update( UserRepository.infoCacheKey, jsonEncode(anotherInfo))); }); @@ -739,7 +754,7 @@ void main() { reason: 'The info should not have any duplicata..'); verify(cacheManagerMock.get(UserRepository.infoCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verifyNever( cacheManagerMock.update(UserRepository.infoCacheKey, jsonEncode(info))); }); @@ -762,7 +777,7 @@ void main() { analyticsServiceMock.logError(UserRepository.tag, any, any, any)); verify(cacheManagerMock.get(UserRepository.infoCacheKey)); - verify(manager.getPassword()); + verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); verifyNever(cacheManagerMock.update(UserRepository.infoCacheKey, any)); From bccb64c07456baad9aa99ed7ab7857bf53609a98 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sun, 7 Jan 2024 22:08:36 -0500 Subject: [PATCH 26/62] Fix GradeEvaluationTile tests --- lib/ui/widgets/grade_evaluation_tile.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/widgets/grade_evaluation_tile.dart b/lib/ui/widgets/grade_evaluation_tile.dart index 00a603a5d..8b05bf832 100644 --- a/lib/ui/widgets/grade_evaluation_tile.dart +++ b/lib/ui/widgets/grade_evaluation_tile.dart @@ -271,7 +271,7 @@ class _GradeEvaluationTileState extends State double getGradeInDecimal(double grade, double maxGrade) => grade / maxGrade; String validateResult(BuildContext context, String? result) { - if (result != null) { + if (result != "null" && result != null) { return result; } From 112f0505d882744d57ecb336f58107eb6a42cae9 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sun, 7 Jan 2024 23:08:53 -0500 Subject: [PATCH 27/62] Fix code problems --- lib/core/managers/settings_manager.dart | 4 ++-- lib/core/models/emergency_procedure.dart | 3 --- lib/core/models/faq_questions.dart | 3 --- lib/core/models/group_discovery.dart | 3 --- lib/core/models/widget_models.dart | 3 --- lib/core/viewmodels/choose_language_viewmodel.dart | 1 - lib/core/viewmodels/login_viewmodel.dart | 1 - lib/ui/views/grades_view.dart | 4 +--- test/helpers.dart | 2 +- test/ui/widgets/password_text_field_test.dart | 4 +++- test/viewmodels/startup_viewmodel_test.dart | 4 ++-- 11 files changed, 9 insertions(+), 23 deletions(-) diff --git a/lib/core/managers/settings_manager.dart b/lib/core/managers/settings_manager.dart index b3c3dd177..035ebd8bb 100644 --- a/lib/core/managers/settings_manager.dart +++ b/lib/core/managers/settings_manager.dart @@ -211,10 +211,10 @@ class SettingsManager with ChangeNotifier { } /// Add/update the value of [flag] - Future setString(PreferencesFlag flag, String value) async { + Future setString(PreferencesFlag flag, String? value) async { // Log the event _analyticsService.logEvent( - "${tag}_${EnumToString.convertToString(flag)}", value); + "${tag}_${EnumToString.convertToString(flag)}", value.toString()); if (value == null) { return _preferencesService.removePreferencesFlag(flag); diff --git a/lib/core/models/emergency_procedure.dart b/lib/core/models/emergency_procedure.dart index 95e8b5ced..3c1ee8daa 100644 --- a/lib/core/models/emergency_procedure.dart +++ b/lib/core/models/emergency_procedure.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - class EmergencyProcedure { final String title; final String detail; diff --git a/lib/core/models/faq_questions.dart b/lib/core/models/faq_questions.dart index 2cb32a558..c73daf468 100644 --- a/lib/core/models/faq_questions.dart +++ b/lib/core/models/faq_questions.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - class QuestionItem { final Map title; final Map description; diff --git a/lib/core/models/group_discovery.dart b/lib/core/models/group_discovery.dart index 85fdfd5bc..8a09af894 100644 --- a/lib/core/models/group_discovery.dart +++ b/lib/core/models/group_discovery.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/material.dart'; - // Project imports: import 'package:notredame/core/models/discovery.dart'; diff --git a/lib/core/models/widget_models.dart b/lib/core/models/widget_models.dart index 69e2c9970..95a2683d3 100644 --- a/lib/core/models/widget_models.dart +++ b/lib/core/models/widget_models.dart @@ -1,6 +1,3 @@ -// Flutter imports: -import 'package:flutter/foundation.dart'; - class GradesWidgetData { static const String keyPrefix = "grade_"; diff --git a/lib/core/viewmodels/choose_language_viewmodel.dart b/lib/core/viewmodels/choose_language_viewmodel.dart index d31a48f82..017b45802 100644 --- a/lib/core/viewmodels/choose_language_viewmodel.dart +++ b/lib/core/viewmodels/choose_language_viewmodel.dart @@ -41,7 +41,6 @@ class ChooseLanguageViewModel extends BaseViewModel { default: throw Exception( 'No valid language for the index $index passed in parameters'); - break; } _navigationService.pop(); diff --git a/lib/core/viewmodels/login_viewmodel.dart b/lib/core/viewmodels/login_viewmodel.dart index 9b0c7bb29..e200a3365 100644 --- a/lib/core/viewmodels/login_viewmodel.dart +++ b/lib/core/viewmodels/login_viewmodel.dart @@ -1,5 +1,4 @@ // Flutter imports: -import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; // Package imports: diff --git a/lib/ui/views/grades_view.dart b/lib/ui/views/grades_view.dart index 983c59408..d362f9eeb 100644 --- a/lib/ui/views/grades_view.dart +++ b/lib/ui/views/grades_view.dart @@ -105,9 +105,7 @@ class _GradesViewState extends State { const SizedBox(height: 16.0), Wrap( children: courses - .map((course) => index == 0 - ? GradeButton(course, showDiscovery: true) - : GradeButton(course, showDiscovery: false)) + .map((course) => GradeButton(course, showDiscovery: index == 0)) .toList(), ), ], diff --git a/test/helpers.dart b/test/helpers.dart index b24b15063..1dfbd1be7 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -139,7 +139,7 @@ InternalInfoServiceMock setupInternalInfoServiceMock() { } /// Load a mock of the [SirenFlutterService] -SirenFlutterService setupSirenFlutterServiceMock() { +SirenFlutterServiceMock setupSirenFlutterServiceMock() { unregister(); final service = SirenFlutterServiceMock(); diff --git a/test/ui/widgets/password_text_field_test.dart b/test/ui/widgets/password_text_field_test.dart index 31a31d8a6..7a2938ea9 100644 --- a/test/ui/widgets/password_text_field_test.dart +++ b/test/ui/widgets/password_text_field_test.dart @@ -17,7 +17,9 @@ void main() { setUpAll(() async { intl = await setupAppIntl(); passwordFormField = PasswordFormField( - validator: (value) {}, + validator: (value) { + return null; + }, onEditionComplete: () {}, ); }); diff --git a/test/viewmodels/startup_viewmodel_test.dart b/test/viewmodels/startup_viewmodel_test.dart index 6f32df692..d700701be 100644 --- a/test/viewmodels/startup_viewmodel_test.dart +++ b/test/viewmodels/startup_viewmodel_test.dart @@ -43,9 +43,9 @@ void main() { userRepositoryMock = setupUserRepositoryMock(); networkingServiceMock = setupNetworkingServiceMock(); internalInfoServiceMock = - setupInternalInfoServiceMock() as InternalInfoServiceMock; + setupInternalInfoServiceMock(); sirenFlutterServiceMock = - setupSirenFlutterServiceMock() as SirenFlutterServiceMock; + setupSirenFlutterServiceMock(); setupLogger(); viewModel = StartUpViewModel(); From 17d042643a344ad8cd710483135c9bf1a8cab805 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sun, 7 Jan 2024 23:33:16 -0500 Subject: [PATCH 28/62] Fix DashboardViewModel tests --- test/viewmodels/dashboard_viewmodel_test.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/viewmodels/dashboard_viewmodel_test.dart b/test/viewmodels/dashboard_viewmodel_test.dart index 748c7ff36..5dd0430eb 100644 --- a/test/viewmodels/dashboard_viewmodel_test.dart +++ b/test/viewmodels/dashboard_viewmodel_test.dart @@ -412,7 +412,7 @@ void main() { verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepositoryMock.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(2); verify(settingsManagerMock.getDashboard()).called(1); }); @@ -447,7 +447,7 @@ void main() { verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepositoryMock.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(2); verify(settingsManagerMock.getDashboard()).called(1); }); @@ -483,7 +483,7 @@ void main() { verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepositoryMock.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(2); verify(settingsManagerMock.getDashboard()).called(1); }); @@ -516,7 +516,7 @@ void main() { verify(courseRepositoryMock.getCoursesActivities(fromCacheOnly: true)) .called(1); - verify(courseRepositoryMock.coursesActivities).called(1); + verify(courseRepositoryMock.coursesActivities).called(2); verify(settingsManagerMock.getDashboard()).called(1); }); From 00ab8278729a9b7e9c6621bb69cc1d7862ad7f29 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 12 Jan 2024 21:04:20 -0500 Subject: [PATCH 29/62] Fix FeedbackViewModelTest --- test/mock/services/github_api_mock.dart | 8 ++++++++ test/viewmodels/feedback_viewmodel_test.dart | 1 + 2 files changed, 9 insertions(+) diff --git a/test/mock/services/github_api_mock.dart b/test/mock/services/github_api_mock.dart index e69491384..ee8f82130 100644 --- a/test/mock/services/github_api_mock.dart +++ b/test/mock/services/github_api_mock.dart @@ -3,6 +3,7 @@ import 'dart:io'; // Package imports: import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:github/github.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -25,4 +26,11 @@ class GithubApiMock extends MockGithubApi { when(client.fetchIssuesByNumbers(any, any)) .thenAnswer((_) async => Future.value(issuesToReturn)); } + + static void stubCreateGithubIssue(GithubApiMock client, Issue toReturn) { + when(client.createGithubIssue(feedbackText: anyNamed("feedbackText"), + fileName: anyNamed("fileName"), feedbackType: anyNamed("feedbackType"), + email: anyNamed("email"))) + .thenAnswer((_) async => Future.value(toReturn)); + } } diff --git a/test/viewmodels/feedback_viewmodel_test.dart b/test/viewmodels/feedback_viewmodel_test.dart index 0b1370b9d..0dffbd270 100644 --- a/test/viewmodels/feedback_viewmodel_test.dart +++ b/test/viewmodels/feedback_viewmodel_test.dart @@ -50,6 +50,7 @@ void main() { setupPreferencesServiceMock(); appIntl = await setupAppIntl(); setupLogger(); + GithubApiMock.stubCreateGithubIssue(githubApiMock, Issue()); viewModel = FeedbackViewModel(intl: appIntl); }); From ab9255aa688e51de2190a175223f92a20340c22e Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 12 Jan 2024 21:15:38 -0500 Subject: [PATCH 30/62] Fix GradeViewModel tests --- test/viewmodels/grades_viewmodel_test.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/viewmodels/grades_viewmodel_test.dart b/test/viewmodels/grades_viewmodel_test.dart index 00ce7877d..0600570b5 100644 --- a/test/viewmodels/grades_viewmodel_test.dart +++ b/test/viewmodels/grades_viewmodel_test.dart @@ -124,6 +124,7 @@ void main() { verifyInOrder([ courseRepositoryMock.getCourses(fromCacheOnly: true), courseRepositoryMock.getCourses(), + courseRepositoryMock.courses, courseRepositoryMock.courses ]); @@ -176,8 +177,9 @@ void main() { expect(viewModel.coursesBySession, coursesBySession); expect(viewModel.sessionOrder, sessionOrder); - verifyInOrder( - [courseRepositoryMock.getCourses(), courseRepositoryMock.courses]); + verifyInOrder([courseRepositoryMock.getCourses(), + courseRepositoryMock.courses, + courseRepositoryMock.courses]); verifyNoMoreInteractions(courseRepositoryMock); }); @@ -213,8 +215,8 @@ void main() { "The list of courses should not change even when an error occurs"); expect(viewModel.sessionOrder, sessionOrder); - verifyInOrder( - [courseRepositoryMock.getCourses(), courseRepositoryMock.courses]); + verifyInOrder([courseRepositoryMock.getCourses(), + courseRepositoryMock.courses, courseRepositoryMock.courses]); verifyNoMoreInteractions(courseRepositoryMock); }); From 3d907e89900639da21bfdd03d0cdfd42ef888f1e Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 12 Jan 2024 21:45:29 -0500 Subject: [PATCH 31/62] Fix UserRepositoryMock tests --- test/mock/managers/user_repository_mock.dart | 4 ++-- test/viewmodels/profile_viewmodel_test.dart | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/mock/managers/user_repository_mock.dart b/test/mock/managers/user_repository_mock.dart index cf07a476e..4fdddd5d4 100644 --- a/test/mock/managers/user_repository_mock.dart +++ b/test/mock/managers/user_repository_mock.dart @@ -53,11 +53,11 @@ class UserRepositoryMock extends MockUserRepository { /// Stub the function [getInfo] of [mock] when called will return [toReturn]. static void stubGetInfo(UserRepositoryMock mock, - {ProfileStudent? toReturn, bool? fromCacheOnly}) { + {required ProfileStudent toReturn, bool? fromCacheOnly}) { when(mock.getInfo( fromCacheOnly: fromCacheOnly ?? anyNamed("fromCacheOnly"))) // ignore: cast_nullable_to_non_nullable - .thenAnswer((_) async => toReturn ?? anyNamed("profileStudent") as ProfileStudent); + .thenAnswer((_) async => toReturn); } /// Stub the function [getInfo] of [mock] when called will throw [toThrow]. diff --git a/test/viewmodels/profile_viewmodel_test.dart b/test/viewmodels/profile_viewmodel_test.dart index 4ff16acc6..afa450b0b 100644 --- a/test/viewmodels/profile_viewmodel_test.dart +++ b/test/viewmodels/profile_viewmodel_test.dart @@ -75,7 +75,7 @@ void main() { test( "first load from cache then call SignetsAPI to get the latest events", () async { - UserRepositoryMock.stubGetInfo(userRepositoryMock); + UserRepositoryMock.stubGetInfo(userRepositoryMock, toReturn: info); UserRepositoryMock.stubGetPrograms( userRepositoryMock); @@ -93,7 +93,8 @@ void main() { test("Signets throw an error while trying to get new events", () async { setupFlutterToastMock(); UserRepositoryMock.stubGetInfo(userRepositoryMock, - fromCacheOnly: true); + fromCacheOnly: true, + toReturn: info); UserRepositoryMock.stubGetInfoException( userRepositoryMock, fromCacheOnly: false); From 1d57405522d9e47b0d1c2bd216acc452a092ffad Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 12 Jan 2024 22:03:59 -0500 Subject: [PATCH 32/62] Fix ScheduleSettingsViewModel tests --- lib/core/viewmodels/schedule_settings_viewmodel.dart | 5 ++++- test/viewmodels/schedule_settings_viewmodel_test.dart | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/core/viewmodels/schedule_settings_viewmodel.dart b/lib/core/viewmodels/schedule_settings_viewmodel.dart index ee922b412..4ed525cfa 100644 --- a/lib/core/viewmodels/schedule_settings_viewmodel.dart +++ b/lib/core/viewmodels/schedule_settings_viewmodel.dart @@ -1,3 +1,6 @@ +// Dart imports: +import 'package:collection/collection.dart'; + // Package imports: import 'package:calendar_view/calendar_view.dart'; import 'package:enum_to_string/enum_to_string.dart'; @@ -188,7 +191,7 @@ class ScheduleSettingsViewModel final scheduleActivityCode = await _settingsManager.getDynamicString( PreferencesFlag.scheduleLaboratoryGroup, courseKey); final scheduleActivity = _scheduleActivitiesByCourse[courseKey] - ?.firstWhere((element) => element.activityCode == scheduleActivityCode); + ?.firstWhereOrNull((element) => element.activityCode == scheduleActivityCode); if (scheduleActivity != null) { _selectedScheduleActivity[courseKey] = scheduleActivity; } diff --git a/test/viewmodels/schedule_settings_viewmodel_test.dart b/test/viewmodels/schedule_settings_viewmodel_test.dart index 3a6216135..9a2f5a7f8 100644 --- a/test/viewmodels/schedule_settings_viewmodel_test.dart +++ b/test/viewmodels/schedule_settings_viewmodel_test.dart @@ -26,7 +26,9 @@ void main() { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.week, PreferencesFlag.scheduleStartWeekday: StartingDayOfWeek.monday, PreferencesFlag.scheduleShowTodayBtn: true, - PreferencesFlag.scheduleShowWeekendDays: false + PreferencesFlag.scheduleShowWeekendDays: false, + PreferencesFlag.scheduleListView: false, + PreferencesFlag.scheduleShowWeekEvents: false }; final List classOneWithLaboratoryABscheduleActivities = [ From 812c59ccd978877bafb6bb9e955f4fef17a9b315 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 12 Jan 2024 22:24:56 -0500 Subject: [PATCH 33/62] Fix ScheduleViewModel tests --- test/viewmodels/schedule_viewmodel_test.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/viewmodels/schedule_viewmodel_test.dart b/test/viewmodels/schedule_viewmodel_test.dart index 6a4adc63a..cbf5cd48d 100644 --- a/test/viewmodels/schedule_viewmodel_test.dart +++ b/test/viewmodels/schedule_viewmodel_test.dart @@ -484,15 +484,24 @@ void main() { group('selectedWeekEvents', () { final Map settingsStartingDayMonday = { PreferencesFlag.scheduleStartWeekday: StartingDayOfWeek.monday, + PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month }; final Map settingsStartingDaySaturday = { PreferencesFlag.scheduleStartWeekday: StartingDayOfWeek.saturday, + PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month + }; + final Map settingsStartingDaySunday = { + PreferencesFlag.scheduleStartWeekday: StartingDayOfWeek.sunday, + PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month }; - test('selectedWeekEvents for starting day sunday', () { + test('selectedWeekEvents for starting day sunday', () async { CourseRepositoryMock.stubCoursesActivities( courseRepositoryMock, toReturn: weekOfActivities); + SettingsManagerMock.stubGetScheduleSettings( + settingsManagerMock, + toReturn: settingsStartingDaySunday); final expected = { DateTime(2020, 1, 5): [gen104], @@ -507,6 +516,7 @@ void main() { // Setting up the viewmodel viewModel.coursesActivities; viewModel.selectedDate = DateTime(2020, 1, 8); + await viewModel.loadSettings(); clearInteractions(courseRepositoryMock); expect(viewModel.selectedWeekEvents(), expected); From 32b1e9d9d74c916278e021cb3d4d12c01a1beb58 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Thu, 18 Jan 2024 22:36:35 -0500 Subject: [PATCH 34/62] Fix GradeDetailsView tests --- test/ui/views/grades_details_view_test.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index 7a69effd0..f73fb34f3 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -112,6 +112,7 @@ void main() { 'has a RefreshIndicator, GradeCircularProgress, three cards and evaluation tiles when a course is valid', (WidgetTester tester) async { setupFlutterToastMock(tester); + CourseRepositoryMock.stubGetCourseSummary(courseRepositoryMock, course, toReturn: course); await tester.pumpWidget(localizedWidget( child: FeatureDiscovery(child: GradesDetailsView(course: course)))); await tester.pumpAndSettle(); @@ -143,7 +144,7 @@ void main() { toReturn: course); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); expect(find.byType(SliverAppBar), findsOneWidget); @@ -164,7 +165,7 @@ void main() { toReturn: course); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); final gesture = await tester From 0c599365e60b93ff1fbc05bf83c2218713fa00dd Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 19 Jan 2024 20:13:22 -0500 Subject: [PATCH 35/62] Fix NotFoundView test --- test/ui/views/not_found_view_test.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/ui/views/not_found_view_test.dart b/test/ui/views/not_found_view_test.dart index 49236e082..0c26d61bb 100644 --- a/test/ui/views/not_found_view_test.dart +++ b/test/ui/views/not_found_view_test.dart @@ -9,7 +9,9 @@ import 'package:flutter_test/flutter_test.dart'; // Project imports: import 'package:notredame/ui/views/not_found_view.dart'; +import 'package:rive/rive.dart'; import '../../helpers.dart'; +import '../../mock/services/rive_animation_service_mock.dart'; void main() { group('NotFoundView - ', () { @@ -17,7 +19,8 @@ void main() { setUp(() async { setupNavigationServiceMock(); setupAnalyticsServiceMock(); - setupRiveAnimationServiceMock(); + final riveAnimationMock = setupRiveAnimationServiceMock(); + RiveAnimationServiceMock.stubLoadRiveFile(riveAnimationMock, 'dot_jumping', RuntimeArtboard()); }); tearDown(() {}); From 455db7e1cdb3281c13d76deb1a27d10a26e4daa7 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sat, 20 Jan 2024 22:40:59 -0500 Subject: [PATCH 36/62] Fix GradeDetailsViewModel tests --- .../viewmodels/grades_details_viewmodel.dart | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/lib/core/viewmodels/grades_details_viewmodel.dart b/lib/core/viewmodels/grades_details_viewmodel.dart index 953190b1c..ad17c6b39 100644 --- a/lib/core/viewmodels/grades_details_viewmodel.dart +++ b/lib/core/viewmodels/grades_details_viewmodel.dart @@ -32,21 +32,15 @@ class GradesDetailsViewModel extends FutureViewModel { @override Future futureToRun() async { - setBusyForObject(course, true); - - // ignore: return_type_invalid_for_catch_error - await _courseRepository - .getCourseSummary(course) - // ignore: return_type_invalid_for_catch_error - .catchError(onError) - .then((value) { - course = value; - }).whenComplete(() { + try { + setBusyForObject(course, true); + course = await _courseRepository.getCourseSummary(course); + notifyListeners(); + } catch(e) { + onError(e); + } finally { setBusyForObject(course, false); - }); - - notifyListeners(); - + } return course; } @@ -66,16 +60,14 @@ class GradesDetailsViewModel extends FutureViewModel { Future refresh() async { try { setBusyForObject(course, true); - await _courseRepository.getCourseSummary(course).then((value) { - course = value; - }); + course = await _courseRepository.getCourseSummary(course); notifyListeners(); - setBusyForObject(course, false); return true; - } on Exception catch (error) { + } catch (error) { onError(error); - setBusyForObject(course, false); return false; + } finally { + setBusyForObject(course, false); } } From 2bc71d7fe5e64c1e392218d1d63a7efe61a8f1e6 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sun, 21 Jan 2024 21:02:00 -0500 Subject: [PATCH 37/62] Fix ScheduleViewModel tests --- lib/core/viewmodels/schedule_viewmodel.dart | 69 +++++++++----------- test/viewmodels/schedule_viewmodel_test.dart | 6 +- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/lib/core/viewmodels/schedule_viewmodel.dart b/lib/core/viewmodels/schedule_viewmodel.dart index 9d01bfe98..22c90f411 100644 --- a/lib/core/viewmodels/schedule_viewmodel.dart +++ b/lib/core/viewmodels/schedule_viewmodel.dart @@ -175,43 +175,37 @@ class ScheduleViewModel extends FutureViewModel> { settings[PreferencesFlag.scheduleListView] as bool; @override - Future> futureToRun() => - _courseRepository.getCoursesActivities(fromCacheOnly: true).then((value) { - setBusyForObject(isLoadingEvents, true); - _courseRepository - .getCoursesActivities() - // ignore: return_type_invalid_for_catch_error - .catchError(onError) - .then((value1) async { - if (value1 != null) { - // Reload the list of activities - coursesActivities; - - await _courseRepository - .getCourses(fromCacheOnly: true) - .then((value2) { - courses = value2; - }); - if (_coursesActivities.isNotEmpty) { - if (calendarFormat == CalendarFormat.week) { - calendarEvents = selectedWeekCalendarEvents(); - } else { - calendarEvents = selectedMonthCalendarEvents(); - } - } + Future> futureToRun() async { + List? activities = await _courseRepository.getCoursesActivities(fromCacheOnly: true); + try { + setBusyForObject(isLoadingEvents, true); + + final fetchedCourseActivities = await _courseRepository.getCoursesActivities(); + if (fetchedCourseActivities != null) { + activities = fetchedCourseActivities; + // Reload the list of activities + coursesActivities; + + courses = await _courseRepository.getCourses(fromCacheOnly: true); + + if (_coursesActivities.isNotEmpty) { + if (calendarFormat == CalendarFormat.week) { + calendarEvents = selectedWeekCalendarEvents(); + } else { + calendarEvents = selectedMonthCalendarEvents(); } - _courseRepository - .getScheduleActivities() - // ignore: return_type_invalid_for_catch_error - .catchError(onError) - .then((value) async { - await assignScheduleActivities(value); - }).whenComplete(() { - setBusyForObject(isLoadingEvents, false); - }); - }); - return value ?? []; - }); + } + } + final scheduleActivities = await _courseRepository.getScheduleActivities(); + await assignScheduleActivities(scheduleActivities); + } catch(e) { + onError(e); + } finally { + setBusyForObject(isLoadingEvents, false); + } + return activities ?? []; + } + Future assignScheduleActivities( List listOfSchedules) async { @@ -351,10 +345,11 @@ class ScheduleViewModel extends FutureViewModel> { try { setBusyForObject(isLoadingEvents, true); await _courseRepository.getCoursesActivities(); - setBusyForObject(isLoadingEvents, false); notifyListeners(); } on Exception catch (error) { onError(error); + } finally { + setBusyForObject(isLoadingEvents, false); } } diff --git a/test/viewmodels/schedule_viewmodel_test.dart b/test/viewmodels/schedule_viewmodel_test.dart index cbf5cd48d..51200d3ae 100644 --- a/test/viewmodels/schedule_viewmodel_test.dart +++ b/test/viewmodels/schedule_viewmodel_test.dart @@ -274,7 +274,11 @@ void main() { verifyInOrder([ courseRepositoryMock.getCoursesActivities(fromCacheOnly: true), - courseRepositoryMock.getCoursesActivities() + courseRepositoryMock.getCoursesActivities(), + courseRepositoryMock.coursesActivities, + courseRepositoryMock.coursesActivities, + courseRepositoryMock.getCourses(fromCacheOnly: true), + courseRepositoryMock.getScheduleActivities(), ]); verifyNoMoreInteractions(courseRepositoryMock); From a7880301e6b2016acef17b764eeb1088dbc8c3f0 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 19:00:44 -0500 Subject: [PATCH 38/62] Remove use of Future OnError --- lib/core/viewmodels/dashboard_viewmodel.dart | 140 +++++++++---------- lib/core/viewmodels/grades_viewmodel.dart | 35 ++--- lib/core/viewmodels/more_viewmodel.dart | 15 +- lib/core/viewmodels/profile_viewmodel.dart | 32 ++--- test/viewmodels/grades_viewmodel_test.dart | 3 +- test/viewmodels/profile_viewmodel_test.dart | 2 + 6 files changed, 112 insertions(+), 115 deletions(-) diff --git a/lib/core/viewmodels/dashboard_viewmodel.dart b/lib/core/viewmodels/dashboard_viewmodel.dart index 45b57076b..ec3fa3979 100644 --- a/lib/core/viewmodels/dashboard_viewmodel.dart +++ b/lib/core/viewmodels/dashboard_viewmodel.dart @@ -361,68 +361,66 @@ class DashboardViewModel extends FutureViewModel> { } Future> futureToRunSessionProgressBar() async { - final progressBarText = + try { + final progressBarText = await _settingsManager.getString(PreferencesFlag.progressBarText) ?? ProgressBarText.daysElapsedWithTotalDays.toString(); - _currentProgressBarText = ProgressBarText.values - .firstWhere((e) => e.toString() == progressBarText); + _currentProgressBarText = ProgressBarText.values + .firstWhere((e) => e.toString() == progressBarText); - setBusyForObject(progress, true); - return _courseRepository - .getSessions() - // ignore: invalid_return_type_for_catch_error - .catchError(onError) - .whenComplete(() { + setBusyForObject(progress, true); + final sessions = await _courseRepository.getSessions(); _sessionDays = getSessionDays(); _progress = getSessionProgress(); + return sessions; + } catch(error) { + onError(error); + } finally { setBusyForObject(progress, false); - }); + } + return []; } Future> futureToRunSchedule() async { - return _courseRepository - .getCoursesActivities(fromCacheOnly: true) - .then((value) { + try { + var courseActivities = await _courseRepository.getCoursesActivities(fromCacheOnly: true); setBusyForObject(_todayDateEvents, true); setBusyForObject(_tomorrowDateEvents, true); _todayDateEvents.clear(); _tomorrowDateEvents.clear(); - final todayDate = _settingsManager.dateTimeNow; - _courseRepository - .getCoursesActivities() - // ignore: return_type_invalid_for_catch_error - .catchError(onError) - .whenComplete(() async { - if (_todayDateEvents.isEmpty && _courseRepository.coursesActivities != null) { - final DateTime tomorrowDate = todayDate.add(const Duration(days: 1)); - // Build the list - for (final CourseActivity course - in _courseRepository.coursesActivities!) { - final DateTime dateOnly = course.startDateTime; - if (isSameDay(todayDate, dateOnly) && - todayDate.compareTo(course.endDateTime) < 0) { - _todayDateEvents.add(course); - } else if (isSameDay(tomorrowDate, dateOnly)) { - _tomorrowDateEvents.add(course); - } + courseActivities = await _courseRepository.getCoursesActivities(); + + if (_todayDateEvents.isEmpty && _courseRepository.coursesActivities != null) { + final DateTime tomorrowDate = todayDate.add(const Duration(days: 1)); + // Build the list + for (final CourseActivity course in _courseRepository.coursesActivities!) { + final DateTime dateOnly = course.startDateTime; + if (isSameDay(todayDate, dateOnly) && + todayDate.compareTo(course.endDateTime) < 0) { + _todayDateEvents.add(course); + } else if (isSameDay(tomorrowDate, dateOnly)) { + _tomorrowDateEvents.add(course); } } - _todayDateEvents - .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); - _tomorrowDateEvents - .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); - - _todayDateEvents = await removeLaboratoryGroup(_todayDateEvents); - _tomorrowDateEvents = await removeLaboratoryGroup(_tomorrowDateEvents); - - setBusyForObject(_todayDateEvents, false); - setBusyForObject(_tomorrowDateEvents, false); - }); + } - return value ?? []; - }); + _todayDateEvents + .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); + _tomorrowDateEvents + .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); + + _todayDateEvents = await removeLaboratoryGroup(_todayDateEvents); + _tomorrowDateEvents = await removeLaboratoryGroup(_tomorrowDateEvents); + return courseActivities ?? []; + } catch(error) { + onError(error); + } finally { + setBusyForObject(_todayDateEvents, false); + setBusyForObject(_tomorrowDateEvents, false); + } + return []; } Future> removeLaboratoryGroup( @@ -492,25 +490,22 @@ class DashboardViewModel extends FutureViewModel> { } /// Get the list of courses for the Grades card. - // ignore: missing_return Future> futureToRunGrades() async { if (!busy(courses)) { - setBusyForObject(courses, true); - if (_courseRepository.sessions == null || - _courseRepository.sessions!.isEmpty) { - // ignore: return_type_invalid_for_catch_error - await _courseRepository.getSessions().catchError(onError); - } + try { + setBusyForObject(courses, true); + if (_courseRepository.sessions == null || + _courseRepository.sessions!.isEmpty) { + await _courseRepository.getSessions(); + } - // Determine current sessions - if (_courseRepository.activeSessions.isEmpty) { - setBusyForObject(courses, false); - return []; - } - final currentSession = _courseRepository.activeSessions.first; + // Determine current sessions + if (_courseRepository.activeSessions.isEmpty) { + return []; + } + final currentSession = _courseRepository.activeSessions.first; - return _courseRepository.getCourses(fromCacheOnly: true).then( - (coursesCached) { + final coursesCached = await _courseRepository.getCourses(fromCacheOnly: true); courses.clear(); for (final Course course in coursesCached) { if (course.session == currentSession.shortName) { @@ -518,21 +513,20 @@ class DashboardViewModel extends FutureViewModel> { } } notifyListeners(); - // ignore: return_type_invalid_for_catch_error - _courseRepository.getCourses().catchError(onError).then((value) { - // Update the courses list - courses.clear(); - for (final Course course in value) { - if (course.session == currentSession.shortName) { - courses.add(course); - } - } - }).whenComplete(() { - setBusyForObject(courses, false); - }); - return courses; - }, onError: onError); + final fetchedCourses = await _courseRepository.getCourses(); + // Update the courses list + courses.clear(); + for (final Course course in fetchedCourses) { + if (course.session == currentSession.shortName) { + courses.add(course); + } + } + } catch (error) { + onError(error); + } finally { + setBusyForObject(courses, false); + } } return courses; } diff --git a/lib/core/viewmodels/grades_viewmodel.dart b/lib/core/viewmodels/grades_viewmodel.dart index 635ad41e4..3ad1d1255 100644 --- a/lib/core/viewmodels/grades_viewmodel.dart +++ b/lib/core/viewmodels/grades_viewmodel.dart @@ -33,22 +33,24 @@ class GradesViewModel extends FutureViewModel>> { GradesViewModel({required AppIntl intl}) : _appIntl = intl; @override - Future>> futureToRun() async => - _courseRepository.getCourses(fromCacheOnly: true).then((coursesCached) { - setBusy(true); - _buildCoursesBySession(coursesCached); - // ignore: return_type_invalid_for_catch_error - _courseRepository.getCourses().catchError(onError).then((value) { - if (_courseRepository.courses != null) { - // Update the courses list - _buildCoursesBySession(_courseRepository.courses!); - } - }).whenComplete(() { - setBusy(false); - }); - - return coursesBySession; - }); + Future>> futureToRun() async { + try { + final coursesCached = await _courseRepository.getCourses(fromCacheOnly: true); + setBusy(true); + _buildCoursesBySession(coursesCached); + await _courseRepository.getCourses(); + if (_courseRepository.courses != null) { + // Update the courses list + _buildCoursesBySession(_courseRepository.courses!); + } + } catch(error) { + onError(error); + } finally { + setBusy(false); + } + return coursesBySession; + } + @override // ignore: type_annotate_public_apis @@ -58,7 +60,6 @@ class GradesViewModel extends FutureViewModel>> { /// Reload the courses from Signets and rebuild the view. Future refresh() async { - // ignore: return_type_invalid_for_catch_error try { await _courseRepository.getCourses(); if(_courseRepository.courses != null) { diff --git a/lib/core/viewmodels/more_viewmodel.dart b/lib/core/viewmodels/more_viewmodel.dart index 0be36a325..e932f0752 100644 --- a/lib/core/viewmodels/more_viewmodel.dart +++ b/lib/core/viewmodels/more_viewmodel.dart @@ -58,13 +58,14 @@ class MoreViewModel extends FutureViewModel { @override Future futureToRun() async { - setBusy(true); - - await PackageInfo.fromPlatform() - .then((value) => _appVersion = value.version) - .onError((error, stackTrace) => 'Error: $error'); - - setBusy(false); + try { + setBusy(true); + await PackageInfo.fromPlatform(); + } catch (error) { + onError(error); + } finally { + setBusy(false); + } return true; } diff --git a/lib/core/viewmodels/profile_viewmodel.dart b/lib/core/viewmodels/profile_viewmodel.dart index e1e5f387d..ecb5cdaca 100644 --- a/lib/core/viewmodels/profile_viewmodel.dart +++ b/lib/core/viewmodels/profile_viewmodel.dart @@ -97,22 +97,22 @@ class ProfileViewModel extends FutureViewModel> { bool isLoadingEvents = false; @override - Future> futureToRun() => _userRepository - .getInfo(fromCacheOnly: true) - .then((value) => _userRepository.getPrograms(fromCacheOnly: true)) - .then((value) { - setBusyForObject(isLoadingEvents, true); - _userRepository - .getInfo() - // ignore: return_type_invalid_for_catch_error - .catchError(onError) - // ignore: return_type_invalid_for_catch_error - .then((value) => _userRepository.getPrograms().catchError(onError)) - .whenComplete(() { - setBusyForObject(isLoadingEvents, false); - }); - return value; - }); + Future> futureToRun() async { + try { + await _userRepository.getInfo(fromCacheOnly: true); + await _userRepository.getPrograms(fromCacheOnly: true); + + setBusyForObject(isLoadingEvents, true); + + await _userRepository.getInfo(); + return await _userRepository.getPrograms(); + } catch (error) { + onError(error); + } finally { + setBusyForObject(isLoadingEvents, false); + } + return _userRepository.programs ?? []; + } Future refresh() async { try { diff --git a/test/viewmodels/grades_viewmodel_test.dart b/test/viewmodels/grades_viewmodel_test.dart index 0600570b5..d5e378372 100644 --- a/test/viewmodels/grades_viewmodel_test.dart +++ b/test/viewmodels/grades_viewmodel_test.dart @@ -215,8 +215,7 @@ void main() { "The list of courses should not change even when an error occurs"); expect(viewModel.sessionOrder, sessionOrder); - verifyInOrder([courseRepositoryMock.getCourses(), - courseRepositoryMock.courses, courseRepositoryMock.courses]); + verifyInOrder([courseRepositoryMock.getCourses()]); verifyNoMoreInteractions(courseRepositoryMock); }); diff --git a/test/viewmodels/profile_viewmodel_test.dart b/test/viewmodels/profile_viewmodel_test.dart index afa450b0b..91356c91e 100644 --- a/test/viewmodels/profile_viewmodel_test.dart +++ b/test/viewmodels/profile_viewmodel_test.dart @@ -85,6 +85,7 @@ void main() { userRepositoryMock.getInfo(fromCacheOnly: true), userRepositoryMock.getPrograms(fromCacheOnly: true), userRepositoryMock.getInfo(), + userRepositoryMock.getPrograms() ]); verifyNoMoreInteractions(userRepositoryMock); @@ -111,6 +112,7 @@ void main() { userRepositoryMock.getInfo(fromCacheOnly: true), userRepositoryMock.getPrograms(fromCacheOnly: true), userRepositoryMock.getInfo(), + userRepositoryMock.programs ]); verifyNoMoreInteractions(userRepositoryMock); From 94eb2daf15c5314cc5c925d748c3348d495d1825 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 20:01:19 -0500 Subject: [PATCH 39/62] Fix ScheduleSettingTest tests --- test/ui/widgets/schedule_settings_test.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/ui/widgets/schedule_settings_test.dart b/test/ui/widgets/schedule_settings_test.dart index da1389fd5..b7255cf74 100644 --- a/test/ui/widgets/schedule_settings_test.dart +++ b/test/ui/widgets/schedule_settings_test.dart @@ -31,7 +31,8 @@ void main() { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.week, PreferencesFlag.scheduleStartWeekday: StartingDayOfWeek.monday, PreferencesFlag.scheduleShowTodayBtn: true, - PreferencesFlag.scheduleListView: true + PreferencesFlag.scheduleListView: true, + PreferencesFlag.scheduleShowWeekEvents: true }; final List classOneWithLaboratoryABscheduleActivities = [ From 9ca3608ce9d7418056fb81d213de2851666440a9 Mon Sep 17 00:00:00 2001 From: apomalyn Date: Fri, 8 Mar 2024 20:12:23 -0500 Subject: [PATCH 40/62] test: Fix settings loading issue refs: #68 --- lib/core/viewmodels/schedule_viewmodel.dart | 13 ++++++++---- lib/ui/views/schedule_view.dart | 22 ++++++++++----------- test/ui/views/schedule_view_test.dart | 2 +- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/core/viewmodels/schedule_viewmodel.dart b/lib/core/viewmodels/schedule_viewmodel.dart index 22c90f411..d24dc95ef 100644 --- a/lib/core/viewmodels/schedule_viewmodel.dart +++ b/lib/core/viewmodels/schedule_viewmodel.dart @@ -171,11 +171,16 @@ class ScheduleViewModel extends FutureViewModel> { bool isLoadingEvents = false; - bool get calendarViewSetting => - settings[PreferencesFlag.scheduleListView] as bool; + bool get calendarViewSetting { + if (busy(settings)) { + return false; + } + return settings[PreferencesFlag.scheduleListView] as bool; + } @override Future> futureToRun() async { + loadSettings(); List? activities = await _courseRepository.getCoursesActivities(fromCacheOnly: true); try { setBusyForObject(isLoadingEvents, true); @@ -238,7 +243,7 @@ class ScheduleViewModel extends FutureViewModel> { } Future loadSettings() async { - setBusy(true); + setBusyForObject(settings, true); settings.clear(); settings.addAll(await _settingsManager.getScheduleSettings()); calendarFormat = @@ -246,7 +251,7 @@ class ScheduleViewModel extends FutureViewModel> { await loadSettingsScheduleActivities(); - setBusy(false); + setBusyForObject(settings, false); } Future loadSettingsScheduleActivities() async { diff --git a/lib/ui/views/schedule_view.dart b/lib/ui/views/schedule_view.dart index c8c35b7c8..0930b82a8 100644 --- a/lib/ui/views/schedule_view.dart +++ b/lib/ui/views/schedule_view.dart @@ -76,11 +76,6 @@ class _ScheduleViewState extends State ViewModelBuilder.reactive( viewModelBuilder: () => ScheduleViewModel( intl: AppIntl.of(context)!, initialSelectedDate: widget.initialDay), - onModelReady: (model) { - if (model.settings.isEmpty) { - model.loadSettings(); - } - }, builder: (context, model, child) => BaseScaffold( isLoading: model.busy(model.isLoadingEvents), isInteractionLimitedWhileLoading: false, @@ -88,14 +83,17 @@ class _ScheduleViewState extends State title: Text(AppIntl.of(context)!.title_schedule), centerTitle: false, automaticallyImplyLeading: false, - actions: _buildActionButtons(model), + actions: + model.busy(model.settings) ? [] : _buildActionButtons(model), ), - body: RefreshIndicator( - child: !model.calendarViewSetting - ? _buildCalendarView(model, context) - : _buildListView(model, context), - onRefresh: () => model.refresh(), - )), + body: model.busy(model.settings) + ? const SizedBox() + : RefreshIndicator( + child: !model.calendarViewSetting + ? _buildCalendarView(model, context) + : _buildListView(model, context), + onRefresh: () => model.refresh(), + )), ); Widget _buildListView(ScheduleViewModel model, BuildContext context) { diff --git a/test/ui/views/schedule_view_test.dart b/test/ui/views/schedule_view_test.dart index eea0269b5..be394122f 100644 --- a/test/ui/views/schedule_view_test.dart +++ b/test/ui/views/schedule_view_test.dart @@ -301,7 +301,7 @@ void main() { await tester.pumpWidget(localizedWidget( child: FeatureDiscovery(child: const ScheduleView()))); - await tester.pumpAndSettle(const Duration(seconds: 1)); + await tester.pumpAndSettle(); // DateFormat has to be after the pumpWidget to correctly load the locale final dateFormat = DateFormat.MMMMEEEEd(); From aa5ebf47fddd378f585aa49f6c0dec932beda4f6 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 20:10:56 -0500 Subject: [PATCH 41/62] Fix DashboardViewModelTest tests --- test/viewmodels/dashboard_viewmodel_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/viewmodels/dashboard_viewmodel_test.dart b/test/viewmodels/dashboard_viewmodel_test.dart index 5dd0430eb..1d223531f 100644 --- a/test/viewmodels/dashboard_viewmodel_test.dart +++ b/test/viewmodels/dashboard_viewmodel_test.dart @@ -926,7 +926,7 @@ void main() { preferencesServiceMock, PreferencesFlag.ratingTimer, toReturn: day); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, PreferencesFlag.hasRatingBeenRequested); + preferencesServiceMock, PreferencesFlag.hasRatingBeenRequested, toReturn: false); expect(await DashboardViewModel.launchInAppReview(), true); From 9962c86fb345016e55f80943f0104b5f7594e4ed Mon Sep 17 00:00:00 2001 From: apomalyn Date: Fri, 8 Mar 2024 20:26:35 -0500 Subject: [PATCH 42/62] test: Fix settings loading issue refs: #68 --- test/viewmodels/schedule_viewmodel_test.dart | 151 ++++++++----------- 1 file changed, 59 insertions(+), 92 deletions(-) diff --git a/test/viewmodels/schedule_viewmodel_test.dart b/test/viewmodels/schedule_viewmodel_test.dart index 51200d3ae..91f16e108 100644 --- a/test/viewmodels/schedule_viewmodel_test.dart +++ b/test/viewmodels/schedule_viewmodel_test.dart @@ -240,6 +240,13 @@ void main() { gen110 ]; + // Some settings + final Map settings = { + PreferencesFlag.scheduleCalendarFormat: CalendarFormat.week, + PreferencesFlag.scheduleStartWeekday: StartingDayOfWeek.monday, + PreferencesFlag.scheduleShowTodayBtn: true + }; + group("ScheduleViewModel - ", () { setUp(() async { // Setting up mocks @@ -258,21 +265,19 @@ void main() { test( "first load from cache than call SignetsAPI to get the latest events", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, + toReturn: settings); expect(await viewModel.futureToRun(), []); verifyInOrder([ + settingsManagerMock.getScheduleSettings(), courseRepositoryMock.getCoursesActivities(fromCacheOnly: true), courseRepositoryMock.getCoursesActivities(), courseRepositoryMock.coursesActivities, @@ -287,20 +292,17 @@ void main() { test("Signets throw an error while trying to get new events", () async { setupFlutterToastMock(); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); CourseRepositoryMock.stubGetCoursesActivitiesException( courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, + toReturn: settings); expect(await viewModel.futureToRun(), [], reason: "Even if SignetsAPI fails we should receives a list."); @@ -309,6 +311,7 @@ void main() { await untilCalled(courseRepositoryMock.getCoursesActivities()); verifyInOrder([ + settingsManagerMock.getScheduleSettings(), courseRepositoryMock.getCoursesActivities(fromCacheOnly: true), courseRepositoryMock.getCoursesActivities() ]); @@ -320,8 +323,7 @@ void main() { group("coursesActivities - ", () { test("build the list of activities sort by date", () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); final expected = { @@ -340,14 +342,11 @@ void main() { test( 'scheduleActivityIsSelected returns true when activityDescription is not labA or labB', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); await viewModel.assignScheduleActivities([ @@ -371,8 +370,7 @@ void main() { test( 'scheduleActivityIsSelected returns true when the course does not have an activity', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesLabs); SettingsManagerMock.stubGetDynamicString( @@ -418,8 +416,7 @@ void main() { group("coursesActivitiesFor - ", () { test("Get the correct list of activities for the specified day", () { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); final expected = [gen102, gen103]; @@ -433,8 +430,7 @@ void main() { }); test("If the day doesn't have any events, return an empty list.", () { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); expect(viewModel.coursesActivitiesFor(DateTime(2020, 1, 3)), isEmpty, @@ -449,8 +445,7 @@ void main() { group("selectedDateEvents", () { test("The events of the date currently selected are return", () { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); final expected = [gen102, gen103]; @@ -467,8 +462,7 @@ void main() { }); test("The events of the date currently selected are return", () { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); final expected = []; @@ -500,11 +494,9 @@ void main() { }; test('selectedWeekEvents for starting day sunday', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: weekOfActivities); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settingsStartingDaySunday); final expected = { @@ -527,11 +519,9 @@ void main() { }); test('selectedWeekEvents for starting day monday', () async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settingsStartingDayMonday); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: weekOfActivities); final expected = { @@ -553,11 +543,9 @@ void main() { }); test('selectedWeekEvents for starting day saturday', () async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settingsStartingDaySaturday); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: weekOfActivities); final expected = { @@ -583,8 +571,7 @@ void main() { test( 'Call SignetsAPI to get the coursesActivities than reload the coursesActivities', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); await viewModel.refresh(); @@ -608,8 +595,7 @@ void main() { group('loadSettings -', () { test('calendarFormat changing', () async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month }); @@ -660,22 +646,15 @@ void main() { test( 'loadSettingsScheduleActivities - test when one is selected from one group', () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, toReturn: activities); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - fromCacheOnly: true, - toReturn: courses); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + fromCacheOnly: true, toReturn: courses); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: { PreferencesFlag.scheduleCalendarFormat: CalendarFormat.month }); @@ -719,14 +698,11 @@ void main() { test( 'coursesActivities - should fill coursesActivities with the activities', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); await viewModel.assignScheduleActivities([ @@ -752,14 +728,11 @@ void main() { test( 'coursesActivities - should fill coursesActivities with the activities with no LabB for GEN103', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); await viewModel.assignScheduleActivities([ @@ -785,14 +758,11 @@ void main() { test( 'coursesActivities - should fill coursesActivities with the activities with no LabA for GEN103', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupB); await viewModel.assignScheduleActivities([ @@ -818,14 +788,11 @@ void main() { test( 'coursesActivities - should fill coursesActivities with all the activities if none are selected', () async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103"); await viewModel.assignScheduleActivities([]); From 36b433b7eb3577eb1c28c12552abf8c3c1e74be2 Mon Sep 17 00:00:00 2001 From: apomalyn Date: Fri, 8 Mar 2024 21:17:30 -0500 Subject: [PATCH 43/62] test: Remove useless test refs: #68 --- test/ui/views/schedule_view_test.dart | 168 ++++++-------------------- 1 file changed, 39 insertions(+), 129 deletions(-) diff --git a/test/ui/views/schedule_view_test.dart b/test/ui/views/schedule_view_test.dart index be394122f..41d6b3b28 100644 --- a/test/ui/views/schedule_view_test.dart +++ b/test/ui/views/schedule_view_test.dart @@ -93,8 +93,7 @@ void main() { PreferencesFlag.scheduleListView: true, }; - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock); RemoteConfigServiceMock.stubGetCalendarViewEnabled( remoteConfigServiceMock); }); @@ -104,20 +103,14 @@ void main() { (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -131,26 +124,20 @@ void main() { testWidgets("default view (no events), showTodayButton disabled", (WidgetTester tester) async { - SettingsManagerMock.stubGetBool(settingsManagerMock, - PreferencesFlag.discoverySchedule); + SettingsManagerMock.stubGetBool( + settingsManagerMock, PreferencesFlag.discoverySchedule); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); settings[PreferencesFlag.scheduleShowTodayBtn] = false; - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -165,21 +152,15 @@ void main() { testWidgets("view with events, day with events selected", (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: [activityYesterday, activityToday, activityTomorrow]); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -197,21 +178,15 @@ void main() { (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: [activityYesterday, activityTomorrow]); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( @@ -227,21 +202,15 @@ void main() { (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: [activityYesterday, activityTomorrow]); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); final testingDate = DateTime(2020); @@ -278,78 +247,19 @@ void main() { }, skip: !Platform.isLinux); group("interactions - ", () { - testWidgets("tap on today button to return on today", - (WidgetTester tester) async { - tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, - toReturn: [activityToday]); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, - fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, - toReturn: settings); - - await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const ScheduleView()))); - await tester.pumpAndSettle(); - - // DateFormat has to be after the pumpWidget to correctly load the locale - final dateFormat = DateFormat.MMMMEEEEd(); - final otherDay = DateTime.now().weekday == 7 - ? DateTime.now().subtract(const Duration(days: 1)) - : DateTime.now().add(const Duration(days: 1)); - - expect(find.text(dateFormat.format(DateTime.now())), findsOneWidget); - - // Tap on the day before today if sunday, otherwise tap on the next day - await tester.tap(find.descendant( - of: find.byType(TableCalendar), - matching: find.text("${otherDay.day}"))); - - // Reload view - await tester.pump(); - - expect(find.text(dateFormat.format(otherDay)), findsOneWidget, - reason: "Should be another day than today"); - - // Tap on "today" button. - await tester.tap(find.byIcon(Icons.today)); - await tester.pump(); - - expect(find.text(dateFormat.format(DateTime.now())), findsOneWidget, - reason: - "Should display today date because we tapped on today button."); - }); - testWidgets("tap on settings button to open the schedule settings", (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: [activityToday]); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester.pumpWidget(localizedWidget( From 6dcc322cae5ad808e626a565e93f5d5406e51578 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 21:54:56 -0500 Subject: [PATCH 44/62] Fix ScheduleViewModel marker not appearing --- lib/core/viewmodels/schedule_viewmodel.dart | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/core/viewmodels/schedule_viewmodel.dart b/lib/core/viewmodels/schedule_viewmodel.dart index d24dc95ef..bead03abb 100644 --- a/lib/core/viewmodels/schedule_viewmodel.dart +++ b/lib/core/viewmodels/schedule_viewmodel.dart @@ -332,11 +332,22 @@ class ScheduleViewModel extends FutureViewModel> { coursesActivities; } - List activities = []; - if (_coursesActivities.containsKey(date)) { - activities = _coursesActivities[date] ?? []; + // TODO: maybe use containsKey and put the _courseActivities key to a string... + DateTime? dateInArray; + final courseActivitiesContains = _coursesActivities.keys.any((element) { + dateInArray = element; + return isSameDay(element, date); + }); + if(courseActivitiesContains) { + return _coursesActivities[dateInArray] ?? []; } - return activities; + return []; + + // List activities = []; + // if (_coursesActivities.containsKey(date)) { + // activities = _coursesActivities[date] ?? []; + // } + // return activities; } Future setCalendarFormat(CalendarFormat format) async { From 37f961fc5289e82bf710f1272e1d68a91b56a9da Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 22:15:37 -0500 Subject: [PATCH 45/62] Fix courses not appearing when no review --- lib/core/managers/course_repository.dart | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/core/managers/course_repository.dart b/lib/core/managers/course_repository.dart index cf963dd6b..d90e24c68 100644 --- a/lib/core/managers/course_repository.dart +++ b/lib/core/managers/course_repository.dart @@ -505,12 +505,10 @@ class CourseRepository { /// Get the evaluation for a course or null if not found. CourseReview? _getReviewForCourse( Course course, Map> reviews) { - if (reviews.containsKey(course.session)) { - return reviews[course.session]!.firstWhere( - (element) => - element.acronym == course.acronym && - element.group == course.group); - } - return null; + final review = reviews[course.session]?.where((element) => + element.acronym == course.acronym && element.group == course.group); + return review?.length == 1 + ? review?.first + : null; } } From b82a43a3fb87126312ff6208a3e2468e88c1ebd1 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 22:26:46 -0500 Subject: [PATCH 46/62] Update CI and documentation --- .github/workflows/dev-workflow.yaml | 9 +++++++-- .github/workflows/master-workflow.yaml | 9 +++++++-- .github/workflows/release-workflow.yaml | 5 ++++- README.md | 5 +++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev-workflow.yaml b/.github/workflows/dev-workflow.yaml index 64063b4d5..53de5a7e1 100644 --- a/.github/workflows/dev-workflow.yaml +++ b/.github/workflows/dev-workflow.yaml @@ -52,7 +52,9 @@ jobs: ENCRYPTED_GOOGLE_SERVICE_PASSWORD: ${{ secrets.ENCRYPTED_GOOGLE_SERVICE_PASSWORD }} # Get flutter dependencies. - - run: flutter pub get + - run: | + flutter pub get + dart run build_runner build # Check the format of the code and commit the formatted files. - name: Format files in lib and test directories @@ -174,6 +176,7 @@ jobs: if: matrix.target == 'iOS' run: | flutter pub get + dart run build_runner build cd ios pod update flutter clean @@ -197,7 +200,9 @@ jobs: exit 1 # Get dependencies and decrypt needed files. - - run: flutter pub get + - run: | + flutter pub get + dart run build_runner build - name: Decrypt SignETS certificate and Google Services files run: | diff --git a/.github/workflows/master-workflow.yaml b/.github/workflows/master-workflow.yaml index c03f4a72c..de751b3ef 100644 --- a/.github/workflows/master-workflow.yaml +++ b/.github/workflows/master-workflow.yaml @@ -85,7 +85,9 @@ jobs: ENCRYPTED_GOOGLE_SERVICE_PASSWORD: ${{ secrets.ENCRYPTED_GOOGLE_SERVICE_PASSWORD }} # Get flutter dependencies. - - run: flutter pub get + - run : | + flutter pub get + dart run build_runner build # Check if the code has any errors/warnings - name: Analyze code @@ -176,12 +178,15 @@ jobs: if: matrix.target == 'iOS' run: | flutter pub get + dart run build_runner build cd ios pod install flutter clean # Get dependencies and decrypt needed files. - - run: flutter pub get + - run: | + flutter pub get + dart run build_runner build - name: Decrypt SignETS certificate and Google Services files run: | diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index be43d384b..2bf9a93ea 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -49,13 +49,16 @@ jobs: if: matrix.target == 'iOS' run: | flutter pub get + dart run build_runner build cd ios pod install flutter clean - run: flutter doctor -v # Get dependencies and decrypt needed files. - - run: flutter pub get + - run: | + flutter pub get + dart run build_runner build - name: Decrypt certificates files run: | diff --git a/README.md b/README.md index 038774f23..bee468231 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,11 @@ chmod +x ./env_variables.sh flutter pub get ``` +- To generate the mocks: +``` +dart run build_runner build +``` + ## Add environment variable for API_KEY - To add the Google Maps API TOKEN and the GitHub API TOKEN, you need to rename the file `.env.template` into `.env`. In From d8a154bf2655043d16ce318b9ad8043fccfd1b03 Mon Sep 17 00:00:00 2001 From: XavierPaquet-Rapold Date: Sat, 9 Mar 2024 03:29:18 +0000 Subject: [PATCH 47/62] [BOT] Applying version. --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 92ca57005..c65629c96 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ description: The 4th generation of ÉTSMobile, the main gateway between the Éco # pub.dev using `pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 4.33.2+1 +version: 4.34.0+1 environment: sdk: ">=2.12.0 <3.0.0" From 2575af03d3adf0ac9ce8d81305d37efd320508a4 Mon Sep 17 00:00:00 2001 From: clubapplets-server Date: Sat, 9 Mar 2024 03:31:08 +0000 Subject: [PATCH 48/62] [BOT] Applying format. --- lib/core/managers/course_repository.dart | 41 ++- lib/core/managers/settings_manager.dart | 9 +- lib/core/managers/user_repository.dart | 21 +- lib/core/models/feedback_issue.dart | 2 +- lib/core/services/analytics_service.dart | 3 +- lib/core/services/navigation_service.dart | 16 +- lib/core/services/preferences_service.dart | 2 +- lib/core/viewmodels/dashboard_viewmodel.dart | 35 +- lib/core/viewmodels/feedback_viewmodel.dart | 3 +- .../viewmodels/grades_details_viewmodel.dart | 2 +- lib/core/viewmodels/grades_viewmodel.dart | 8 +- lib/core/viewmodels/not_found_viewmodel.dart | 2 +- .../schedule_settings_viewmodel.dart | 5 +- lib/core/viewmodels/schedule_viewmodel.dart | 17 +- lib/core/viewmodels/settings_viewmodel.dart | 2 +- lib/ui/utils/discovery_components.dart | 23 +- lib/ui/views/contributors_view.dart | 7 +- lib/ui/views/dashboard_view.dart | 16 +- lib/ui/views/emergency_view.dart | 4 +- lib/ui/views/faq_view.dart | 4 +- lib/ui/views/feedback_view.dart | 40 +- lib/ui/views/grade_details_view.dart | 28 +- lib/ui/views/grades_view.dart | 3 +- lib/ui/views/login_view.dart | 8 +- lib/ui/views/more_view.dart | 4 +- lib/ui/views/not_found_view.dart | 4 +- lib/ui/views/outage_view.dart | 6 +- lib/ui/views/profile_view.dart | 8 +- lib/ui/widgets/grade_button.dart | 7 +- lib/ui/widgets/grade_circular_progress.dart | 4 +- lib/ui/widgets/grade_evaluation_tile.dart | 4 +- lib/ui/widgets/grade_not_available.dart | 4 +- lib/ui/widgets/password_text_field.dart | 3 +- lib/ui/widgets/schedule_settings.dart | 3 +- test/managers/course_repository_test.dart | 207 +++++------ test/managers/quick_link_repository_test.dart | 8 +- test/managers/settings_manager_test.dart | 102 +++--- test/managers/user_repository_test.dart | 134 +++---- .../mock/managers/course_repository_mock.dart | 22 +- test/mock/managers/settings_manager_mock.dart | 3 +- test/mock/services/github_api_mock.dart | 8 +- test/services/app_widget_service_test.dart | 2 +- test/ui/views/dashboard_view_test.dart | 280 ++++++-------- test/ui/views/grades_details_view_test.dart | 12 +- test/ui/views/grades_view_test.dart | 42 +-- test/ui/views/more_view_test.dart | 9 +- test/ui/views/not_found_view_test.dart | 3 +- test/ui/views/profile_view_test.dart | 3 +- test/ui/views/quick_links_view_test.dart | 3 +- test/ui/views/student_view_test.dart | 9 +- test/ui/widgets/bottom_bar_test.dart | 10 +- test/ui/widgets/grade_button_test.dart | 33 +- .../widgets/grade_evaluation_tile_test.dart | 6 +- test/ui/widgets/password_text_field_test.dart | 9 +- test/ui/widgets/schedule_settings_test.dart | 50 +-- .../choose_language_viewmodel_test.dart | 6 +- test/viewmodels/dashboard_viewmodel_test.dart | 342 +++++++----------- test/viewmodels/feedback_viewmodel_test.dart | 3 +- .../grades_details_viewmodel_test.dart | 2 +- test/viewmodels/grades_viewmodel_test.dart | 59 ++- test/viewmodels/login_viewmodel_test.dart | 4 +- test/viewmodels/more_viewmodel_test.dart | 3 +- test/viewmodels/not_found_viewmodel_test.dart | 15 +- test/viewmodels/profile_viewmodel_test.dart | 30 +- .../schedule_settings_viewmodel_test.dart | 56 ++- test/viewmodels/settings_viewmodel_test.dart | 3 +- test/viewmodels/startup_viewmodel_test.dart | 9 +- .../web_link_card_viewmodel_test.dart | 8 +- 68 files changed, 784 insertions(+), 1059 deletions(-) diff --git a/lib/core/managers/course_repository.dart b/lib/core/managers/course_repository.dart index d90e24c68..26ca53ea6 100644 --- a/lib/core/managers/course_repository.dart +++ b/lib/core/managers/course_repository.dart @@ -128,7 +128,7 @@ class CourseRepository { await getSessions(); } - if(_userRepository.monETSUser != null) { + if (_userRepository.monETSUser != null) { final String password = await _userRepository.getPassword(); for (final Session session in activeSessions) { fetchedCoursesActivities.addAll( @@ -159,7 +159,8 @@ class CourseRepository { // Update the list of activities to avoid duplicate activities for (final CourseActivity activity in fetchedCoursesActivities) { - if (_coursesActivities != null && !_coursesActivities!.contains(activity)) { + if (_coursesActivities != null && + !_coursesActivities!.contains(activity)) { _coursesActivities!.add(activity); } } @@ -220,7 +221,7 @@ class CourseRepository { await getSessions(); } - if(_userRepository.monETSUser != null) { + if (_userRepository.monETSUser != null) { final String password = await _userRepository.getPassword(); for (final Session session in activeSessions) { @@ -243,7 +244,8 @@ class CourseRepository { // Update the list of activities to avoid duplicate activities for (final ScheduleActivity activity in fetchedScheduleActivities) { - if (_scheduleActivities != null && !_scheduleActivities!.contains(activity)) { + if (_scheduleActivities != null && + !_scheduleActivities!.contains(activity)) { _scheduleActivities!.add(activity); } } @@ -290,15 +292,16 @@ class CourseRepository { } try { - if(_userRepository.monETSUser != null) { + if (_userRepository.monETSUser != null) { // getPassword will try to authenticate the user if not authenticated. final String password = await _userRepository.getPassword(); - final List fetchedSession = await _signetsApiClient.getSessions( - username: _userRepository.monETSUser!.universalCode, - password: password); - _logger - .d("$tag - getSessions: ${fetchedSession.length} sessions fetched."); + final List fetchedSession = + await _signetsApiClient.getSessions( + username: _userRepository.monETSUser!.universalCode, + password: password); + _logger.d( + "$tag - getSessions: ${fetchedSession.length} sessions fetched."); for (final Session session in fetchedSession) { if (!_sessions!.contains(session)) { _sessions!.add(session); @@ -358,13 +361,14 @@ class CourseRepository { final Map> fetchedCourseReviews = {}; try { - if(_userRepository.monETSUser != null) { + if (_userRepository.monETSUser != null) { final String password = await _userRepository.getPassword(); fetchedCourses.addAll(await _signetsApiClient.getCourses( username: _userRepository.monETSUser!.universalCode, password: password)); - _logger.d("$tag - getCourses: fetched ${fetchedCourses.length} courses."); + _logger + .d("$tag - getCourses: fetched ${fetchedCourses.length} courses."); } } on Exception catch (e, stacktrace) { _analyticsService.logError( @@ -423,14 +427,15 @@ class CourseRepository { } try { - if(_userRepository.monETSUser != null) { + if (_userRepository.monETSUser != null) { final String password = await _userRepository.getPassword(); summary = await _signetsApiClient.getCourseSummary( username: _userRepository.monETSUser!.universalCode, password: password, course: course); - _logger.d("$tag - getCourseSummary: fetched ${course.acronym} summary."); + _logger + .d("$tag - getCourseSummary: fetched ${course.acronym} summary."); } } on Exception catch (e, stacktrace) { if (e is ApiException) { @@ -481,7 +486,7 @@ class CourseRepository { await getSessions(); } - if(_userRepository.monETSUser != null) { + if (_userRepository.monETSUser != null) { for (final Session session in _sessions!) { sessionReviews = await _signetsApiClient.getCourseReviews( username: _userRepository.monETSUser!.universalCode, @@ -506,9 +511,7 @@ class CourseRepository { CourseReview? _getReviewForCourse( Course course, Map> reviews) { final review = reviews[course.session]?.where((element) => - element.acronym == course.acronym && element.group == course.group); - return review?.length == 1 - ? review?.first - : null; + element.acronym == course.acronym && element.group == course.group); + return review?.length == 1 ? review?.first : null; } } diff --git a/lib/core/managers/settings_manager.dart b/lib/core/managers/settings_manager.dart index 035ebd8bb..f414c1d42 100644 --- a/lib/core/managers/settings_manager.dart +++ b/lib/core/managers/settings_manager.dart @@ -151,8 +151,9 @@ class SettingsManager with ChangeNotifier { "${tag}_${EnumToString.convertToString(PreferencesFlag.locale)}", _locale?.languageCode ?? 'Not found'); - if(_locale != null) { - _preferencesService.setString(PreferencesFlag.locale, _locale!.languageCode); + if (_locale != null) { + _preferencesService.setString( + PreferencesFlag.locale, _locale!.languageCode); _locale = Locale(_locale!.languageCode); notifyListeners(); } @@ -166,8 +167,8 @@ class SettingsManager with ChangeNotifier { .getString(PreferencesFlag.scheduleCalendarFormat) .then((value) => value == null ? CalendarFormat.week - : EnumToString.fromString(CalendarFormat.values, value) - ?? CalendarFormat.week); + : EnumToString.fromString(CalendarFormat.values, value) ?? + CalendarFormat.week); settings.putIfAbsent( PreferencesFlag.scheduleCalendarFormat, () => calendarFormat); diff --git a/lib/core/managers/user_repository.dart b/lib/core/managers/user_repository.dart index f0da6fcf8..a4eae1e80 100644 --- a/lib/core/managers/user_repository.dart +++ b/lib/core/managers/user_repository.dart @@ -133,11 +133,10 @@ class UserRepository { final username = await _secureStorage.read(key: usernameSecureKey); if (username != null) { final password = await _secureStorage.read(key: passwordSecureKey); - if(password == null) { + if (password == null) { await _secureStorage.deleteAll(); - _analyticsService.logError( - tag, - "SilentAuthenticate - PlatformException(Handled) - $passwordSecureKey not found"); + _analyticsService.logError(tag, + "SilentAuthenticate - PlatformException(Handled) - $passwordSecureKey not found"); return false; } return await authenticate( @@ -185,7 +184,7 @@ class UserRepository { } try { final password = await _secureStorage.read(key: passwordSecureKey); - if(password == null) { + if (password == null) { throw const ApiException(prefix: tag, message: "Not authenticated"); } return password; @@ -236,10 +235,10 @@ class UserRepository { // getPassword will try to authenticate the user if not authenticated. final String password = await getPassword(); - if(_monETSUser != null) { + if (_monETSUser != null) { _programs = await _signetsApiClient.getPrograms( - username: _monETSUser!.universalCode, password: password); - + username: _monETSUser!.universalCode, password: password); + _logger.d("$tag - getPrograms: ${_programs!.length} programs fetched."); // Update cache @@ -291,7 +290,7 @@ class UserRepository { // getPassword will try to authenticate the user if not authenticated. final String password = await getPassword(); - if(_monETSUser != null) { + if (_monETSUser != null) { final fetchedInfo = await _signetsApiClient.getStudentInfo( username: _monETSUser!.universalCode, password: password); @@ -304,7 +303,6 @@ class UserRepository { _cacheManager.update(infoCacheKey, jsonEncode(_info)); } } - } on CacheException catch (_) { _logger.e( "$tag - getInfo: exception raised while trying to update the cache."); @@ -323,8 +321,7 @@ class UserRepository { try { final username = await _secureStorage.read(key: passwordSecureKey); if (username != null) { - final password = - await _secureStorage.read(key: passwordSecureKey); + final password = await _secureStorage.read(key: passwordSecureKey); return password != null && password.isNotEmpty; } } on PlatformException catch (e, stacktrace) { diff --git a/lib/core/models/feedback_issue.dart b/lib/core/models/feedback_issue.dart index 88d673b85..4ac56dc7f 100644 --- a/lib/core/models/feedback_issue.dart +++ b/lib/core/models/feedback_issue.dart @@ -9,7 +9,7 @@ class FeedbackIssue { late bool isOpen; late int number; late String createdAt; - + // Constructor FeedbackIssue(Issue issue) { id = issue.id; diff --git a/lib/core/services/analytics_service.dart b/lib/core/services/analytics_service.dart index 3ca534b4a..a9adea0bf 100644 --- a/lib/core/services/analytics_service.dart +++ b/lib/core/services/analytics_service.dart @@ -35,7 +35,8 @@ class AnalyticsService { } /// Set user properties to identify the user against firebase app. - Future setUserProperties({required String userId, required String domain}) async { + Future setUserProperties( + {required String userId, required String domain}) async { await _analytics.setUserId(id: userId); await _analytics.setUserProperty( name: _userPropertiesDomainKey, value: domain); diff --git a/lib/core/services/navigation_service.dart b/lib/core/services/navigation_service.dart index 1119fe311..a9e12f7c2 100644 --- a/lib/core/services/navigation_service.dart +++ b/lib/core/services/navigation_service.dart @@ -35,16 +35,15 @@ class NavigationService { Future pushNamed(String routeName, {dynamic arguments}) { final currentState = _navigatorKey.currentState; - if(currentState == null) { + if (currentState == null) { return Future.error("Navigator state is null"); } if (remoteConfigService.outage) { - return currentState - .pushNamedAndRemoveUntil(RouterPaths.serviceOutage, (route) => false); + return currentState.pushNamedAndRemoveUntil( + RouterPaths.serviceOutage, (route) => false); } - return currentState - .pushNamed(routeName, arguments: arguments); + return currentState.pushNamed(routeName, arguments: arguments); } /// Replace the current route of the navigator by pushing the route named @@ -52,15 +51,14 @@ class NavigationService { Future pushNamedAndRemoveUntil(String routeName, [String removeUntilRouteNamed = RouterPaths.dashboard, Object? arguments]) { - final currentState = _navigatorKey.currentState; - if(currentState == null) { + if (currentState == null) { return Future.error("Navigator state is null"); } if (remoteConfigService.outage) { - return currentState - .pushNamedAndRemoveUntil(RouterPaths.serviceOutage, (route) => false); + return currentState.pushNamedAndRemoveUntil( + RouterPaths.serviceOutage, (route) => false); } return currentState.pushNamedAndRemoveUntil( routeName, ModalRoute.withName(removeUntilRouteNamed), diff --git a/lib/core/services/preferences_service.dart b/lib/core/services/preferences_service.dart index 592d2f3fe..6320bfd94 100644 --- a/lib/core/services/preferences_service.dart +++ b/lib/core/services/preferences_service.dart @@ -126,7 +126,7 @@ class PreferencesService { final SharedPreferences prefs = await SharedPreferences.getInstance(); final flagPreference = prefs.getString(flag.toString()); - if(flagPreference != null) { + if (flagPreference != null) { return DateTime.parse(flagPreference); } diff --git a/lib/core/viewmodels/dashboard_viewmodel.dart b/lib/core/viewmodels/dashboard_viewmodel.dart index ec3fa3979..46a6183ae 100644 --- a/lib/core/viewmodels/dashboard_viewmodel.dart +++ b/lib/core/viewmodels/dashboard_viewmodel.dart @@ -254,9 +254,10 @@ class DashboardViewModel extends FutureViewModel> { return course.grade!; } else if (course.summary != null && course.summary!.markOutOf > 0 && - !(course.inReviewPeriod && (course.reviewCompleted != null && !course.reviewCompleted!))) { + !(course.inReviewPeriod && + (course.reviewCompleted != null && !course.reviewCompleted!))) { return _appIntl.grades_grade_in_percentage( - course.summary!.currentMarkInPercent.round()); + course.summary!.currentMarkInPercent.round()); } return _appIntl.grades_not_available; }).toList(); @@ -351,9 +352,7 @@ class DashboardViewModel extends FutureViewModel> { remoteConfigService.dashboardMessageEn); if (_cards != null && _cards![PreferencesFlag.broadcastCard]! < 0) { _cards?.updateAll((key, value) { - return value >= 0 - ? value + 1 - : value; + return value >= 0 ? value + 1 : value; }); _cards![PreferencesFlag.broadcastCard] = 0; } @@ -363,8 +362,8 @@ class DashboardViewModel extends FutureViewModel> { Future> futureToRunSessionProgressBar() async { try { final progressBarText = - await _settingsManager.getString(PreferencesFlag.progressBarText) - ?? ProgressBarText.daysElapsedWithTotalDays.toString(); + await _settingsManager.getString(PreferencesFlag.progressBarText) ?? + ProgressBarText.daysElapsedWithTotalDays.toString(); _currentProgressBarText = ProgressBarText.values .firstWhere((e) => e.toString() == progressBarText); @@ -374,7 +373,7 @@ class DashboardViewModel extends FutureViewModel> { _sessionDays = getSessionDays(); _progress = getSessionProgress(); return sessions; - } catch(error) { + } catch (error) { onError(error); } finally { setBusyForObject(progress, false); @@ -384,7 +383,8 @@ class DashboardViewModel extends FutureViewModel> { Future> futureToRunSchedule() async { try { - var courseActivities = await _courseRepository.getCoursesActivities(fromCacheOnly: true); + var courseActivities = + await _courseRepository.getCoursesActivities(fromCacheOnly: true); setBusyForObject(_todayDateEvents, true); setBusyForObject(_tomorrowDateEvents, true); _todayDateEvents.clear(); @@ -392,10 +392,12 @@ class DashboardViewModel extends FutureViewModel> { final todayDate = _settingsManager.dateTimeNow; courseActivities = await _courseRepository.getCoursesActivities(); - if (_todayDateEvents.isEmpty && _courseRepository.coursesActivities != null) { + if (_todayDateEvents.isEmpty && + _courseRepository.coursesActivities != null) { final DateTime tomorrowDate = todayDate.add(const Duration(days: 1)); // Build the list - for (final CourseActivity course in _courseRepository.coursesActivities!) { + for (final CourseActivity course + in _courseRepository.coursesActivities!) { final DateTime dateOnly = course.startDateTime; if (isSameDay(todayDate, dateOnly) && todayDate.compareTo(course.endDateTime) < 0) { @@ -407,14 +409,14 @@ class DashboardViewModel extends FutureViewModel> { } _todayDateEvents - .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); + .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); _tomorrowDateEvents - .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); + .sort((a, b) => a.startDateTime.compareTo(b.startDateTime)); _todayDateEvents = await removeLaboratoryGroup(_todayDateEvents); _tomorrowDateEvents = await removeLaboratoryGroup(_tomorrowDateEvents); return courseActivities ?? []; - } catch(error) { + } catch (error) { onError(error); } finally { setBusyForObject(_todayDateEvents, false); @@ -449,7 +451,7 @@ class DashboardViewModel extends FutureViewModel> { /// Update cards order and display status in preferences void updatePreferences() { - if(_cards == null || _cardsToDisplay == null) { + if (_cards == null || _cardsToDisplay == null) { return; } for (final MapEntry element in _cards!.entries) { @@ -505,7 +507,8 @@ class DashboardViewModel extends FutureViewModel> { } final currentSession = _courseRepository.activeSessions.first; - final coursesCached = await _courseRepository.getCourses(fromCacheOnly: true); + final coursesCached = + await _courseRepository.getCourses(fromCacheOnly: true); courses.clear(); for (final Course course in coursesCached) { if (course.session == currentSession.shortName) { diff --git a/lib/core/viewmodels/feedback_viewmodel.dart b/lib/core/viewmodels/feedback_viewmodel.dart index 94f16e438..279221e94 100644 --- a/lib/core/viewmodels/feedback_viewmodel.dart +++ b/lib/core/viewmodels/feedback_viewmodel.dart @@ -75,7 +75,8 @@ class FeedbackViewModel extends FutureViewModel { } List encodeScreenshotForGithub(Uint8List screenshot) { - return image.encodePng(image.copyResize(image.decodeImage(screenshot) ?? image.Image(0, 0), + return image.encodePng(image.copyResize( + image.decodeImage(screenshot) ?? image.Image(0, 0), width: _screenshotImageWidth)); } diff --git a/lib/core/viewmodels/grades_details_viewmodel.dart b/lib/core/viewmodels/grades_details_viewmodel.dart index ad17c6b39..89988a992 100644 --- a/lib/core/viewmodels/grades_details_viewmodel.dart +++ b/lib/core/viewmodels/grades_details_viewmodel.dart @@ -36,7 +36,7 @@ class GradesDetailsViewModel extends FutureViewModel { setBusyForObject(course, true); course = await _courseRepository.getCourseSummary(course); notifyListeners(); - } catch(e) { + } catch (e) { onError(e); } finally { setBusyForObject(course, false); diff --git a/lib/core/viewmodels/grades_viewmodel.dart b/lib/core/viewmodels/grades_viewmodel.dart index 3ad1d1255..1ea14e0c6 100644 --- a/lib/core/viewmodels/grades_viewmodel.dart +++ b/lib/core/viewmodels/grades_viewmodel.dart @@ -35,7 +35,8 @@ class GradesViewModel extends FutureViewModel>> { @override Future>> futureToRun() async { try { - final coursesCached = await _courseRepository.getCourses(fromCacheOnly: true); + final coursesCached = + await _courseRepository.getCourses(fromCacheOnly: true); setBusy(true); _buildCoursesBySession(coursesCached); await _courseRepository.getCourses(); @@ -43,14 +44,13 @@ class GradesViewModel extends FutureViewModel>> { // Update the courses list _buildCoursesBySession(_courseRepository.courses!); } - } catch(error) { + } catch (error) { onError(error); } finally { setBusy(false); } return coursesBySession; } - @override // ignore: type_annotate_public_apis @@ -62,7 +62,7 @@ class GradesViewModel extends FutureViewModel>> { Future refresh() async { try { await _courseRepository.getCourses(); - if(_courseRepository.courses != null) { + if (_courseRepository.courses != null) { _buildCoursesBySession(_courseRepository.courses!); } notifyListeners(); diff --git a/lib/core/viewmodels/not_found_viewmodel.dart b/lib/core/viewmodels/not_found_viewmodel.dart index c7068488f..98dc1c958 100644 --- a/lib/core/viewmodels/not_found_viewmodel.dart +++ b/lib/core/viewmodels/not_found_viewmodel.dart @@ -53,7 +53,7 @@ class NotFoundViewModel extends BaseViewModel { void startRiveAnimation() { try { - if(artboard != null) { + if (artboard != null) { _riveAnimationService.addControllerToAnimation(artboard: _artboard!); } } on Exception catch (e, stacktrace) { diff --git a/lib/core/viewmodels/schedule_settings_viewmodel.dart b/lib/core/viewmodels/schedule_settings_viewmodel.dart index 4ed525cfa..d7dac0071 100644 --- a/lib/core/viewmodels/schedule_settings_viewmodel.dart +++ b/lib/core/viewmodels/schedule_settings_viewmodel.dart @@ -148,7 +148,7 @@ class ScheduleSettingsViewModel PreferencesFlag.scheduleLaboratoryGroup, courseAcronym, scheduleActivityToSave.activityCode); - _selectedScheduleActivity[courseAcronym] = scheduleActivityToSave; + _selectedScheduleActivity[courseAcronym] = scheduleActivityToSave; } setBusy(false); } @@ -191,7 +191,8 @@ class ScheduleSettingsViewModel final scheduleActivityCode = await _settingsManager.getDynamicString( PreferencesFlag.scheduleLaboratoryGroup, courseKey); final scheduleActivity = _scheduleActivitiesByCourse[courseKey] - ?.firstWhereOrNull((element) => element.activityCode == scheduleActivityCode); + ?.firstWhereOrNull( + (element) => element.activityCode == scheduleActivityCode); if (scheduleActivity != null) { _selectedScheduleActivity[courseKey] = scheduleActivity; } diff --git a/lib/core/viewmodels/schedule_viewmodel.dart b/lib/core/viewmodels/schedule_viewmodel.dart index bead03abb..e9123526f 100644 --- a/lib/core/viewmodels/schedule_viewmodel.dart +++ b/lib/core/viewmodels/schedule_viewmodel.dart @@ -181,11 +181,13 @@ class ScheduleViewModel extends FutureViewModel> { @override Future> futureToRun() async { loadSettings(); - List? activities = await _courseRepository.getCoursesActivities(fromCacheOnly: true); + List? activities = + await _courseRepository.getCoursesActivities(fromCacheOnly: true); try { setBusyForObject(isLoadingEvents, true); - final fetchedCourseActivities = await _courseRepository.getCoursesActivities(); + final fetchedCourseActivities = + await _courseRepository.getCoursesActivities(); if (fetchedCourseActivities != null) { activities = fetchedCourseActivities; // Reload the list of activities @@ -201,9 +203,10 @@ class ScheduleViewModel extends FutureViewModel> { } } } - final scheduleActivities = await _courseRepository.getScheduleActivities(); + final scheduleActivities = + await _courseRepository.getScheduleActivities(); await assignScheduleActivities(scheduleActivities); - } catch(e) { + } catch (e) { onError(e); } finally { setBusyForObject(isLoadingEvents, false); @@ -211,7 +214,6 @@ class ScheduleViewModel extends FutureViewModel> { return activities ?? []; } - Future assignScheduleActivities( List listOfSchedules) async { if (listOfSchedules.isEmpty || @@ -278,7 +280,8 @@ class ScheduleViewModel extends FutureViewModel> { // Build the map if (_courseRepository.coursesActivities != null) { - for (final CourseActivity course in _courseRepository.coursesActivities!) { + for (final CourseActivity course + in _courseRepository.coursesActivities!) { final DateTime dateOnly = course.startDateTime.subtract(Duration( hours: course.startDateTime.hour, minutes: course.startDateTime.minute)); @@ -338,7 +341,7 @@ class ScheduleViewModel extends FutureViewModel> { dateInArray = element; return isSameDay(element, date); }); - if(courseActivitiesContains) { + if (courseActivitiesContains) { return _coursesActivities[dateInArray] ?? []; } return []; diff --git a/lib/core/viewmodels/settings_viewmodel.dart b/lib/core/viewmodels/settings_viewmodel.dart index 94e5fb740..6d01fbff1 100644 --- a/lib/core/viewmodels/settings_viewmodel.dart +++ b/lib/core/viewmodels/settings_viewmodel.dart @@ -26,7 +26,7 @@ class SettingsViewModel extends FutureViewModel { /// Set theme set selectedTheme(ThemeMode? value) { - if(value != null) { + if (value != null) { _settingsManager.setThemeMode(value); _selectedTheme = value; } diff --git a/lib/ui/utils/discovery_components.dart b/lib/ui/utils/discovery_components.dart index 5da5ecbbe..68a99f37e 100644 --- a/lib/ui/utils/discovery_components.dart +++ b/lib/ui/utils/discovery_components.dart @@ -27,14 +27,15 @@ List discoveryComponents(BuildContext context) { maxHeight: MediaQuery.of(context).size.height * 0.6), child: Column( children: [ - _buildHeader(AppIntl.of(context)!.discovery_navbar_dashboard_title, + _buildHeader( + AppIntl.of(context)!.discovery_navbar_dashboard_title, context), Expanded( child: ListView( padding: EdgeInsets.zero, children: [ - Text( - AppIntl.of(context)!.discovery_navbar_dashboard_details), + Text(AppIntl.of(context)! + .discovery_navbar_dashboard_details), const Text('\n'), if (AppIntl.of(context)!.localeName == "fr") Image.asset( @@ -89,8 +90,8 @@ List discoveryComponents(BuildContext context) { maxHeight: MediaQuery.of(context).size.height * 0.6), child: Column( children: [ - _buildHeader( - AppIntl.of(context)!.discovery_navbar_schedule_title, context), + _buildHeader(AppIntl.of(context)!.discovery_navbar_schedule_title, + context), Expanded( child: ListView( padding: EdgeInsets.zero, @@ -250,13 +251,13 @@ List discoveryComponents(BuildContext context) { children: [ _buildSkipDiscoveryButton(context), Text( - AppIntl.of(context) - !.discovery_page_student_grades_session, + AppIntl.of(context)! + .discovery_page_student_grades_session, textAlign: TextAlign.justify), const Text('\n'), Text( - AppIntl.of(context) - !.discovery_page_student_grades_grade_button, + AppIntl.of(context)! + .discovery_page_student_grades_grade_button, textAlign: TextAlign.justify), ], ), @@ -443,8 +444,8 @@ Padding _buildHeader(String title, BuildContext context) { Text(title, style: Theme.of(context) .textTheme - .headline6 - !.copyWith(color: Colors.white)), + .headline6! + .copyWith(color: Colors.white)), _buildSkipDiscoveryButton(context) ], ), diff --git a/lib/ui/views/contributors_view.dart b/lib/ui/views/contributors_view.dart index e93d26d38..1fcca95d5 100644 --- a/lib/ui/views/contributors_view.dart +++ b/lib/ui/views/contributors_view.dart @@ -34,10 +34,11 @@ class ContributorsView extends StatelessWidget { itemBuilder: (context, index) => ListTile( title: Text(snapshot.data![index].login ?? ''), leading: CircleAvatar( - backgroundImage: - NetworkImage(snapshot.data![index].avatarUrl ?? '')), + backgroundImage: NetworkImage( + snapshot.data![index].avatarUrl ?? '')), onTap: () => Utils.launchURL( - snapshot.data![index].htmlUrl ?? '', AppIntl.of(context)!), + snapshot.data![index].htmlUrl ?? '', + AppIntl.of(context)!), ), ); }, diff --git a/lib/ui/views/dashboard_view.dart b/lib/ui/views/dashboard_view.dart index 6ff34fbc7..77b66873e 100644 --- a/lib/ui/views/dashboard_view.dart +++ b/lib/ui/views/dashboard_view.dart @@ -158,7 +158,8 @@ class _DashboardViewState extends State IconButton( onPressed: () { _analyticsService.logEvent(tag, "Facebook clicked"); - Utils.launchURL(Urls.clubFacebook, AppIntl.of(context)!); + Utils.launchURL( + Urls.clubFacebook, AppIntl.of(context)!); }, icon: const FaIcon( FontAwesomeIcons.facebook, @@ -289,8 +290,8 @@ class _DashboardViewState extends State if (model.currentProgressBarText == ProgressBarText.daysElapsedWithTotalDays) { progressBarText = Text( - AppIntl.of(context) - !.progress_bar_message(model.sessionDays[0], model.sessionDays[1]), + AppIntl.of(context)! + .progress_bar_message(model.sessionDays[0], model.sessionDays[1]), style: const TextStyle(color: Colors.white), ); } else if (model.currentProgressBarText == ProgressBarText.percentage) { @@ -390,8 +391,8 @@ class _DashboardViewState extends State SizedBox( height: 100, child: Center( - child: Text(AppIntl.of(context) - !.grades_msg_no_grades + child: Text(AppIntl.of(context)! + .grades_msg_no_grades .split("\n") .first)), ) @@ -400,8 +401,7 @@ class _DashboardViewState extends State padding: const EdgeInsets.fromLTRB(17, 10, 15, 10), child: Wrap( children: model.courses - .map((course) => - GradeButton(course)) + .map((course) => GradeButton(course)) .toList(), ), ) @@ -492,7 +492,7 @@ class _DashboardViewState extends State } // Should not happen becase dismiss card will not be called if the card is null. - if(model.cards == null) { + if (model.cards == null) { throw Exception("Cards is null"); } diff --git a/lib/ui/views/emergency_view.dart b/lib/ui/views/emergency_view.dart index 005840382..da51d372c 100644 --- a/lib/ui/views/emergency_view.dart +++ b/lib/ui/views/emergency_view.dart @@ -49,8 +49,8 @@ class _EmergencyViewState extends State { ), body: WebView( onWebViewCreated: (WebViewController webViewController) async { - await model.loadHtmlFromAssets( - widget.description, Theme.of(context).brightness, webViewController); + await model.loadHtmlFromAssets(widget.description, + Theme.of(context).brightness, webViewController); }, ), ), diff --git a/lib/ui/views/faq_view.dart b/lib/ui/views/faq_view.dart index 56261591d..f6e377037 100644 --- a/lib/ui/views/faq_view.dart +++ b/lib/ui/views/faq_view.dart @@ -59,7 +59,9 @@ class _FaqViewState extends State { ), child: getQuestionCard( question.title[model.locale?.languageCode] ?? '', - question.description[model.locale?.languageCode] ?? '', + question.description[ + model.locale?.languageCode] ?? + '', ), ); }, diff --git a/lib/ui/views/feedback_view.dart b/lib/ui/views/feedback_view.dart index a52ab9e16..470b1e170 100644 --- a/lib/ui/views/feedback_view.dart +++ b/lib/ui/views/feedback_view.dart @@ -155,10 +155,10 @@ class _FeedbackViewState extends State { const SizedBox(width: 4), createListTag( model.myIssues[index].isOpen - ? AppIntl.of(context) - !.ticket_status_open - : AppIntl.of(context) - !.ticket_status_closed, + ? AppIntl.of(context)! + .ticket_status_open + : AppIntl.of(context)! + .ticket_status_closed, color: model.myIssues[index].state == 'open' ? Colors.green @@ -190,8 +190,8 @@ class _FeedbackViewState extends State { overflow: TextOverflow.ellipsis, style: Theme.of(context) .textTheme - .headline6 - !.copyWith( + .headline6! + .copyWith( color: isLightMode ? const Color.fromARGB( 168, 0, 0, 0) @@ -224,14 +224,14 @@ class _FeedbackViewState extends State { text: AppIntl.of(context)!.more_report_bug_step1, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith(fontSize: 18)), + .bodyText2! + .copyWith(fontSize: 18)), TextSpan( text: AppIntl.of(context)!.more_report_bug_step2, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith( + .bodyText2! + .copyWith( fontSize: 18, color: Theme.of(context).brightness == Brightness.light @@ -242,14 +242,14 @@ class _FeedbackViewState extends State { text: AppIntl.of(context)!.more_report_bug_step3, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith(fontSize: 18)), + .bodyText2! + .copyWith(fontSize: 18)), TextSpan( text: AppIntl.of(context)!.more_report_bug_step4, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith( + .bodyText2! + .copyWith( fontSize: 18, color: Theme.of(context).brightness == Brightness.light @@ -260,8 +260,8 @@ class _FeedbackViewState extends State { text: AppIntl.of(context)!.more_report_bug_step5, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith(fontSize: 18)), + .bodyText2! + .copyWith(fontSize: 18)), ], ), ), @@ -302,16 +302,16 @@ class _FeedbackViewState extends State { title, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith(fontSize: 19), + .bodyText2! + .copyWith(fontSize: 19), textAlign: TextAlign.left, ), Text( subtitle, style: Theme.of(context) .textTheme - .bodyText2 - !.copyWith(fontSize: 16), + .bodyText2! + .copyWith(fontSize: 16), textAlign: TextAlign.left, ) ], diff --git a/lib/ui/views/grade_details_view.dart b/lib/ui/views/grade_details_view.dart index bf0fad427..bf642dfb4 100644 --- a/lib/ui/views/grade_details_view.dart +++ b/lib/ui/views/grade_details_view.dart @@ -105,12 +105,12 @@ class _GradesDetailsViewState extends State children: [ _buildClassInfo(model.course.title), if (model.course.teacherName != null) - _buildClassInfo(AppIntl.of(context) - !.grades_teacher(model.course.teacherName!)), - _buildClassInfo(AppIntl.of(context) - !.grades_group_number(model.course.group)), - _buildClassInfo(AppIntl.of(context)!.credits_number( - model.course.numberOfCredits)), + _buildClassInfo(AppIntl.of(context)! + .grades_teacher(model.course.teacherName!)), + _buildClassInfo(AppIntl.of(context)! + .grades_group_number(model.course.group)), + _buildClassInfo(AppIntl.of(context)! + .credits_number(model.course.numberOfCredits)), ], ), ), @@ -129,7 +129,8 @@ class _GradesDetailsViewState extends State Widget _buildGradeEvaluations(GradesDetailsViewModel model) { if (model.isBusy) { return const Center(child: CircularProgressIndicator()); - } else if (model.course.inReviewPeriod && !(model.course.reviewCompleted ?? false)) { + } else if (model.course.inReviewPeriod && + !(model.course.reviewCompleted ?? false)) { return Center( child: GradeNotAvailable( key: const Key("EvaluationNotCompleted"), @@ -237,7 +238,8 @@ class _GradesDetailsViewState extends State ), ]), Column(children: [ - for (CourseEvaluation evaluation in model.course.summary?.evaluations ?? []) + for (CourseEvaluation evaluation + in model.course.summary?.evaluations ?? []) GradeEvaluationTile( evaluation, completed: _completed, @@ -267,8 +269,8 @@ class _GradesDetailsViewState extends State info, style: Theme.of(context) .textTheme - .bodyText1 - !.copyWith(color: Colors.white, fontSize: 16), + .bodyText1! + .copyWith(color: Colors.white, fontSize: 16), overflow: TextOverflow.ellipsis, ), ), @@ -291,8 +293,10 @@ class _GradesDetailsViewState extends State maxGrade, ), ), - style: - Theme.of(context).textTheme.headline6!.copyWith(color: color)), + style: Theme.of(context) + .textTheme + .headline6! + .copyWith(color: color)), ), Text(recipient, style: diff --git a/lib/ui/views/grades_view.dart b/lib/ui/views/grades_view.dart index d362f9eeb..a0e187b18 100644 --- a/lib/ui/views/grades_view.dart +++ b/lib/ui/views/grades_view.dart @@ -105,7 +105,8 @@ class _GradesViewState extends State { const SizedBox(height: 16.0), Wrap( children: courses - .map((course) => GradeButton(course, showDiscovery: index == 0)) + .map((course) => + GradeButton(course, showDiscovery: index == 0)) .toList(), ), ], diff --git a/lib/ui/views/login_view.dart b/lib/ui/views/login_view.dart index 9bf6c5075..3c1bd9ce0 100644 --- a/lib/ui/views/login_view.dart +++ b/lib/ui/views/login_view.dart @@ -103,16 +103,16 @@ class _LoginViewState extends State { borderSide: BorderSide( color: errorTextColor, width: borderRadiusOnFocus)), - labelText: AppIntl.of(context) - !.login_prompt_universal_code, + labelText: AppIntl.of(context)! + .login_prompt_universal_code, labelStyle: const TextStyle(color: Colors.white54), errorStyle: TextStyle(color: errorTextColor), suffixIcon: Tooltip( key: tooltipkey, triggerMode: TooltipTriggerMode.manual, - message: AppIntl.of(context) - !.universal_code_example, + message: AppIntl.of(context)! + .universal_code_example, preferBelow: true, child: IconButton( icon: const Icon(Icons.help, diff --git a/lib/ui/views/more_view.dart b/lib/ui/views/more_view.dart index 6fea01ad1..aa8002300 100644 --- a/lib/ui/views/more_view.dart +++ b/lib/ui/views/more_view.dart @@ -197,8 +197,8 @@ class _MoreViewState extends State { AppIntl.of(context)!.more_log_out, style: const TextStyle(color: Colors.red), ), - content: Text(AppIntl.of(context) - !.more_prompt_log_out_confirmation), + content: Text(AppIntl.of(context)! + .more_prompt_log_out_confirmation), actions: [ TextButton( onPressed: () async { diff --git a/lib/ui/views/not_found_view.dart b/lib/ui/views/not_found_view.dart index 85230cf5e..7027cc1f7 100644 --- a/lib/ui/views/not_found_view.dart +++ b/lib/ui/views/not_found_view.dart @@ -78,8 +78,8 @@ class _NotFoundState extends State { bottom: 70, ), child: Text( - AppIntl.of(context) - !.not_found_message(model.notFoundPageName), + AppIntl.of(context)! + .not_found_message(model.notFoundPageName), textAlign: TextAlign.center, style: const TextStyle( fontSize: 15, diff --git a/lib/ui/views/outage_view.dart b/lib/ui/views/outage_view.dart index 3e74df47b..3fb55e825 100644 --- a/lib/ui/views/outage_view.dart +++ b/lib/ui/views/outage_view.dart @@ -83,7 +83,8 @@ class OutageView extends StatelessWidget { color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubWebsite, AppIntl.of(context)!)), + Urls.clubWebsite, + AppIntl.of(context)!)), IconButton( icon: const FaIcon( FontAwesomeIcons.github, @@ -104,7 +105,8 @@ class OutageView extends StatelessWidget { color: Colors.white, ), onPressed: () => Utils.launchURL( - Urls.clubDiscord, AppIntl.of(context)!)), + Urls.clubDiscord, + AppIntl.of(context)!)), ], ), ], diff --git a/lib/ui/views/profile_view.dart b/lib/ui/views/profile_view.dart index b58ce7c00..45729deef 100644 --- a/lib/ui/views/profile_view.dart +++ b/lib/ui/views/profile_view.dart @@ -179,8 +179,8 @@ Card getMyInfosCard(ProfileViewModel model, BuildContext context) { Clipboard.setData( ClipboardData(text: model.profileStudent.permanentCode)); ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(AppIntl.of(context) - !.profile_permanent_code_copied_to_clipboard), + content: Text(AppIntl.of(context)! + .profile_permanent_code_copied_to_clipboard), )); }, child: Column( @@ -208,8 +208,8 @@ Card getMyInfosCard(ProfileViewModel model, BuildContext context) { onTap: () { Clipboard.setData(ClipboardData(text: model.universalAccessCode)); ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(AppIntl.of(context) - !.profile_universal_code_copied_to_clipboard), + content: Text(AppIntl.of(context)! + .profile_universal_code_copied_to_clipboard), )); }, child: Column( diff --git a/lib/ui/widgets/grade_button.dart b/lib/ui/widgets/grade_button.dart index 5dcdcaf57..e8b963d7b 100644 --- a/lib/ui/widgets/grade_button.dart +++ b/lib/ui/widgets/grade_button.dart @@ -32,7 +32,8 @@ class GradeButton extends StatelessWidget { Widget build(BuildContext context) => Card( child: InkWell( onTap: () async { - if (ModalRoute.of(context)!.settings.name == RouterPaths.dashboard || + if (ModalRoute.of(context)!.settings.name == + RouterPaths.dashboard || await _settingsManager .getBool(PreferencesFlag.discoveryStudentGrade) == true) { @@ -89,8 +90,8 @@ class GradeButton extends StatelessWidget { course.acronym, style: Theme.of(context) .textTheme - .bodyText1 - !.copyWith(color: Colors.white), + .bodyText1! + .copyWith(color: Colors.white), ), ), ), diff --git a/lib/ui/widgets/grade_circular_progress.dart b/lib/ui/widgets/grade_circular_progress.dart index 431045c94..3b8064617 100644 --- a/lib/ui/widgets/grade_circular_progress.dart +++ b/lib/ui/widgets/grade_circular_progress.dart @@ -96,8 +96,8 @@ class _GradeCircularProgressState extends State } if (widget.studentGrade != null) { - return AppIntl.of(context) - !.grades_grade_in_percentage(widget.studentGrade!.round()); + return AppIntl.of(context)! + .grades_grade_in_percentage(widget.studentGrade!.round()); } return AppIntl.of(context)!.grades_not_available; diff --git a/lib/ui/widgets/grade_evaluation_tile.dart b/lib/ui/widgets/grade_evaluation_tile.dart index 8b05bf832..f559ca71b 100644 --- a/lib/ui/widgets/grade_evaluation_tile.dart +++ b/lib/ui/widgets/grade_evaluation_tile.dart @@ -159,8 +159,8 @@ class _GradeEvaluationTileState extends State Padding( padding: const EdgeInsets.only(top: 10.0, bottom: 20.0), child: Text( - AppIntl.of(context) - !.grades_weight(widget.evaluation.weight), + AppIntl.of(context)! + .grades_weight(widget.evaluation.weight), style: TextStyle( fontSize: 14, color: Utils.getColorByBrightness( diff --git a/lib/ui/widgets/grade_not_available.dart b/lib/ui/widgets/grade_not_available.dart index 7b030fc99..a85f68759 100644 --- a/lib/ui/widgets/grade_not_available.dart +++ b/lib/ui/widgets/grade_not_available.dart @@ -30,8 +30,8 @@ class GradeNotAvailable extends StatelessWidget { const SizedBox(height: 25), Text( isEvaluationPeriod - ? AppIntl.of(context) - !.grades_error_course_evaluations_not_completed + ? AppIntl.of(context)! + .grades_error_course_evaluations_not_completed : AppIntl.of(context)!.grades_msg_no_grade, textAlign: TextAlign.center, softWrap: true, diff --git a/lib/ui/widgets/password_text_field.dart b/lib/ui/widgets/password_text_field.dart index b8b2be6e9..70e472dbd 100644 --- a/lib/ui/widgets/password_text_field.dart +++ b/lib/ui/widgets/password_text_field.dart @@ -8,7 +8,8 @@ class PasswordFormField extends StatefulWidget { final FormFieldValidator validator; final VoidCallback onEditionComplete; - const PasswordFormField({Key? key, required this.validator, required this.onEditionComplete}) + const PasswordFormField( + {Key? key, required this.validator, required this.onEditionComplete}) : super(key: key); @override diff --git a/lib/ui/widgets/schedule_settings.dart b/lib/ui/widgets/schedule_settings.dart index c3c57a0ea..5d14c457b 100644 --- a/lib/ui/widgets/schedule_settings.dart +++ b/lib/ui/widgets/schedule_settings.dart @@ -149,7 +149,7 @@ class _ScheduleSettingsState extends State { title: Text(AppIntl.of(context)!.course_activity_group_both), )); - if(model.scheduleActivitiesByCourse[courseActivitiesAcronym] != null) { + if (model.scheduleActivitiesByCourse[courseActivitiesAcronym] != null) { for (final course in model.scheduleActivitiesByCourse[courseActivitiesAcronym]!) { tiles.add(ListTile( @@ -162,7 +162,6 @@ class _ScheduleSettingsState extends State { )); } } - if (model.scheduleActivitiesByCourse.values.length > 1) { tiles.add(const Divider(endIndent: 50, thickness: 1.5)); diff --git a/test/managers/course_repository_test.dart b/test/managers/course_repository_test.dart index c712ce95c..b7cebb9e7 100644 --- a/test/managers/course_repository_test.dart +++ b/test/managers/course_repository_test.dart @@ -89,8 +89,7 @@ void main() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, "password"); + UserRepositoryMock.stubGetPassword(userRepositoryMock, "password"); // Stub some sessions CacheManagerMock.stubGet(cacheManagerMock, @@ -150,8 +149,8 @@ void main() { "Trying to recover activities from cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubGetException(cacheManagerMock, - CourseRepository.coursesActivitiesCacheKey); + CacheManagerMock.stubGetException( + cacheManagerMock, CourseRepository.coursesActivitiesCacheKey); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetCoursesActivities( @@ -174,7 +173,8 @@ void main() { username: username, password: anyNamed("password"), session: session.shortName), - cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, any) + cacheManagerMock.update( + CourseRepository.coursesActivitiesCacheKey, any) ]); verify(signetsApiMock.getSessions( @@ -215,7 +215,8 @@ void main() { username: username, password: anyNamed("password"), session: session.shortName), - cacheManagerMock.update(CourseRepository.coursesActivitiesCacheKey, any) + cacheManagerMock.update( + CourseRepository.coursesActivitiesCacheKey, any) ]); verifyNoMoreInteractions(signetsApiMock); @@ -224,8 +225,7 @@ void main() { test("getSessions fails", () async { // Stub SignetsApi to throw an exception reset(signetsApiMock); - SignetsAPIClientMock.stubGetSessionsException( - signetsApiMock, username); + SignetsAPIClientMock.stubGetSessionsException(signetsApiMock, username); // Stub the cache to return 1 activity CacheManagerMock.stubGet(cacheManagerMock, @@ -266,10 +266,9 @@ void main() { // Stub an authentication error reset(userRepositoryMock); - UserRepositoryMock.stubGetPasswordException( - userRepositoryMock); - UserRepositoryMock.stubMonETSUser( - userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); + UserRepositoryMock.stubGetPasswordException(userRepositoryMock); + UserRepositoryMock.stubMonETSUser(userRepositoryMock, + MonETSUser(domain: '', typeUsagerId: 0, username: username)); expect(manager.getCoursesActivities(), throwsA(isInstanceOf())); @@ -311,9 +310,7 @@ void main() { // Stub the SignetsAPI to return 2 activities SignetsAPIClientMock.stubGetCoursesActivities( - signetsApiMock, - session.shortName, - [activity, courseActivity]); + signetsApiMock, session.shortName, [activity, courseActivity]); expect(manager.coursesActivities, isNull); final List? results = @@ -395,9 +392,7 @@ void main() { // Stub the SignetsAPI to return the same activity as the cache SignetsAPIClientMock.stubGetCoursesActivities( - signetsApiMock, - session.shortName, - [changedActivity]); + signetsApiMock, session.shortName, [changedActivity]); expect(manager.coursesActivities, isNull); final List? results = @@ -465,8 +460,8 @@ void main() { SignetsAPIClientMock.stubGetCoursesActivities( signetsApiMock, session.shortName, activities); - CacheManagerMock.stubUpdateException(cacheManagerMock, - CourseRepository.coursesActivitiesCacheKey); + CacheManagerMock.stubUpdateException( + cacheManagerMock, CourseRepository.coursesActivitiesCacheKey); expect(manager.coursesActivities, isNull); final List? results = @@ -541,8 +536,7 @@ void main() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, "password"); + UserRepositoryMock.stubGetPassword(userRepositoryMock, "password"); // Stub some sessions CacheManagerMock.stubGet(cacheManagerMock, @@ -582,7 +576,8 @@ void main() { username: username, password: anyNamed("password"), session: session.shortName), - cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, any) + cacheManagerMock.update( + CourseRepository.scheduleActivitiesCacheKey, any) ]); }); @@ -614,8 +609,8 @@ void main() { "Trying to recover activities from cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubGetException(cacheManagerMock, - CourseRepository.scheduleActivitiesCacheKey); + CacheManagerMock.stubGetException( + cacheManagerMock, CourseRepository.scheduleActivitiesCacheKey); // Stub the SignetsAPI to return 0 activities SignetsAPIClientMock.stubGetScheduleActivities( @@ -638,7 +633,8 @@ void main() { username: username, password: anyNamed("password"), session: session.shortName), - cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, any) + cacheManagerMock.update( + CourseRepository.scheduleActivitiesCacheKey, any) ]); verify(signetsApiMock.getSessions( @@ -681,7 +677,8 @@ void main() { username: username, password: anyNamed("password"), session: session.shortName), - cacheManagerMock.update(CourseRepository.scheduleActivitiesCacheKey, any) + cacheManagerMock.update( + CourseRepository.scheduleActivitiesCacheKey, any) ]); verifyNoMoreInteractions(signetsApiMock); @@ -690,8 +687,7 @@ void main() { test("getSessions fails", () async { // Stub SignetsApi to throw an exception reset(signetsApiMock); - SignetsAPIClientMock.stubGetSessionsException( - signetsApiMock, username); + SignetsAPIClientMock.stubGetSessionsException(signetsApiMock, username); // Stub the cache to return 1 activity CacheManagerMock.stubGet( @@ -734,10 +730,9 @@ void main() { // Stub an authentication error reset(userRepositoryMock); - UserRepositoryMock.stubGetPasswordException( - userRepositoryMock); - UserRepositoryMock.stubMonETSUser( - userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); + UserRepositoryMock.stubGetPasswordException(userRepositoryMock); + UserRepositoryMock.stubMonETSUser(userRepositoryMock, + MonETSUser(domain: '', typeUsagerId: 0, username: username)); expect(manager.getScheduleActivities(), throwsA(isInstanceOf())); @@ -772,9 +767,7 @@ void main() { // Stub the SignetsAPI to return the same activity as the cache SignetsAPIClientMock.stubGetScheduleActivities( - signetsApiMock, - session.shortName, - scheduleActivities); + signetsApiMock, session.shortName, scheduleActivities); expect(manager.scheduleActivities, isNull); final List results = @@ -861,12 +854,9 @@ void main() { CourseRepository.sessionsCacheKey, jsonEncode(sessions)); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetSessions( - signetsApiMock, username, []); - UserRepositoryMock.stubMonETSUser( - userRepositoryMock, user); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, password); + SignetsAPIClientMock.stubGetSessions(signetsApiMock, username, []); + UserRepositoryMock.stubMonETSUser(userRepositoryMock, user); + UserRepositoryMock.stubGetPassword(userRepositoryMock, password); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -895,8 +885,8 @@ void main() { () async { // Stub to simulate an exception when trying to get the sessions from the cache reset(cacheManagerMock); - CacheManagerMock.stubGetException(cacheManagerMock, - CourseRepository.sessionsCacheKey); + CacheManagerMock.stubGetException( + cacheManagerMock, CourseRepository.sessionsCacheKey); expect(manager.sessions, isNull); final results = await manager.getSessions(); @@ -910,7 +900,8 @@ void main() { userRepositoryMock.getPassword(), userRepositoryMock.monETSUser, signetsApiMock.getSessions(username: username, password: password), - cacheManagerMock.update(CourseRepository.sessionsCacheKey, jsonEncode([])) + cacheManagerMock.update( + CourseRepository.sessionsCacheKey, jsonEncode([])) ]); }); @@ -974,8 +965,7 @@ void main() { CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetSessionsException( - signetsApiMock, username); + SignetsAPIClientMock.stubGetSessionsException(signetsApiMock, username); expect(manager.sessions, isNull); expect(manager.getSessions(), throwsA(isInstanceOf())); @@ -1004,8 +994,8 @@ void main() { CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub to simulate exception when updating cache - CacheManagerMock.stubUpdateException(cacheManagerMock, - CourseRepository.sessionsCacheKey); + CacheManagerMock.stubUpdateException( + cacheManagerMock, CourseRepository.sessionsCacheKey); // Stub SignetsApi answer to test only the cache retrieving SignetsAPIClientMock.stubGetSessions( @@ -1035,8 +1025,7 @@ void main() { CourseRepository.sessionsCacheKey, jsonEncode([])); // Stub UserRepository to throw a exception - UserRepositoryMock.stubGetPasswordException( - userRepositoryMock); + UserRepositoryMock.stubGetPasswordException(userRepositoryMock); expect(manager.sessions, isNull); expect(manager.getSessions(), throwsA(isInstanceOf())); @@ -1117,8 +1106,7 @@ void main() { signetsApiMock, username, sessions); UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, password); + UserRepositoryMock.stubGetPassword(userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1151,8 +1139,7 @@ void main() { signetsApiMock, username, sessions); UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, password); + UserRepositoryMock.stubGetPassword(userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1185,8 +1172,7 @@ void main() { signetsApiMock, username, sessions); UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, password); + UserRepositoryMock.stubGetPassword(userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode(sessions)); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1197,12 +1183,10 @@ void main() { }); test("there is no session", () async { - SignetsAPIClientMock.stubGetSessions( - signetsApiMock, username, []); + SignetsAPIClientMock.stubGetSessions(signetsApiMock, username, []); UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, password); + UserRepositoryMock.stubGetPassword(userRepositoryMock, password); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.sessionsCacheKey, jsonEncode([])); NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -1283,8 +1267,7 @@ void main() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, "password"); + UserRepositoryMock.stubGetPassword(userRepositoryMock, "password"); // Stub some sessions SignetsAPIClientMock.stubGetSessions( @@ -1297,11 +1280,9 @@ void main() { }); test("Courses are loaded from cache and cache is updated", () async { - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseWithGrade]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])); @@ -1371,11 +1352,9 @@ void main() { cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade, courseWithGradeDuplicate])); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseFetched, courseWithGradeDuplicate]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1398,8 +1377,7 @@ void main() { test("Trying to recover courses from cache failed (exception raised)", () async { expect(manager.courses, isNull); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username); CacheManagerMock.stubGetException( cacheManagerMock, CourseRepository.coursesCacheKey); @@ -1420,10 +1398,9 @@ void main() { test("Signets raised an exception while trying to recover courses", () async { - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); - SignetsAPIClientMock.stubGetCoursesException( - signetsApiMock, username); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); + SignetsAPIClientMock.stubGetCoursesException(signetsApiMock, username); expect(manager.courses, isNull); @@ -1453,8 +1430,7 @@ void main() { () async { CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithoutGrade])); - SignetsAPIClientMock.stubGetCoursesException( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCoursesException(signetsApiMock, username); expect(manager.courses, isNull); @@ -1506,16 +1482,14 @@ void main() { title: 'Cours générique', summary: summary); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseFetched]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username); SignetsAPIClientMock.stubGetCourseSummary( signetsApiMock, username, courseFetched, summaryToReturn: summary); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1546,15 +1520,13 @@ void main() { numberOfCredits: 3, title: 'Cours générique'); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseFetched]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username); SignetsAPIClientMock.stubGetCourseSummaryException( signetsApiMock, username, courseFetched); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1578,11 +1550,9 @@ void main() { test("Cache update fails, should still return the list of courses", () async { - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseWithGrade]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username); + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username); CacheManagerMock.stubGet(cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([courseWithGrade])); CacheManagerMock.stubUpdateException( @@ -1610,12 +1580,11 @@ void main() { test("UserRepository return an exception", () async { // Stub to simulate presence of session cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); // Stub UserRepository to throw a exception - UserRepositoryMock.stubGetPasswordException( - userRepositoryMock); + UserRepositoryMock.stubGetPasswordException(userRepositoryMock); expect(manager.sessions, isNull); expect(manager.getCourses(), throwsA(isInstanceOf())); @@ -1634,7 +1603,8 @@ void main() { verifyNever(signetsApiMock.getCourses( username: anyNamed("username"), password: anyNamed("password"))); - verifyNever(cacheManagerMock.update(CourseRepository.coursesCacheKey, any)); + verifyNever( + cacheManagerMock.update(CourseRepository.coursesCacheKey, any)); }); test("Should force fromCacheOnly mode when user has no connectivity", @@ -1662,14 +1632,12 @@ void main() { numberOfCredits: 3, title: 'Cours générique'); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseFetched]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username, session: session); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1721,14 +1689,12 @@ void main() { title: 'Cours générique', review: review); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseFetched]); - SignetsAPIClientMock.stubGetCourseReviews( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourseReviews(signetsApiMock, username, session: session, reviewsToReturn: [review]); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1760,14 +1726,13 @@ void main() { numberOfCredits: 3, title: 'Cours générique'); - SignetsAPIClientMock.stubGetCourses( - signetsApiMock, username, + SignetsAPIClientMock.stubGetCourses(signetsApiMock, username, coursesToReturn: [courseFetched]); SignetsAPIClientMock.stubGetCourseReviewsException( signetsApiMock, username, session: session); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); expect(manager.courses, isNull); final results = await manager.getCourses(); @@ -1802,8 +1767,7 @@ void main() { // Stub a user UserRepositoryMock.stubMonETSUser(userRepositoryMock, MonETSUser(domain: '', typeUsagerId: 0, username: username)); - UserRepositoryMock.stubGetPassword( - userRepositoryMock, "password"); + UserRepositoryMock.stubGetPassword(userRepositoryMock, "password"); // Reset models course = Course( @@ -1958,12 +1922,11 @@ void main() { test("UserRepository return an exception", () async { // Stub to simulate presence of session cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - CourseRepository.coursesCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, CourseRepository.coursesCacheKey, jsonEncode([])); // Stub UserRepository to throw a exception - UserRepositoryMock.stubGetPasswordException( - userRepositoryMock); + UserRepositoryMock.stubGetPasswordException(userRepositoryMock); expect(manager.sessions, isNull); expect(manager.getCourseSummary(course), diff --git a/test/managers/quick_link_repository_test.dart b/test/managers/quick_link_repository_test.dart index 47f728d6b..b1bc3acdf 100644 --- a/test/managers/quick_link_repository_test.dart +++ b/test/managers/quick_link_repository_test.dart @@ -58,8 +58,8 @@ void main() { "Trying to recover QuickLinkData from cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubGetException(cacheManagerMock, - QuickLinkRepository.quickLinksCacheKey); + CacheManagerMock.stubGetException( + cacheManagerMock, QuickLinkRepository.quickLinksCacheKey); expect(quickLinkRepository.getQuickLinkDataFromCache(), throwsA(isInstanceOf())); @@ -83,8 +83,8 @@ void main() { "Trying to update QuickLinkData to cache but an exception is raised.", () async { // Stub the cache to throw an exception - CacheManagerMock.stubUpdateException(cacheManagerMock, - QuickLinkRepository.quickLinksCacheKey); + CacheManagerMock.stubUpdateException( + cacheManagerMock, QuickLinkRepository.quickLinksCacheKey); final quickLink = QuickLink(id: 1, image: const Text(""), name: 'name', link: 'url'); diff --git a/test/managers/settings_manager_test.dart b/test/managers/settings_manager_test.dart index 4a4b136d2..f0a806108 100644 --- a/test/managers/settings_manager_test.dart +++ b/test/managers/settings_manager_test.dart @@ -46,28 +46,22 @@ void main() { test("validate default behaviour", () async { // Stubs the answer of the preferences services PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.scheduleStartWeekday, + preferencesServiceMock, PreferencesFlag.scheduleStartWeekday, toReturn: null); PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.scheduleOtherWeekday, + preferencesServiceMock, PreferencesFlag.scheduleOtherWeekday, toReturn: null); PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.scheduleCalendarFormat, + preferencesServiceMock, PreferencesFlag.scheduleCalendarFormat, toReturn: null); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, - PreferencesFlag.scheduleShowTodayBtn, + preferencesServiceMock, PreferencesFlag.scheduleShowTodayBtn, toReturn: null); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, - PreferencesFlag.scheduleListView, + preferencesServiceMock, PreferencesFlag.scheduleListView, toReturn: null); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, - PreferencesFlag.scheduleShowWeekEvents, + preferencesServiceMock, PreferencesFlag.scheduleShowWeekEvents, toReturn: null); RemoteConfigServiceMock.stubGetCalendarViewEnabled( remoteConfigServiceMock); @@ -94,7 +88,8 @@ void main() { verify(preferencesServiceMock .getString(PreferencesFlag.scheduleCalendarFormat)) .called(1); - verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleShowTodayBtn)) + verify(preferencesServiceMock + .getBool(PreferencesFlag.scheduleShowTodayBtn)) .called(1); verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleListView)) .called(1); @@ -109,28 +104,22 @@ void main() { test("validate the loading of the settings", () async { // Stubs the answer of the preferences services PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.scheduleStartWeekday, + preferencesServiceMock, PreferencesFlag.scheduleStartWeekday, toReturn: EnumToString.convertToString(StartingDayOfWeek.sunday)); PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.scheduleOtherWeekday, + preferencesServiceMock, PreferencesFlag.scheduleOtherWeekday, toReturn: EnumToString.convertToString(WeekDays.monday)); PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.scheduleCalendarFormat, + preferencesServiceMock, PreferencesFlag.scheduleCalendarFormat, toReturn: EnumToString.convertToString(CalendarFormat.month)); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, - PreferencesFlag.scheduleShowTodayBtn, + preferencesServiceMock, PreferencesFlag.scheduleShowTodayBtn, toReturn: false); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, - PreferencesFlag.scheduleListView, + preferencesServiceMock, PreferencesFlag.scheduleListView, toReturn: false); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, - PreferencesFlag.scheduleShowWeekEvents, + preferencesServiceMock, PreferencesFlag.scheduleShowWeekEvents, toReturn: false); final expected = { @@ -155,7 +144,8 @@ void main() { verify(preferencesServiceMock .getString(PreferencesFlag.scheduleCalendarFormat)) .called(1); - verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleShowTodayBtn)) + verify(preferencesServiceMock + .getBool(PreferencesFlag.scheduleShowTodayBtn)) .called(1); verify(preferencesServiceMock.getBool(PreferencesFlag.scheduleListView)) .called(1); @@ -210,8 +200,7 @@ void main() { test("validate default behaviour", () async { const flag = PreferencesFlag.theme; - PreferencesServiceMock.stubGetString( - preferencesServiceMock, flag, + PreferencesServiceMock.stubGetString(preferencesServiceMock, flag, toReturn: ThemeMode.light.toString()); manager.themeMode; @@ -229,8 +218,7 @@ void main() { test("validate default behaviour", () async { const flag = PreferencesFlag.locale; PreferencesServiceMock.stubGetString( - preferencesServiceMock, - PreferencesFlag.locale, + preferencesServiceMock, PreferencesFlag.locale, toReturn: const Locale('fr').toString()); manager.setLocale('fr'); @@ -238,7 +226,8 @@ void main() { verify(preferencesServiceMock.setString(PreferencesFlag.locale, 'fr')) .called(1); - verify(preferencesServiceMock.getString(PreferencesFlag.locale)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.locale)) + .called(1); verify(analyticsServiceMock.logEvent( "${SettingsManager.tag}_${EnumToString.convertToString(flag)}", @@ -290,7 +279,8 @@ void main() { expect(manager.locale, const Locale('en')); - verify(preferencesServiceMock.getString(PreferencesFlag.locale)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.locale)) + .called(1); verifyNoMoreInteractions(preferencesServiceMock); verifyNoMoreInteractions(analyticsServiceMock); @@ -308,7 +298,8 @@ void main() { await manager.fetchLanguageAndThemeMode(); verify(preferencesServiceMock.getString(PreferencesFlag.theme)).called(1); - verify(preferencesServiceMock.getString(PreferencesFlag.locale)).called(1); + verify(preferencesServiceMock.getString(PreferencesFlag.locale)) + .called(1); verifyNoMoreInteractions(preferencesServiceMock); verifyNoMoreInteractions(analyticsServiceMock); @@ -340,8 +331,7 @@ void main() { test("setString", () async { const flag = PreferencesFlag.scheduleCalendarFormat; - PreferencesServiceMock.stubSetString( - preferencesServiceMock, flag); + PreferencesServiceMock.stubSetString(preferencesServiceMock, flag); expect(await manager.setString(flag, "test"), true, reason: @@ -359,8 +349,7 @@ void main() { test("setInt", () async { const flag = PreferencesFlag.aboutUsCard; - PreferencesServiceMock.stubSetInt( - preferencesServiceMock, flag); + PreferencesServiceMock.stubSetInt(preferencesServiceMock, flag); expect(await manager.setInt(flag, 0), true, reason: @@ -378,8 +367,7 @@ void main() { test("getString", () async { const flag = PreferencesFlag.scheduleCalendarFormat; - PreferencesServiceMock.stubGetString( - preferencesServiceMock, flag); + PreferencesServiceMock.stubGetString(preferencesServiceMock, flag); expect(await manager.getString(flag), 'test', reason: @@ -397,8 +385,7 @@ void main() { test("setBool", () async { const flag = PreferencesFlag.scheduleCalendarFormat; - PreferencesServiceMock.stubSetBool( - preferencesServiceMock, flag); + PreferencesServiceMock.stubSetBool(preferencesServiceMock, flag); expect(await manager.setBool(flag, true), true, reason: @@ -417,20 +404,16 @@ void main() { group("Dashboard - ", () { test("validate default behaviour", () async { PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.aboutUsCard, + preferencesServiceMock, PreferencesFlag.aboutUsCard, toReturn: null); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.scheduleCard, + preferencesServiceMock, PreferencesFlag.scheduleCard, toReturn: null); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.progressBarCard, + preferencesServiceMock, PreferencesFlag.progressBarCard, toReturn: null); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.gradesCard, + preferencesServiceMock, PreferencesFlag.gradesCard, toReturn: null); // Cards @@ -455,7 +438,8 @@ void main() { .called(1); verify(preferencesServiceMock.getInt(PreferencesFlag.progressBarCard)) .called(1); - verify(preferencesServiceMock.getInt(PreferencesFlag.gradesCard)).called(1); + verify(preferencesServiceMock.getInt(PreferencesFlag.gradesCard)) + .called(1); verifyNoMoreInteractions(preferencesServiceMock); verifyNoMoreInteractions(analyticsServiceMock); @@ -463,25 +447,20 @@ void main() { test("validate the loading of the cards", () async { PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.broadcastCard, + preferencesServiceMock, PreferencesFlag.broadcastCard, toReturn: 0); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.aboutUsCard, + preferencesServiceMock, PreferencesFlag.aboutUsCard, toReturn: 2); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.scheduleCard, + preferencesServiceMock, PreferencesFlag.scheduleCard, toReturn: 3); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.progressBarCard, + preferencesServiceMock, PreferencesFlag.progressBarCard, // ignore: avoid_redundant_argument_values toReturn: 1); PreferencesServiceMock.stubGetInt( - preferencesServiceMock, - PreferencesFlag.gradesCard, + preferencesServiceMock, PreferencesFlag.gradesCard, toReturn: 4); // Cards @@ -506,7 +485,8 @@ void main() { .called(1); verify(preferencesServiceMock.getInt(PreferencesFlag.progressBarCard)) .called(1); - verify(preferencesServiceMock.getInt(PreferencesFlag.gradesCard)).called(1); + verify(preferencesServiceMock.getInt(PreferencesFlag.gradesCard)) + .called(1); verifyNoMoreInteractions(preferencesServiceMock); verifyNoMoreInteractions(analyticsServiceMock); diff --git a/test/managers/user_repository_test.dart b/test/managers/user_repository_test.dart index e55b8433f..b38974299 100644 --- a/test/managers/user_repository_test.dart +++ b/test/managers/user_repository_test.dart @@ -39,8 +39,7 @@ void main() { // Setup needed service analyticsServiceMock = setupAnalyticsServiceMock(); monETSApiMock = setupMonETSApiMock(); - secureStorageMock = - setupFlutterSecureStorageMock(); + secureStorageMock = setupFlutterSecureStorageMock(); cacheManagerMock = setupCacheManagerMock(); signetsApiMock = setupSignetsApiMock(); networkingServiceMock = setupNetworkingServiceMock(); @@ -66,8 +65,7 @@ void main() { final MonETSUser user = MonETSUser( domain: "ENS", typeUsagerId: 1, username: "right credentials"); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); // Result is true expect( @@ -91,8 +89,7 @@ void main() { test('An exception is throw during the MonETSApi call', () async { const String username = "exceptionUser"; - MonETSAPIClientMock.stubException( - monETSApiMock, username); + MonETSAPIClientMock.stubException(monETSApiMock, username); expect(await manager.authenticate(username: username, password: ""), isFalse, @@ -121,8 +118,7 @@ void main() { final MonETSUser user = MonETSUser( domain: "ENS", typeUsagerId: 1, username: "right credentials"); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); FlutterSecureStorageMock.stubWriteException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -152,16 +148,13 @@ void main() { final MonETSUser user = MonETSUser(domain: "ENS", typeUsagerId: 1, username: "AAXXXXXX"); - MonETSAPIClientMock.stubException( - monETSApiMock, user.username, + MonETSAPIClientMock.stubException(monETSApiMock, user.username, exception: HttpException( prefix: "MonETSAPI", code: 415, message: "{ \"Message\": \"The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.\"}")); - SignetsAPIClientMock.stubAuthenticate( - signetsApiMock, - connected: true); + SignetsAPIClientMock.stubAuthenticate(signetsApiMock, connected: true); // Result is true expect( @@ -183,15 +176,13 @@ void main() { test('MonETSAPI failed and SignetsAPI return false', () async { const String username = "exceptionUser"; - MonETSAPIClientMock.stubException( - monETSApiMock, username, + MonETSAPIClientMock.stubException(monETSApiMock, username, exception: HttpException( prefix: "MonETSAPI", code: 415, message: "{ \"Message\": \"The request contains an entity body but no Content-Type header. The inferred media type 'application/octet-stream' is not supported for this resource.\"}")); - SignetsAPIClientMock.stubAuthenticate( - signetsApiMock); + SignetsAPIClientMock.stubAuthenticate(signetsApiMock); expect(await manager.authenticate(username: username, password: ""), isFalse, @@ -230,8 +221,7 @@ void main() { FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); expect(await manager.silentAuthenticate(), isTrue, reason: "Result should be true"); @@ -257,8 +247,7 @@ void main() { FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: password); - MonETSAPIClientMock.stubAuthenticateException( - monETSApiMock, username); + MonETSAPIClientMock.stubAuthenticateException(monETSApiMock, username); expect(await manager.silentAuthenticate(), isFalse, reason: "Result should be false"); @@ -301,8 +290,7 @@ void main() { final MonETSUser user = MonETSUser( domain: "ENS", typeUsagerId: 1, username: "right credentials"); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.usernameSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -346,7 +334,8 @@ void main() { verify(secureStorageMock.delete(key: UserRepository.usernameSecureKey)); verify(secureStorageMock.deleteAll()); - verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); + verify( + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); }); @@ -363,8 +352,7 @@ void main() { final MonETSUser user = MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); FlutterSecureStorageMock.stubRead(secureStorageMock, @@ -393,8 +381,7 @@ void main() { final MonETSUser user = MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); FlutterSecureStorageMock.stubRead(secureStorageMock, @@ -419,8 +406,7 @@ void main() { const String username = "username"; const String password = "password"; - MonETSAPIClientMock.stubAuthenticateException( - monETSApiMock, username); + MonETSAPIClientMock.stubAuthenticateException(monETSApiMock, username); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.usernameSecureKey, valueToReturn: username); FlutterSecureStorageMock.stubRead(secureStorageMock, @@ -447,8 +433,7 @@ void main() { final MonETSUser user = MonETSUser(domain: "ENS", typeUsagerId: 1, username: username); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); FlutterSecureStorageMock.stubReadException(secureStorageMock, key: UserRepository.passwordSecureKey, exceptionToThrow: PlatformException(code: "bad key")); @@ -462,7 +447,8 @@ void main() { analyticsServiceMock.logError(UserRepository.tag, any, any, any)); verify(secureStorageMock.deleteAll()); - verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); + verify( + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); }); @@ -490,8 +476,7 @@ void main() { CacheManagerMock.stubGet(cacheManagerMock, UserRepository.programsCacheKey, jsonEncode(programs)); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); // Result is true expect( @@ -500,8 +485,7 @@ void main() { reason: "Check the authentication is successful"); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetPrograms( - signetsApiMock, username, []); + SignetsAPIClientMock.stubGetPrograms(signetsApiMock, username, []); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -545,8 +529,8 @@ void main() { test("SignetsAPI return another program", () async { // Stub to simulate presence of program cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.programsCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: ''); @@ -572,12 +556,11 @@ void main() { test("SignetsAPI return an exception", () async { // Stub to simulate presence of program cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.programsCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetProgramsException( - signetsApiMock, username); + SignetsAPIClientMock.stubGetProgramsException(signetsApiMock, username); FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: ''); @@ -593,16 +576,18 @@ void main() { verify(cacheManagerMock.get(UserRepository.programsCacheKey)); verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); - verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); + verify( + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); - verifyNever(cacheManagerMock.update(UserRepository.programsCacheKey, any)); + verifyNever( + cacheManagerMock.update(UserRepository.programsCacheKey, any)); }); test("Cache update fail", () async { // Stub to simulate presence of program cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.programsCacheKey, jsonEncode([])); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.programsCacheKey, jsonEncode([])); // Stub to simulate exception when updating cache CacheManagerMock.stubUpdateException( @@ -643,10 +628,7 @@ void main() { lastName: 'Doe', permanentCode: 'DOEJ00000000'); final ProfileStudent defaultInfo = ProfileStudent( - balance: '', - firstName: '', - lastName: '', - permanentCode: ''); + balance: '', firstName: '', lastName: '', permanentCode: ''); const String username = "username"; @@ -655,12 +637,11 @@ void main() { setUp(() async { // Stub to simulate presence of info cache - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.infoCacheKey, jsonEncode(info)); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); + + MonETSAPIClientMock.stubAuthenticate(monETSApiMock, user); - MonETSAPIClientMock.stubAuthenticate( - monETSApiMock, user); - FlutterSecureStorageMock.stubRead(secureStorageMock, key: UserRepository.passwordSecureKey, valueToReturn: ''); @@ -671,8 +652,7 @@ void main() { reason: "Check the authentication is successful"); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetInfo( - signetsApiMock, username, defaultInfo); + SignetsAPIClientMock.stubGetInfo(signetsApiMock, username, defaultInfo); // Stub to simulate that the user has an active internet connection NetworkingServiceMock.stubHasConnectivity(networkingServiceMock); @@ -705,15 +685,15 @@ void main() { verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); - verifyNever( - cacheManagerMock.update(UserRepository.infoCacheKey, jsonEncode(info))); + verifyNever(cacheManagerMock.update( + UserRepository.infoCacheKey, jsonEncode(info))); }); test("SignetsAPI return another info", () async { // Stub to simulate presence of info cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.infoCacheKey, jsonEncode(info)); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); // Stub SignetsApi answer to test only the cache retrieving final ProfileStudent anotherInfo = ProfileStudent( @@ -722,8 +702,7 @@ void main() { lastName: 'Doe', permanentCode: 'DOEJ00000000'); reset(signetsApiMock); - SignetsAPIClientMock.stubGetInfo( - signetsApiMock, username, anotherInfo); + SignetsAPIClientMock.stubGetInfo(signetsApiMock, username, anotherInfo); expect(manager.info, isNull); final results = await manager.getInfo(); @@ -742,8 +721,7 @@ void main() { test("SignetsAPI return a info that already exists", () async { // Stub SignetsApi answer to test only the cache retrieving reset(signetsApiMock); - SignetsAPIClientMock.stubGetInfo( - signetsApiMock, username, info); + SignetsAPIClientMock.stubGetInfo(signetsApiMock, username, info); expect(manager.info, isNull); final results = await manager.getInfo(); @@ -755,19 +733,18 @@ void main() { verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); - verifyNever( - cacheManagerMock.update(UserRepository.infoCacheKey, jsonEncode(info))); + verifyNever(cacheManagerMock.update( + UserRepository.infoCacheKey, jsonEncode(info))); }); test("SignetsAPI return an exception", () async { // Stub to simulate presence of info cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.infoCacheKey, jsonEncode(info)); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetInfoException( - signetsApiMock, username); + SignetsAPIClientMock.stubGetInfoException(signetsApiMock, username); expect(manager.info, isNull); expect(manager.getInfo(), throwsA(isInstanceOf())); @@ -778,7 +755,8 @@ void main() { verify(cacheManagerMock.get(UserRepository.infoCacheKey)); verify(secureStorageMock.read(key: UserRepository.passwordSecureKey)); - verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); + verify( + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); verifyNever(cacheManagerMock.update(UserRepository.infoCacheKey, any)); }); @@ -786,16 +764,15 @@ void main() { test("Cache update fail", () async { // Stub to simulate presence of session cache reset(cacheManagerMock); - CacheManagerMock.stubGet(cacheManagerMock, - UserRepository.infoCacheKey, jsonEncode(info)); + CacheManagerMock.stubGet( + cacheManagerMock, UserRepository.infoCacheKey, jsonEncode(info)); // Stub to simulate exception when updating cache CacheManagerMock.stubUpdateException( cacheManagerMock, UserRepository.infoCacheKey); // Stub SignetsApi answer to test only the cache retrieving - SignetsAPIClientMock.stubGetInfo( - signetsApiMock, username, info); + SignetsAPIClientMock.stubGetInfo(signetsApiMock, username, info); expect(manager.info, isNull); final results = await manager.getInfo(); @@ -856,7 +833,8 @@ void main() { expect(await manager.wasPreviouslyLoggedIn(), isFalse); verify(secureStorageMock.deleteAll()); - verify(analyticsServiceMock.logError(UserRepository.tag, any, any, any)); + verify( + analyticsServiceMock.logError(UserRepository.tag, any, any, any)); }); }); }); diff --git a/test/mock/managers/course_repository_mock.dart b/test/mock/managers/course_repository_mock.dart index 498ddf505..6dee4cedc 100644 --- a/test/mock/managers/course_repository_mock.dart +++ b/test/mock/managers/course_repository_mock.dart @@ -32,8 +32,7 @@ class CourseRepositoryMock extends MockCourseRepository { /// Stub the function [getCoursesActivities] of [mock] when called will return [toReturn]. static void stubGetCoursesActivities(CourseRepositoryMock mock, {List toReturn = const [], bool fromCacheOnly = false}) { - when(mock.getCoursesActivities( - fromCacheOnly: fromCacheOnly)) + when(mock.getCoursesActivities(fromCacheOnly: fromCacheOnly)) .thenAnswer((_) async => toReturn); } @@ -41,9 +40,8 @@ class CourseRepositoryMock extends MockCourseRepository { static void stubGetCoursesActivitiesException(CourseRepositoryMock mock, {Exception toThrow = const ApiException(prefix: 'ApiException'), bool fromCacheOnly = false}) { - when(mock.getCoursesActivities( - fromCacheOnly: fromCacheOnly)) - .thenAnswer((_) => Future.delayed(const Duration(milliseconds: 50)) + when(mock.getCoursesActivities(fromCacheOnly: fromCacheOnly)).thenAnswer( + (_) => Future.delayed(const Duration(milliseconds: 50)) .then((value) => throw toThrow)); } @@ -64,8 +62,7 @@ class CourseRepositoryMock extends MockCourseRepository { /// Stub the function [getCourses] of [mock] when called will return [toReturn]. static void stubGetCourses(CourseRepositoryMock mock, {List toReturn = const [], bool fromCacheOnly = false}) { - when(mock.getCourses( - fromCacheOnly: fromCacheOnly)) + when(mock.getCourses(fromCacheOnly: fromCacheOnly)) .thenAnswer((_) async => toReturn); } @@ -79,9 +76,8 @@ class CourseRepositoryMock extends MockCourseRepository { static void stubGetCoursesException(CourseRepositoryMock mock, {Exception toThrow = const ApiException(prefix: 'ApiException'), bool fromCacheOnly = false}) { - when(mock.getCourses( - fromCacheOnly: fromCacheOnly)) - .thenAnswer((_) => Future.delayed(const Duration(milliseconds: 50)) + when(mock.getCourses(fromCacheOnly: fromCacheOnly)).thenAnswer((_) => + Future.delayed(const Duration(milliseconds: 50)) .then((value) => throw toThrow)); } @@ -103,9 +99,9 @@ class CourseRepositoryMock extends MockCourseRepository { /// Stub the function [getScheduleActivities] of [mock] when called will return [toReturn]. static void stubGetScheduleActivities(CourseRepositoryMock mock, - {List toReturn = const [], bool fromCacheOnly = false}) { - when(mock.getScheduleActivities( - fromCacheOnly: fromCacheOnly)) + {List toReturn = const [], + bool fromCacheOnly = false}) { + when(mock.getScheduleActivities(fromCacheOnly: fromCacheOnly)) .thenAnswer((_) async => toReturn); } diff --git a/test/mock/managers/settings_manager_mock.dart b/test/mock/managers/settings_manager_mock.dart index f4bc3c268..a27043f2c 100644 --- a/test/mock/managers/settings_manager_mock.dart +++ b/test/mock/managers/settings_manager_mock.dart @@ -75,7 +75,8 @@ class SettingsManagerMock extends MockSettingsManager { } /// Stub the [dateTimeNow] function of [mock], when called return [toReturn]. - static void stubDateTimeNow(SettingsManagerMock mock, {required DateTime toReturn}) { + static void stubDateTimeNow(SettingsManagerMock mock, + {required DateTime toReturn}) { // ignore: cast_nullable_to_non_nullable when(mock.dateTimeNow).thenReturn(toReturn); } diff --git a/test/mock/services/github_api_mock.dart b/test/mock/services/github_api_mock.dart index ee8f82130..404632d52 100644 --- a/test/mock/services/github_api_mock.dart +++ b/test/mock/services/github_api_mock.dart @@ -28,9 +28,11 @@ class GithubApiMock extends MockGithubApi { } static void stubCreateGithubIssue(GithubApiMock client, Issue toReturn) { - when(client.createGithubIssue(feedbackText: anyNamed("feedbackText"), - fileName: anyNamed("fileName"), feedbackType: anyNamed("feedbackType"), - email: anyNamed("email"))) + when(client.createGithubIssue( + feedbackText: anyNamed("feedbackText"), + fileName: anyNamed("fileName"), + feedbackType: anyNamed("feedbackType"), + email: anyNamed("email"))) .thenAnswer((_) async => Future.value(toReturn)); } } diff --git a/test/services/app_widget_service_test.dart b/test/services/app_widget_service_test.dart index 348b40a71..b458ca0c1 100644 --- a/test/services/app_widget_service_test.dart +++ b/test/services/app_widget_service_test.dart @@ -15,7 +15,7 @@ void main() { late HomeWidgetMock homeWidgetMock; late AppWidgetService service; - + group("AppWidgetServiceTest - ", () { setUp(() { setupAnalyticsServiceMock(); diff --git a/test/ui/views/dashboard_view_test.dart b/test/ui/views/dashboard_view_test.dart index ab1410a30..9f4b439db 100644 --- a/test/ui/views/dashboard_view_test.dart +++ b/test/ui/views/dashboard_view_test.dart @@ -142,24 +142,21 @@ void main() { Future testDashboardSchedule(WidgetTester tester, DateTime now, List courses, int expected) async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubDateTimeNow(settingsManagerMock, - toReturn: now); + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: now); - await tester.pumpWidget( - localizedWidget(child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + await tester.pumpWidget(localizedWidget( + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find schedule card in second position by its title @@ -187,53 +184,36 @@ void main() { InAppReviewServiceMock.stubIsAvailable(inAppReviewServiceMock, toReturn: false); - CourseRepositoryMock.stubSessions( - courseRepositoryMock, + CourseRepositoryMock.stubSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubGetSessions( - courseRepositoryMock, + CourseRepositoryMock.stubGetSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - - RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastColor( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastEn( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastFr( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastTitleEn( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastTitleFr( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastType( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastUrl( - remoteConfigServiceMock); - - SettingsManagerMock.stubGetBool(settingsManagerMock, - PreferencesFlag.discoveryDashboard, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + + RemoteConfigServiceMock.stubGetBroadcastEnabled(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastColor(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastEn(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastFr(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastTitleEn(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastTitleFr(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastType(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastUrl(remoteConfigServiceMock); + + SettingsManagerMock.stubGetBool( + settingsManagerMock, PreferencesFlag.discoveryDashboard, toReturn: true); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.broadcastCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.broadcastCard); SettingsManagerMock.stubSetInt( settingsManagerMock, PreferencesFlag.aboutUsCard); @@ -241,14 +221,13 @@ void main() { SettingsManagerMock.stubSetInt( settingsManagerMock, PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.progressBarCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.progressBarCard); SettingsManagerMock.stubSetInt( settingsManagerMock, PreferencesFlag.gradesCard); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime.now()); }); @@ -257,12 +236,12 @@ void main() { group('UI - ', () { testWidgets('Has view title restore button and cards, displayed', (WidgetTester tester) async { - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dashboard Title @@ -283,22 +262,19 @@ void main() { testWidgets('Has card aboutUs displayed properly', (WidgetTester tester) async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find aboutUs card @@ -382,36 +358,33 @@ void main() { group('Interactions - ', () { testWidgets('AboutUsCard is dismissible and can be restored', (WidgetTester tester) async { - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.broadcastCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.aboutUsCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.scheduleCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.scheduleCard); SettingsManagerMock.stubSetInt( settingsManagerMock, PreferencesFlag.gradesCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.progressBarCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.progressBarCard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -442,35 +415,32 @@ void main() { testWidgets('AboutUsCard is reorderable and can be restored', (WidgetTester tester) async { - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.broadcastCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.aboutUsCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.scheduleCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.scheduleCard); SettingsManagerMock.stubSetInt( settingsManagerMock, PreferencesFlag.gradesCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.progressBarCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.progressBarCard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -526,12 +496,12 @@ void main() { testWidgets('ScheduleCard is dismissible and can be restored', (WidgetTester tester) async { - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -567,12 +537,12 @@ void main() { group('UI - gradesCard', () { testWidgets('Has card grades displayed - with no courses', (WidgetTester tester) async { - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find grades card @@ -593,23 +563,19 @@ void main() { testWidgets('Has card grades displayed - with courses', (WidgetTester tester) async { - CourseRepositoryMock.stubCourses( - courseRepositoryMock, - toReturn: courses); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - fromCacheOnly: true, + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + fromCacheOnly: true, toReturn: courses); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find grades card @@ -628,26 +594,26 @@ void main() { testWidgets('gradesCard is dismissible and can be restored', (WidgetTester tester) async { - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.broadcastCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.aboutUsCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.scheduleCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.progressBarCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.progressBarCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.gradesCard); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.gradesCard); + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -684,12 +650,12 @@ void main() { group("UI - progressBar", () { testWidgets('Has card progressBar displayed', (WidgetTester tester) async { - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find progress card @@ -707,12 +673,12 @@ void main() { testWidgets('progressCard is dismissible and can be restored', (WidgetTester tester) async { - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -745,12 +711,12 @@ void main() { testWidgets('progressBarCard is reorderable and can be restored', (WidgetTester tester) async { InAppReviewServiceMock.stubIsAvailable(inAppReviewServiceMock); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); // Find Dismissible Cards @@ -811,8 +777,7 @@ void main() { }); testWidgets("Applets Card", (WidgetTester tester) async { - RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigServiceMock, + RemoteConfigServiceMock.stubGetBroadcastEnabled(remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -821,12 +786,12 @@ void main() { PreferencesFlag.aboutUsCard: 1, }; - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); await expectLater(find.byType(DashboardView), @@ -834,38 +799,33 @@ void main() { }); testWidgets("Schedule card", (WidgetTester tester) async { - RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigServiceMock, + RemoteConfigServiceMock.stubGetBroadcastEnabled(remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); dashboard = { PreferencesFlag.broadcastCard: 0, PreferencesFlag.scheduleCard: 1, }; - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); await expectLater(find.byType(DashboardView), matchesGoldenFile(goldenFilePath("dashboardView_scheduleCard_1"))); }); testWidgets("progressBar Card", (WidgetTester tester) async { - RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigServiceMock, + RemoteConfigServiceMock.stubGetBroadcastEnabled(remoteConfigServiceMock, toReturn: false); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -874,12 +834,12 @@ void main() { PreferencesFlag.progressBarCard: 1, }; - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: const DashboardView(updateCode: UpdateCode.none)))); + child: FeatureDiscovery( + child: const DashboardView(updateCode: UpdateCode.none)))); await tester.pumpAndSettle(); await expectLater( diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index f73fb34f3..178bc8990 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -112,7 +112,8 @@ void main() { 'has a RefreshIndicator, GradeCircularProgress, three cards and evaluation tiles when a course is valid', (WidgetTester tester) async { setupFlutterToastMock(tester); - CourseRepositoryMock.stubGetCourseSummary(courseRepositoryMock, course, toReturn: course); + CourseRepositoryMock.stubGetCourseSummary(courseRepositoryMock, course, + toReturn: course); await tester.pumpWidget(localizedWidget( child: FeatureDiscovery(child: GradesDetailsView(course: course)))); await tester.pumpAndSettle(); @@ -144,7 +145,8 @@ void main() { toReturn: course); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); + child: FeatureDiscovery( + child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); expect(find.byType(SliverAppBar), findsOneWidget); @@ -165,7 +167,8 @@ void main() { toReturn: course); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); + child: FeatureDiscovery( + child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); final gesture = await tester @@ -198,8 +201,7 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepositoryMock, - courseWithEvaluationNotCompleted, + courseRepositoryMock, courseWithEvaluationNotCompleted, toReturn: courseWithEvaluationNotCompleted); await tester.pumpWidget(localizedWidget( diff --git a/test/ui/views/grades_view_test.dart b/test/ui/views/grades_view_test.dart index 250bb07a5..d0f354b70 100644 --- a/test/ui/views/grades_view_test.dart +++ b/test/ui/views/grades_view_test.dart @@ -79,12 +79,9 @@ void main() { group("golden -", () { testWidgets("No grades available", (WidgetTester tester) async { // Mock the repository to have 0 courses available - CourseRepositoryMock.stubCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -100,15 +97,11 @@ void main() { testWidgets("Multiples sessions and grades loaded", (WidgetTester tester) async { // Mock the repository to have 0 courses available - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -126,12 +119,9 @@ void main() { "Right message is displayed when there is no grades available", (WidgetTester tester) async { // Mock the repository to have 0 courses available - CourseRepositoryMock.stubCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -147,15 +137,11 @@ void main() { "Correct number of grade button and right session name are displayed", (WidgetTester tester) async { // Mock the repository to have 4 courses available - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); diff --git a/test/ui/views/more_view_test.dart b/test/ui/views/more_view_test.dart index 5d74acb80..46cfedbd8 100644 --- a/test/ui/views/more_view_test.dart +++ b/test/ui/views/more_view_test.dart @@ -159,7 +159,8 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigationServiceMock.pushNamed(RouterPaths.contributors)).called(1); + verify(navigationServiceMock.pushNamed(RouterPaths.contributors)) + .called(1); }); testWidgets('licenses', (WidgetTester tester) async { @@ -196,7 +197,8 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigationServiceMock.pushNamed(RouterPaths.faq, arguments: Colors.white)) + verify(navigationServiceMock.pushNamed(RouterPaths.faq, + arguments: Colors.white)) .called(1); }); @@ -214,7 +216,8 @@ void main() { // Rebuild the widget after the state has changed. await tester.pump(); - verify(navigationServiceMock.pushNamed(RouterPaths.settings)).called(1); + verify(navigationServiceMock.pushNamed(RouterPaths.settings)) + .called(1); }); testWidgets('logout', (WidgetTester tester) async { diff --git a/test/ui/views/not_found_view_test.dart b/test/ui/views/not_found_view_test.dart index 0c26d61bb..e48bb25d2 100644 --- a/test/ui/views/not_found_view_test.dart +++ b/test/ui/views/not_found_view_test.dart @@ -20,7 +20,8 @@ void main() { setupNavigationServiceMock(); setupAnalyticsServiceMock(); final riveAnimationMock = setupRiveAnimationServiceMock(); - RiveAnimationServiceMock.stubLoadRiveFile(riveAnimationMock, 'dot_jumping', RuntimeArtboard()); + RiveAnimationServiceMock.stubLoadRiveFile( + riveAnimationMock, 'dot_jumping', RuntimeArtboard()); }); tearDown(() {}); diff --git a/test/ui/views/profile_view_test.dart b/test/ui/views/profile_view_test.dart index 201063094..fa98c8efd 100644 --- a/test/ui/views/profile_view_test.dart +++ b/test/ui/views/profile_view_test.dart @@ -49,8 +49,7 @@ void main() { UserRepositoryMock.stubGetInfo(userRepositoryMock, toReturn: profileStudent); - UserRepositoryMock.stubProfileStudent( - userRepositoryMock, + UserRepositoryMock.stubProfileStudent(userRepositoryMock, toReturn: profileStudent); UserRepositoryMock.stubGetPrograms(userRepositoryMock, diff --git a/test/ui/views/quick_links_view_test.dart b/test/ui/views/quick_links_view_test.dart index ccc1f5b79..31c3d112a 100644 --- a/test/ui/views/quick_links_view_test.dart +++ b/test/ui/views/quick_links_view_test.dart @@ -36,8 +36,7 @@ void main() { setupNetworkingServiceMock(); setupLaunchUrlServiceMock(); quickLinkRepositoryMock = setupQuickLinkRepositoryMock(); - QuickLinkRepositoryMock.stubGetDefaultQuickLinks( - quickLinkRepositoryMock, + QuickLinkRepositoryMock.stubGetDefaultQuickLinks(quickLinkRepositoryMock, toReturn: quickLinks(intl)); QuickLinkRepositoryMock.stubGetQuickLinkDataFromCacheException( diff --git a/test/ui/views/student_view_test.dart b/test/ui/views/student_view_test.dart index 6bb1cf6e8..8cb497f38 100644 --- a/test/ui/views/student_view_test.dart +++ b/test/ui/views/student_view_test.dart @@ -29,12 +29,9 @@ void main() { setupSettingsManagerMock(); setupAnalyticsServiceMock(); - CourseRepositoryMock.stubCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); }); diff --git a/test/ui/widgets/bottom_bar_test.dart b/test/ui/widgets/bottom_bar_test.dart index 179a240da..dc069a22e 100644 --- a/test/ui/widgets/bottom_bar_test.dart +++ b/test/ui/widgets/bottom_bar_test.dart @@ -71,8 +71,8 @@ void main() { await tester.tap(find.byIcon(Icons.schedule)); await tester.tap(find.byIcon(Icons.dashboard)); - verify( - navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.dashboard)); + verify(navigationServiceMock + .pushNamedAndRemoveUntil(RouterPaths.dashboard)); }); testWidgets('schedule', (WidgetTester tester) async { @@ -82,7 +82,8 @@ void main() { await tester.tap(find.byIcon(Icons.schedule)); - verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.schedule)); + verify(navigationServiceMock + .pushNamedAndRemoveUntil(RouterPaths.schedule)); }); testWidgets('student', (WidgetTester tester) async { @@ -92,7 +93,8 @@ void main() { await tester.tap(find.byIcon(Icons.school)); - verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.student)); + verify( + navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.student)); }); testWidgets('ets', (WidgetTester tester) async { diff --git a/test/ui/widgets/grade_button_test.dart b/test/ui/widgets/grade_button_test.dart index 3ba4dafe1..e6e1f3deb 100644 --- a/test/ui/widgets/grade_button_test.dart +++ b/test/ui/widgets/grade_button_test.dart @@ -70,12 +70,11 @@ void main() { testWidgets("Display acronym of the course and the current grade", (WidgetTester tester) async { SettingsManagerMock.stubGetString( - settingsManagerMock, - PreferencesFlag.discoveryStudentGrade, + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: 'true'); - await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithGrade))); + await tester + .pumpWidget(localizedWidget(child: GradeButton(courseWithGrade))); await tester.pumpAndSettle(); expect(find.text(courseWithGrade.acronym), findsOneWidget); @@ -85,12 +84,11 @@ void main() { testWidgets("Grade not available and summary is loaded.", (WidgetTester tester) async { SettingsManagerMock.stubGetString( - settingsManagerMock, - PreferencesFlag.discoveryStudentGrade, + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: 'true'); - await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithSummary))); + await tester + .pumpWidget(localizedWidget(child: GradeButton(courseWithSummary))); await tester.pumpAndSettle(); expect(find.text(courseWithGrade.acronym), findsOneWidget); @@ -106,12 +104,11 @@ void main() { testWidgets("Grade and summary not available.", (WidgetTester tester) async { SettingsManagerMock.stubGetString( - settingsManagerMock, - PreferencesFlag.discoveryStudentGrade, + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: 'true'); - await tester.pumpWidget(localizedWidget( - child: GradeButton(gradesNotAvailable))); + await tester.pumpWidget( + localizedWidget(child: GradeButton(gradesNotAvailable))); await tester.pumpAndSettle(); expect(find.text(courseWithGrade.acronym), findsOneWidget); @@ -125,11 +122,11 @@ void main() { group('Interactions - ', () { testWidgets('Grade button redirects to grades view when tapped ', (WidgetTester tester) async { - SettingsManagerMock.stubGetBool(settingsManagerMock, - PreferencesFlag.discoveryStudentGrade, + SettingsManagerMock.stubGetBool( + settingsManagerMock, PreferencesFlag.discoveryStudentGrade, toReturn: true); - await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithGrade))); + await tester + .pumpWidget(localizedWidget(child: GradeButton(courseWithGrade))); await tester.pumpAndSettle(); await tester.tap(find.text(courseWithGrade.acronym)); @@ -141,8 +138,8 @@ void main() { testWidgets( 'Grade button does not redirect to grades view if the grades discovery did not already launch', (WidgetTester tester) async { - await tester.pumpWidget(localizedWidget( - child: GradeButton(courseWithGrade))); + await tester + .pumpWidget(localizedWidget(child: GradeButton(courseWithGrade))); await tester.pumpAndSettle(); await tester.tap(find.text(courseWithGrade.acronym)); diff --git a/test/ui/widgets/grade_evaluation_tile_test.dart b/test/ui/widgets/grade_evaluation_tile_test.dart index 5d171876d..91e56317e 100644 --- a/test/ui/widgets/grade_evaluation_tile_test.dart +++ b/test/ui/widgets/grade_evaluation_tile_test.dart @@ -65,8 +65,7 @@ void main() { await tester.pumpWidget(localizedWidget( child: FeatureDiscovery( - child: GradeEvaluationTile(evaluation, - completed: true)))); + child: GradeEvaluationTile(evaluation, completed: true)))); await tester.pumpAndSettle(); final circularPercentIndicator = find.byType(GradeCircularProgress); @@ -85,8 +84,7 @@ void main() { final widget = localizedWidget( child: FeatureDiscovery( - child: GradeEvaluationTile(evaluation, - completed: true))); + child: GradeEvaluationTile(evaluation, completed: true))); await tester.pumpWidget(widget); diff --git a/test/ui/widgets/password_text_field_test.dart b/test/ui/widgets/password_text_field_test.dart index 7a2938ea9..b6b937e8b 100644 --- a/test/ui/widgets/password_text_field_test.dart +++ b/test/ui/widgets/password_text_field_test.dart @@ -26,8 +26,7 @@ void main() { testWidgets('has a label, the visibility icon and obscure text', (WidgetTester tester) async { - await tester - .pumpWidget(localizedWidget(child: passwordFormField)); + await tester.pumpWidget(localizedWidget(child: passwordFormField)); await tester.pumpAndSettle(); final icon = find.byIcon(Icons.visibility); @@ -41,8 +40,7 @@ void main() { testWidgets( 'toggling the visibility button should disable the obscureText property', (WidgetTester tester) async { - await tester - .pumpWidget(localizedWidget(child: passwordFormField)); + await tester.pumpWidget(localizedWidget(child: passwordFormField)); await tester.pumpAndSettle(); await tester.tap(find.byIcon(Icons.visibility)); @@ -60,8 +58,7 @@ void main() { testWidgets( 'toggling the visibility button two times should enable the obscureText property', (WidgetTester tester) async { - await tester - .pumpWidget(localizedWidget(child: passwordFormField)); + await tester.pumpWidget(localizedWidget(child: passwordFormField)); await tester.pumpAndSettle(); await tester.tap(find.byIcon(Icons.visibility)); diff --git a/test/ui/widgets/schedule_settings_test.dart b/test/ui/widgets/schedule_settings_test.dart index b7255cf74..2d855f028 100644 --- a/test/ui/widgets/schedule_settings_test.dart +++ b/test/ui/widgets/schedule_settings_test.dart @@ -77,20 +77,18 @@ void main() { group("ScheduleSettings - ", () { setUp(() async { settingsManagerMock = setupSettingsManagerMock(); - courseRepositoryMock = - setupCourseRepositoryMock(); - remoteConfigServiceMock = - setupRemoteConfigServiceMock(); + courseRepositoryMock = setupCourseRepositoryMock(); + remoteConfigServiceMock = setupRemoteConfigServiceMock(); intl = await setupAppIntl(); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock); - RemoteConfigServiceMock.stubGetCalendarViewEnabled(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetCalendarViewEnabled( + remoteConfigServiceMock); }); group("ui - ", () { testWidgets("With handle", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester .pumpWidget(localizedWidget(child: const ScheduleSettings())); @@ -176,8 +174,7 @@ void main() { }); testWidgets("Without handle", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); await tester.pumpWidget( @@ -266,8 +263,7 @@ void main() { testWidgets( "Should display activity selection section when a course has activities", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); @@ -303,16 +299,13 @@ void main() { testWidgets( "When a settings laboratory is already selected, verify that it is in fact preselected", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); // preselect the laboB - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN101", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN101", toReturn: ActivityCode.labGroupB); const scheduleSettings = ScheduleSettings(showHandle: false); @@ -340,8 +333,7 @@ void main() { testWidgets( "if there is only a laboA (no labo b) the options should not appear on screen", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); final courseWithOnlyLabA = List.from( classOneWithLaboratoryABscheduleActivities); @@ -368,12 +360,10 @@ void main() { group("interactions - ", () { testWidgets("onChange calendarFormat", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); SettingsManagerMock.stubSetString( - settingsManagerMock, - PreferencesFlag.scheduleCalendarFormat); + settingsManagerMock, PreferencesFlag.scheduleCalendarFormat); await tester.pumpWidget( localizedWidget(child: const ScheduleSettings(showHandle: false))); @@ -397,11 +387,10 @@ void main() { }); testWidgets("onChange showTodayBtn", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); - SettingsManagerMock.stubSetBool(settingsManagerMock, - PreferencesFlag.scheduleShowTodayBtn); + SettingsManagerMock.stubSetBool( + settingsManagerMock, PreferencesFlag.scheduleShowTodayBtn); await tester.pumpWidget( localizedWidget(child: const ScheduleSettings(showHandle: false))); @@ -419,8 +408,8 @@ void main() { await tester.pumpAndSettle(); - await untilCalled( - settingsManagerMock.setBool(PreferencesFlag.scheduleShowTodayBtn, any)); + await untilCalled(settingsManagerMock.setBool( + PreferencesFlag.scheduleShowTodayBtn, any)); expect( tester.widget(find.descendant( @@ -436,8 +425,7 @@ void main() { testWidgets( "Should display activity selection section when a course has activities", (WidgetTester tester) async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); diff --git a/test/viewmodels/choose_language_viewmodel_test.dart b/test/viewmodels/choose_language_viewmodel_test.dart index 8cf5407e6..1e93a2e52 100644 --- a/test/viewmodels/choose_language_viewmodel_test.dart +++ b/test/viewmodels/choose_language_viewmodel_test.dart @@ -44,7 +44,8 @@ void main() { verify(settingsManagerMock .setLocale(AppIntl.supportedLocales.first.languageCode)); verify(navigationServiceMock.pop()); - verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.login)); + verify( + navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.login)); }); test('can set language français', () async { @@ -56,7 +57,8 @@ void main() { verify(settingsManagerMock .setLocale(AppIntl.supportedLocales.last.languageCode)); verify(navigationServiceMock.pop()); - verify(navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.login)); + verify( + navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.login)); }); test('throws an error when index does not exist', () async { diff --git a/test/viewmodels/dashboard_viewmodel_test.dart b/test/viewmodels/dashboard_viewmodel_test.dart index 1d223531f..21932be10 100644 --- a/test/viewmodels/dashboard_viewmodel_test.dart +++ b/test/viewmodels/dashboard_viewmodel_test.dart @@ -202,27 +202,19 @@ void main() { preferencesServiceMock = setupPreferencesServiceMock(); viewModel = DashboardViewModel(intl: await setupAppIntl()); - CourseRepositoryMock.stubGetSessions( - courseRepositoryMock, + CourseRepositoryMock.stubGetSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(2020)); - RemoteConfigServiceMock.stubGetBroadcastEnabled( - remoteConfigServiceMock); - RemoteConfigServiceMock.stubGetBroadcastEn( - remoteConfigServiceMock, + RemoteConfigServiceMock.stubGetBroadcastEnabled(remoteConfigServiceMock); + RemoteConfigServiceMock.stubGetBroadcastEn(remoteConfigServiceMock, toReturn: ""); inAppReviewServiceMock = @@ -236,22 +228,16 @@ void main() { group('futureToRunGrades -', () { test('first load from cache than call SignetsAPI to get the courses', () async { - CourseRepositoryMock.stubSessions( - courseRepositoryMock, + CourseRepositoryMock.stubSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubGetSessions( - courseRepositoryMock, + CourseRepositoryMock.stubGetSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); expect(await viewModel.futureToRunGrades(), courses); @@ -275,26 +261,19 @@ void main() { test('Signets throw an error while trying to get courses', () async { setupFlutterToastMock(); - CourseRepositoryMock.stubSessions( - courseRepositoryMock, + CourseRepositoryMock.stubSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubGetSessions( - courseRepositoryMock, + CourseRepositoryMock.stubGetSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesException( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesException(courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); expect(await viewModel.futureToRunGrades(), courses, @@ -319,11 +298,8 @@ void main() { }); test('There is no session active', () async { - CourseRepositoryMock.stubSessions( - courseRepositoryMock, - toReturn: []); - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubSessions(courseRepositoryMock, toReturn: []); + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: []); expect(await viewModel.futureToRunGrades(), [], @@ -347,25 +323,18 @@ void main() { group("futureToRun - ", () { test("The initial cards are correctly loaded", () async { setupFlutterToastMock(); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesException( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesException(courseRepositoryMock, fromCacheOnly: true); - CourseRepositoryMock.stubGetSessions( - courseRepositoryMock); - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubGetSessions(courseRepositoryMock); + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); await viewModel.futureToRun(); @@ -385,20 +354,15 @@ void main() { }); test("build the list todays activities sorted by time", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 8)); await viewModel.futureToRun(); @@ -420,20 +384,15 @@ void main() { test( "build the list todays activities (doesnt remove activity when pending completion)", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 11, 59)); await viewModel.futureToRun(); @@ -454,20 +413,15 @@ void main() { test("build the list todays activities (remove activity when finished)", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 12, 01)); await viewModel.futureToRun(); @@ -489,20 +443,15 @@ void main() { }); test("build the list tomorrow activities sorted by time", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activities); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); final now = DateTime.now(); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(now.year, now.month, now.day, 8)); await viewModel.futureToRun(); @@ -524,26 +473,18 @@ void main() { test( "build the list todays activities with the right course activities (should not have labo A)", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesWithLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN101"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN101"); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN102"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN102"); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupB); expect(await viewModel.removeLaboratoryGroup(activitiesWithLabs), [ @@ -557,26 +498,18 @@ void main() { test( "build the list todays activities with the right course activities (should not have labo B)", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesWithLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN101"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN101"); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN102"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN102"); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103", + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103", toReturn: ActivityCode.labGroupA); expect(await viewModel.removeLaboratoryGroup(activitiesWithLabs), [ @@ -590,26 +523,18 @@ void main() { test( "build the list todays activities with the right course activities (should have both labs)", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock, toReturn: activitiesWithLabs); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN101"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN101"); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN102"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN102"); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - "GEN103"); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, "GEN103"); expect(await viewModel.removeLaboratoryGroup(activitiesWithLabs), activitiesWithLabs); @@ -618,25 +543,18 @@ void main() { test("An exception is thrown during the preferenceService call", () async { setupFlutterToastMock(); - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); PreferencesServiceMock.stubException( - preferenceServiceMock, - PreferencesFlag.broadcastCard); + preferenceServiceMock, PreferencesFlag.broadcastCard); PreferencesServiceMock.stubException( - preferenceServiceMock, - PreferencesFlag.aboutUsCard); + preferenceServiceMock, PreferencesFlag.aboutUsCard); PreferencesServiceMock.stubException( - preferenceServiceMock, - PreferencesFlag.scheduleCard); + preferenceServiceMock, PreferencesFlag.scheduleCard); PreferencesServiceMock.stubException( - preferenceServiceMock, - PreferencesFlag.progressBarCard); + preferenceServiceMock, PreferencesFlag.progressBarCard); await viewModel.futureToRun(); expect(viewModel.cardsToDisplay, []); @@ -647,14 +565,11 @@ void main() { group("futureToRunSessionProgressBar - ", () { test("There is an active session", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(2020)); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, 0.5); @@ -662,14 +577,11 @@ void main() { }); test("Invalid date (Superior limit)", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(2020, 1, 20)); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, 1); @@ -677,14 +589,11 @@ void main() { }); test("Invalid date (Lower limit)", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock, + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock, toReturn: [session]); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubDateTimeNow( - settingsManagerMock, + SettingsManagerMock.stubDateTimeNow(settingsManagerMock, toReturn: DateTime(2019, 12, 31)); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, 0); @@ -692,8 +601,7 @@ void main() { }); test("Active session is null", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock); + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock); await viewModel.futureToRunSessionProgressBar(); expect(viewModel.progress, -1.0); @@ -703,8 +611,7 @@ void main() { test( "currentProgressBarText should be set to ProgressBarText.percentage when it is the first time changeProgressBarText is called", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock); + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock); viewModel.changeProgressBarText(); verify(settingsManagerMock.setString(PreferencesFlag.progressBarText, @@ -715,8 +622,7 @@ void main() { test( "currentProgressBarText flag should be set to ProgressBarText.remainingDays when it is the second time changeProgressBarText is called", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock); + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock); viewModel.changeProgressBarText(); viewModel.changeProgressBarText(); @@ -728,8 +634,7 @@ void main() { test( "currentProgressBarText flag should be set to ProgressBarText.daysElapsedWithTotalDays when it is the third time changeProgressBarText is called", () async { - CourseRepositoryMock.stubActiveSessions( - courseRepositoryMock); + CourseRepositoryMock.stubActiveSessions(courseRepositoryMock); viewModel.changeProgressBarText(); viewModel.changeProgressBarText(); @@ -743,20 +648,18 @@ void main() { group("interact with cards - ", () { test("can hide a card and reset cards to default layout", () async { - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.progressBarCard); - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.broadcastCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.aboutUsCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.scheduleCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.progressBarCard); + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); await viewModel.futureToRun(); @@ -798,8 +701,8 @@ void main() { PreferencesFlag.progressBarCard ]); - verify( - analyticsServiceMock.logEvent("DashboardViewModel", "Restoring cards")); + verify(analyticsServiceMock.logEvent( + "DashboardViewModel", "Restoring cards")); verify(settingsManagerMock.getDashboard()).called(1); verify(settingsManagerMock.setInt(PreferencesFlag.broadcastCard, 0)) .called(1); @@ -816,25 +719,21 @@ void main() { }); test("can set new order for cards", () async { - CourseRepositoryMock.stubGetCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubCoursesActivities( - courseRepositoryMock); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - - SettingsManagerMock.stubGetDashboard( - settingsManagerMock, + CourseRepositoryMock.stubGetCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubCoursesActivities(courseRepositoryMock); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + + SettingsManagerMock.stubGetDashboard(settingsManagerMock, toReturn: dashboard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.broadcastCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.aboutUsCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.scheduleCard); - SettingsManagerMock.stubSetInt(settingsManagerMock, - PreferencesFlag.progressBarCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.broadcastCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.aboutUsCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.scheduleCard); + SettingsManagerMock.stubSetInt( + settingsManagerMock, PreferencesFlag.progressBarCard); await viewModel.futureToRun(); @@ -926,7 +825,8 @@ void main() { preferencesServiceMock, PreferencesFlag.ratingTimer, toReturn: day); PreferencesServiceMock.stubGetBool( - preferencesServiceMock, PreferencesFlag.hasRatingBeenRequested, toReturn: false); + preferencesServiceMock, PreferencesFlag.hasRatingBeenRequested, + toReturn: false); expect(await DashboardViewModel.launchInAppReview(), true); diff --git a/test/viewmodels/feedback_viewmodel_test.dart b/test/viewmodels/feedback_viewmodel_test.dart index 0dffbd270..b685b2b9b 100644 --- a/test/viewmodels/feedback_viewmodel_test.dart +++ b/test/viewmodels/feedback_viewmodel_test.dart @@ -46,8 +46,7 @@ void main() { setUp(() async { setupNavigationServiceMock(); githubApiMock = setupGithubApiMock(); - preferencesServiceMock = - setupPreferencesServiceMock(); + preferencesServiceMock = setupPreferencesServiceMock(); appIntl = await setupAppIntl(); setupLogger(); GithubApiMock.stubCreateGithubIssue(githubApiMock, Issue()); diff --git a/test/viewmodels/grades_details_viewmodel_test.dart b/test/viewmodels/grades_details_viewmodel_test.dart index 7353835ad..a099f4c79 100644 --- a/test/viewmodels/grades_details_viewmodel_test.dart +++ b/test/viewmodels/grades_details_viewmodel_test.dart @@ -14,7 +14,7 @@ import '../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); late AppIntl intl; - + late CourseRepositoryMock courseRepositoryMock; late GradesDetailsViewModel viewModel; diff --git a/test/viewmodels/grades_viewmodel_test.dart b/test/viewmodels/grades_viewmodel_test.dart index d5e378372..b3be684fb 100644 --- a/test/viewmodels/grades_viewmodel_test.dart +++ b/test/viewmodels/grades_viewmodel_test.dart @@ -15,9 +15,8 @@ import '../mock/managers/course_repository_mock.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); late AppIntl intl; - + late CourseRepositoryMock courseRepositoryMock; - late GradesViewModel viewModel; @@ -103,15 +102,11 @@ void main() { group('futureToRun -', () { test('first load from cache than call SignetsAPI to get the courses', () async { - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); expect(await viewModel.futureToRun(), coursesBySession); @@ -132,14 +127,10 @@ void main() { }); test('Signets throw an error while trying to get courses', () async { - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); - CourseRepositoryMock.stubGetCoursesException( - courseRepositoryMock); - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); + CourseRepositoryMock.stubGetCoursesException(courseRepositoryMock); + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); setupFlutterToastMock(); @@ -165,11 +156,9 @@ void main() { test( 'Call SignetsAPI to get the courses than reload the coursesBySession', () async { - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); await viewModel.refresh(); @@ -177,22 +166,20 @@ void main() { expect(viewModel.coursesBySession, coursesBySession); expect(viewModel.sessionOrder, sessionOrder); - verifyInOrder([courseRepositoryMock.getCourses(), - courseRepositoryMock.courses, - courseRepositoryMock.courses]); + verifyInOrder([ + courseRepositoryMock.getCourses(), + courseRepositoryMock.courses, + courseRepositoryMock.courses + ]); verifyNoMoreInteractions(courseRepositoryMock); }); test('Signets throw an error', () async { - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock, - toReturn: courses, - fromCacheOnly: true); - CourseRepositoryMock.stubGetCourses( - courseRepositoryMock); - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubGetCourses(courseRepositoryMock, + toReturn: courses, fromCacheOnly: true); + CourseRepositoryMock.stubGetCourses(courseRepositoryMock); + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); setupFlutterToastMock(); @@ -202,11 +189,9 @@ void main() { expect(viewModel.sessionOrder, sessionOrder); reset(courseRepositoryMock); - CourseRepositoryMock.stubCourses( - courseRepositoryMock, + CourseRepositoryMock.stubCourses(courseRepositoryMock, toReturn: courses); - CourseRepositoryMock.stubGetCoursesException( - courseRepositoryMock); + CourseRepositoryMock.stubGetCoursesException(courseRepositoryMock); await viewModel.refresh(); diff --git a/test/viewmodels/login_viewmodel_test.dart b/test/viewmodels/login_viewmodel_test.dart index 0ee6b4302..a96be3d0a 100644 --- a/test/viewmodels/login_viewmodel_test.dart +++ b/test/viewmodels/login_viewmodel_test.dart @@ -110,8 +110,8 @@ void main() { viewModel.validatePassword(passwordCodeValid); await viewModel.authenticate(); - verify( - navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.dashboard)); + verify(navigationServiceMock + .pushNamedAndRemoveUntil(RouterPaths.dashboard)); }); test( diff --git a/test/viewmodels/more_viewmodel_test.dart b/test/viewmodels/more_viewmodel_test.dart index c472256c2..a6a78203a 100644 --- a/test/viewmodels/more_viewmodel_test.dart +++ b/test/viewmodels/more_viewmodel_test.dart @@ -115,8 +115,7 @@ void main() { setUp(() async { cacheManagerMock = setupCacheManagerMock(); settingsManagerMock = setupSettingsManagerMock(); - courseRepositoryMock = - setupCourseRepositoryMock(); + courseRepositoryMock = setupCourseRepositoryMock(); remoteConfigServiceMock = setupRemoteConfigServiceMock(); preferenceServiceMock = setupPreferencesServiceMock(); userRepositoryMock = setupUserRepositoryMock(); diff --git a/test/viewmodels/not_found_viewmodel_test.dart b/test/viewmodels/not_found_viewmodel_test.dart index 8c676beb8..52e228fe7 100644 --- a/test/viewmodels/not_found_viewmodel_test.dart +++ b/test/viewmodels/not_found_viewmodel_test.dart @@ -54,8 +54,8 @@ void main() { test('navigating back worked', () async { viewModel.navigateToDashboard(); - verify( - navigationServiceMock.pushNamedAndRemoveUntil(RouterPaths.dashboard)); + verify(navigationServiceMock + .pushNamedAndRemoveUntil(RouterPaths.dashboard)); }); }); @@ -78,9 +78,7 @@ void main() { final expectedArtboard = Artboard(); RiveAnimationServiceMock.stubLoadRiveFile( - riveAnimationServiceMock, - 'dot_jumping', - expectedArtboard); + riveAnimationServiceMock, 'dot_jumping', expectedArtboard); await viewModel.loadRiveAnimation(); final artboard = viewModel.artboard; @@ -93,7 +91,8 @@ void main() { test('load the dot_jumping Rive animation successfuly', () async { await viewModel.loadRiveAnimation(); - verify(riveAnimationServiceMock.loadRiveFile(riveFileName: riveFileName)); + verify( + riveAnimationServiceMock.loadRiveFile(riveFileName: riveFileName)); }); test('load file Rive animation with error', () async { @@ -115,9 +114,7 @@ void main() { final artboard = Artboard(); RiveAnimationServiceMock.stubLoadRiveFile( - riveAnimationServiceMock, - 'dot_jumping', - artboard); + riveAnimationServiceMock, 'dot_jumping', artboard); RiveAnimationServiceMock.stubAddControllerToAnimationException( riveAnimationServiceMock, artboard); diff --git a/test/viewmodels/profile_viewmodel_test.dart b/test/viewmodels/profile_viewmodel_test.dart index 91356c91e..71a984bb7 100644 --- a/test/viewmodels/profile_viewmodel_test.dart +++ b/test/viewmodels/profile_viewmodel_test.dart @@ -76,8 +76,7 @@ void main() { "first load from cache then call SignetsAPI to get the latest events", () async { UserRepositoryMock.stubGetInfo(userRepositoryMock, toReturn: info); - UserRepositoryMock.stubGetPrograms( - userRepositoryMock); + UserRepositoryMock.stubGetPrograms(userRepositoryMock); expect(await viewModel.futureToRun(), []); @@ -94,15 +93,12 @@ void main() { test("Signets throw an error while trying to get new events", () async { setupFlutterToastMock(); UserRepositoryMock.stubGetInfo(userRepositoryMock, - fromCacheOnly: true, - toReturn: info); - UserRepositoryMock.stubGetInfoException( - userRepositoryMock, + fromCacheOnly: true, toReturn: info); + UserRepositoryMock.stubGetInfoException(userRepositoryMock, fromCacheOnly: false); UserRepositoryMock.stubGetPrograms(userRepositoryMock, fromCacheOnly: true); - UserRepositoryMock.stubGetProgramsException( - userRepositoryMock, + UserRepositoryMock.stubGetProgramsException(userRepositoryMock, fromCacheOnly: false); expect(await viewModel.futureToRun(), [], @@ -121,8 +117,7 @@ void main() { group("info - ", () { test("build the info", () async { - UserRepositoryMock.stubProfileStudent( - userRepositoryMock, + UserRepositoryMock.stubProfileStudent(userRepositoryMock, toReturn: info); expect(viewModel.profileStudent, info); @@ -135,8 +130,7 @@ void main() { group("programs - ", () { test("build the list of programs", () async { - UserRepositoryMock.stubPrograms(userRepositoryMock, - toReturn: programs); + UserRepositoryMock.stubPrograms(userRepositoryMock, toReturn: programs); expect(viewModel.programList, programs); @@ -185,7 +179,8 @@ void main() { // Calculate the expected progression based on the defined ProgramCredits final double expectedProgression = - (45 / programCredits.programsCredits['7694']! * 100).roundToDouble(); + (45 / programCredits.programsCredits['7694']! * 100) + .roundToDouble(); // Verify that the calculated progression matches the expected value expect(progression, expectedProgression); @@ -221,13 +216,10 @@ void main() { group('refresh -', () { test('Call SignetsAPI to get the user info and programs', () async { - UserRepositoryMock.stubProfileStudent( - userRepositoryMock, + UserRepositoryMock.stubProfileStudent(userRepositoryMock, toReturn: info); - UserRepositoryMock.stubGetInfo(userRepositoryMock, - toReturn: info); - UserRepositoryMock.stubGetPrograms( - userRepositoryMock); + UserRepositoryMock.stubGetInfo(userRepositoryMock, toReturn: info); + UserRepositoryMock.stubGetPrograms(userRepositoryMock); await viewModel.refresh(); diff --git a/test/viewmodels/schedule_settings_viewmodel_test.dart b/test/viewmodels/schedule_settings_viewmodel_test.dart index 9a2f5a7f8..0d9b1f70b 100644 --- a/test/viewmodels/schedule_settings_viewmodel_test.dart +++ b/test/viewmodels/schedule_settings_viewmodel_test.dart @@ -130,12 +130,10 @@ void main() { test( "The settings are correctly loaded and sets (if no schedule activities present to use)", () async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: []); expect(await viewModel.futureToRun(), settings); @@ -156,12 +154,10 @@ void main() { test( "If there is one valid class which has grouped laboratory, we parse it and store it (None selected)", () async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: classOneWithLaboratoryABscheduleActivities); final courseAcronymWithLaboratory = @@ -178,8 +174,8 @@ void main() { .containsKey(courseAcronymWithLaboratory), true); expect( - viewModel - .scheduleActivitiesByCourse[courseAcronymWithLaboratory]!.length, + viewModel.scheduleActivitiesByCourse[courseAcronymWithLaboratory]! + .length, 2); expect( viewModel.selectedScheduleActivity @@ -194,12 +190,10 @@ void main() { test( "If there is two valid class which has grouped laboratory, we store both (First => none selected, Second => group A selected)", () async { - SettingsManagerMock.stubGetScheduleSettings( - settingsManagerMock, + SettingsManagerMock.stubGetScheduleSettings(settingsManagerMock, toReturn: settings); - CourseRepositoryMock.stubGetScheduleActivities( - courseRepositoryMock, + CourseRepositoryMock.stubGetScheduleActivities(courseRepositoryMock, toReturn: twoClassesWithLaboratoryABscheduleActivities); final firstCourseAcronymWithLab = @@ -208,14 +202,10 @@ void main() { final secondCourseAcronymWithLab = classTwoWithLaboratoryABscheduleActivities.first.courseAcronym; - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - firstCourseAcronymWithLab); - SettingsManagerMock.stubGetDynamicString( - settingsManagerMock, - PreferencesFlag.scheduleLaboratoryGroup, - secondCourseAcronymWithLab, + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, firstCourseAcronymWithLab); + SettingsManagerMock.stubGetDynamicString(settingsManagerMock, + PreferencesFlag.scheduleLaboratoryGroup, secondCourseAcronymWithLab, toReturn: ActivityCode.labGroupA); expect(await viewModel.futureToRun(), settings); @@ -251,8 +241,7 @@ void main() { group("setter calendarFormat - ", () { test("calendarFormat is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManagerMock, - PreferencesFlag.scheduleCalendarFormat); + settingsManagerMock, PreferencesFlag.scheduleCalendarFormat); // Call the setter. viewModel.calendarFormat = CalendarFormat.twoWeeks; @@ -273,8 +262,7 @@ void main() { group("setter calendarView - ", () { test("calendarView is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManagerMock, - PreferencesFlag.scheduleListView); + settingsManagerMock, PreferencesFlag.scheduleListView); const expected = true; @@ -287,7 +275,8 @@ void main() { expect(viewModel.toggleCalendarView, true); expect(viewModel.isBusy, false); - verify(settingsManagerMock.setBool(PreferencesFlag.scheduleListView, any)) + verify(settingsManagerMock.setBool( + PreferencesFlag.scheduleListView, any)) .called(1); verifyNoMoreInteractions(settingsManagerMock); }); @@ -296,8 +285,7 @@ void main() { group("setter scheduleShowWeekendDays - ", () { test("scheduleShowWeekendDays is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManagerMock, - PreferencesFlag.scheduleShowWeekendDays); + settingsManagerMock, PreferencesFlag.scheduleShowWeekendDays); const expected = true; @@ -321,8 +309,7 @@ void main() { group("setter startingDayOfWeek - ", () { test("startingDayOfWeek is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManagerMock, - PreferencesFlag.scheduleStartWeekday); + settingsManagerMock, PreferencesFlag.scheduleStartWeekday); // Call the setter. viewModel.startingDayOfWeek = StartingDayOfWeek.friday; @@ -343,16 +330,15 @@ void main() { group("setter showTodayBtn - ", () { test("showTodayBtn is updated on the settings", () async { SettingsManagerMock.stubSetString( - settingsManagerMock, - PreferencesFlag.scheduleStartWeekday); + settingsManagerMock, PreferencesFlag.scheduleStartWeekday); const expected = false; // Call the setter. viewModel.showTodayBtn = expected; - await untilCalled( - settingsManagerMock.setBool(PreferencesFlag.scheduleShowTodayBtn, any)); + await untilCalled(settingsManagerMock.setBool( + PreferencesFlag.scheduleShowTodayBtn, any)); expect(viewModel.showTodayBtn, expected); expect(viewModel.isBusy, false); diff --git a/test/viewmodels/settings_viewmodel_test.dart b/test/viewmodels/settings_viewmodel_test.dart index d00afe0a9..a3d01d24e 100644 --- a/test/viewmodels/settings_viewmodel_test.dart +++ b/test/viewmodels/settings_viewmodel_test.dart @@ -35,8 +35,7 @@ void main() { test("The settings are correctly loaded and sets", () async { SettingsManagerMock.stubLocale(settingsManagerMock); - SettingsManagerMock.stubThemeMode( - settingsManagerMock); + SettingsManagerMock.stubThemeMode(settingsManagerMock); await viewModel.futureToRun(); expect(viewModel.currentLocale, 'English'); diff --git a/test/viewmodels/startup_viewmodel_test.dart b/test/viewmodels/startup_viewmodel_test.dart index d700701be..211173905 100644 --- a/test/viewmodels/startup_viewmodel_test.dart +++ b/test/viewmodels/startup_viewmodel_test.dart @@ -38,14 +38,11 @@ void main() { setupAnalyticsServiceMock(); navigationServiceMock = setupNavigationServiceMock(); settingsManagerMock = setupSettingsManagerMock(); - preferencesServiceMock = - setupPreferencesServiceMock(); + preferencesServiceMock = setupPreferencesServiceMock(); userRepositoryMock = setupUserRepositoryMock(); networkingServiceMock = setupNetworkingServiceMock(); - internalInfoServiceMock = - setupInternalInfoServiceMock(); - sirenFlutterServiceMock = - setupSirenFlutterServiceMock(); + internalInfoServiceMock = setupInternalInfoServiceMock(); + sirenFlutterServiceMock = setupSirenFlutterServiceMock(); setupLogger(); viewModel = StartUpViewModel(); diff --git a/test/viewmodels/web_link_card_viewmodel_test.dart b/test/viewmodels/web_link_card_viewmodel_test.dart index e50d0e3df..290c835dd 100644 --- a/test/viewmodels/web_link_card_viewmodel_test.dart +++ b/test/viewmodels/web_link_card_viewmodel_test.dart @@ -60,8 +60,8 @@ void main() { test('navigate to security', () async { await viewModel.onLinkClicked(securityQuickLink, Brightness.light); - verify( - analyticsServiceMock.logEvent("QuickLink", "QuickLink clicked: test")); + verify(analyticsServiceMock.logEvent( + "QuickLink", "QuickLink clicked: test")); verify(navigationServiceMock.pushNamed(RouterPaths.security)); verifyNoMoreInteractions(navigationServiceMock); }); @@ -72,8 +72,8 @@ void main() { await viewModel.onLinkClicked(quickLink, Brightness.light); - verify( - launchUrlServiceMock.launchInBrowser(quickLink.link, Brightness.light)); + verify(launchUrlServiceMock.launchInBrowser( + quickLink.link, Brightness.light)); verifyNoMoreInteractions(navigationServiceMock); }); }); From 21678877fa9f41bbb640de44d0ed1404a492640a Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 23:05:05 -0500 Subject: [PATCH 49/62] Fix analyze --- lib/ui/widgets/schedule_settings.dart | 2 +- test/ui/views/schedule_view_test.dart | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ui/widgets/schedule_settings.dart b/lib/ui/widgets/schedule_settings.dart index 5d14c457b..490b4873f 100644 --- a/lib/ui/widgets/schedule_settings.dart +++ b/lib/ui/widgets/schedule_settings.dart @@ -78,7 +78,7 @@ class _ScheduleSettingsState extends State { child: ListView( key: const ValueKey("SettingsScrollingArea"), children: _buildSettings( - context, model as ScheduleSettingsViewModel), + context, model! as ScheduleSettingsViewModel), ), ), ), diff --git a/test/ui/views/schedule_view_test.dart b/test/ui/views/schedule_view_test.dart index 41d6b3b28..04ceb5051 100644 --- a/test/ui/views/schedule_view_test.dart +++ b/test/ui/views/schedule_view_test.dart @@ -8,7 +8,6 @@ import 'package:flutter/material.dart'; import 'package:ets_api_clients/models.dart'; import 'package:feature_discovery/feature_discovery.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:intl/intl.dart'; import 'package:table_calendar/table_calendar.dart'; // Project imports: From df2e47ade35385ef572b99c1046e8e581df44214 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Fri, 8 Mar 2024 23:54:56 -0500 Subject: [PATCH 50/62] Fix Golden --- lib/ui/views/schedule_view.dart | 1 + test/ui/views/grades_details_view_test.dart | 6 +++--- test/ui/views/schedule_view_test.dart | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/ui/views/schedule_view.dart b/lib/ui/views/schedule_view.dart index 0930b82a8..99cf44916 100644 --- a/lib/ui/views/schedule_view.dart +++ b/lib/ui/views/schedule_view.dart @@ -395,6 +395,7 @@ class _ScheduleViewState extends State valueListenable: model.focusedDate, builder: (context, value, _) { return TableCalendar( + key: const Key("TableCalendar"), startingDayOfWeek: model.settings[PreferencesFlag.scheduleStartWeekday] as StartingDayOfWeek, diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index 178bc8990..28f77076d 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -224,7 +224,7 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); await expectLater(find.byType(GradesDetailsView), @@ -241,7 +241,7 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); await expectLater(find.byType(GradesDetailsView), @@ -258,7 +258,7 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); await expectLater( diff --git a/test/ui/views/schedule_view_test.dart b/test/ui/views/schedule_view_test.dart index 04ceb5051..4e0e59f77 100644 --- a/test/ui/views/schedule_view_test.dart +++ b/test/ui/views/schedule_view_test.dart @@ -98,6 +98,7 @@ void main() { }); group("golden - ", () { + const tableCalendarKey = Key("TableCalendar"); testWidgets("default view (no events), showTodayButton enabled", (WidgetTester tester) async { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); @@ -221,10 +222,10 @@ void main() { child: ScheduleView(initialDay: testingDate))))); await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byType(TableCalendar, skipOffstage: false), findsOneWidget); + expect(find.byKey(tableCalendarKey, skipOffstage: false), findsOneWidget); expect( find.descendant( - of: find.byType(TableCalendar, skipOffstage: false), + of: find.byKey(tableCalendarKey, skipOffstage: false), matching: find.text( "${testingDate.add(const Duration(days: 1)).day}", skipOffstage: false)), @@ -232,7 +233,7 @@ void main() { // Tap on the day after selected day await tester.tap(find.descendant( - of: find.byType(TableCalendar, skipOffstage: false), + of: find.byKey(tableCalendarKey, skipOffstage: false), matching: find.text( "${testingDate.add(const Duration(days: 1)).day}", skipOffstage: false))); From 1587f09bdbca734115f32dd04960edd461336947 Mon Sep 17 00:00:00 2001 From: XavierPaquet-Rapold Date: Sat, 9 Mar 2024 04:56:56 +0000 Subject: [PATCH 51/62] [BOT] Applying format. --- test/ui/views/grades_details_view_test.dart | 9 ++++++--- test/ui/views/schedule_view_test.dart | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index 28f77076d..81916e2e8 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -224,7 +224,8 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); + child: FeatureDiscovery( + child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); await expectLater(find.byType(GradesDetailsView), @@ -241,7 +242,8 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); + child: FeatureDiscovery( + child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); await expectLater(find.byType(GradesDetailsView), @@ -258,7 +260,8 @@ void main() { tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); + child: FeatureDiscovery( + child: GradesDetailsView(course: courseWithoutSummary)))); await tester.pumpAndSettle(); await expectLater( diff --git a/test/ui/views/schedule_view_test.dart b/test/ui/views/schedule_view_test.dart index 4e0e59f77..b19aec4ef 100644 --- a/test/ui/views/schedule_view_test.dart +++ b/test/ui/views/schedule_view_test.dart @@ -222,7 +222,8 @@ void main() { child: ScheduleView(initialDay: testingDate))))); await tester.pumpAndSettle(const Duration(seconds: 1)); - expect(find.byKey(tableCalendarKey, skipOffstage: false), findsOneWidget); + expect( + find.byKey(tableCalendarKey, skipOffstage: false), findsOneWidget); expect( find.descendant( of: find.byKey(tableCalendarKey, skipOffstage: false), From d1551893c7ed6ebdf9428adbd2991895ded24633 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sat, 9 Mar 2024 00:09:00 -0500 Subject: [PATCH 52/62] Update pumpAndSettle duration --- test/ui/views/grades_details_view_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index 28f77076d..435209b76 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -242,7 +242,7 @@ void main() { await tester.pumpWidget(localizedWidget( child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); - await tester.pumpAndSettle(); + await tester.pumpAndSettle(const Duration(seconds: 1)); await expectLater(find.byType(GradesDetailsView), matchesGoldenFile(goldenFilePath("gradesDetailsView_2"))); @@ -259,7 +259,7 @@ void main() { await tester.pumpWidget(localizedWidget( child: FeatureDiscovery(child: GradesDetailsView(course: courseWithoutSummary)))); - await tester.pumpAndSettle(); + await tester.pumpAndSettle(const Duration(seconds: 1)); await expectLater( find.byType(GradesDetailsView), From 07727a686d49cddd69f2e935af8224fb77ba6ccd Mon Sep 17 00:00:00 2001 From: XavierPaquet-Rapold Date: Sat, 9 Mar 2024 05:13:37 +0000 Subject: [PATCH 53/62] [BOT] Update golden files --- .../views/goldenFiles/gradesDetailsView_2.png | Bin 13405 -> 2534 bytes ...esDetailsView_evaluation_not_completed.png | Bin 13405 -> 2865 bytes test/ui/views/goldenFiles/notFoundView_1.png | Bin 2671 -> 2552 bytes .../goldenFiles/scheduleSettingsView_1.png | Bin 2237 -> 2294 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/ui/views/goldenFiles/gradesDetailsView_2.png b/test/ui/views/goldenFiles/gradesDetailsView_2.png index c7db3e6bb74390e51bedcce8df4d953c0a45ffd1..5c3a06e175e41976aa86a1eab10d921b49da747e 100644 GIT binary patch literal 2534 zcmd5;drZ?;6fTb`2!capOz00mx0+aFh=Z0_r?3G-i?c>SK!FO#Km;qa0tLmn;RK4y zpcJ8lhPZwHhmCY4 z-RNXC1Y(@;@3Z$Xp+q(qm`zWHwkYJ48)d~T+*$7k&A~^XSlgT0m)hMl11z&PW+{qlYL20C!&8gYY}qEGyOmpF?Q%!5F0(7@UAhrr7N%c|JLRrkN~y|C zpd@;62Pv9#nyu1_GpEP@|hLf7t6wL(LqkL3xryKbQ z7fDWLHaz2jGb4`OQ4G@AKb>JEl7pq#2y(ADE%bXxdnn#=DJpKfqd6l<^Oat7T^#BL zxjBiynW()tOUK7rgaf)&SAyPvcIKepDDN{w&;VX zxTp@u6sd4F^-t!UEO`XE<42{E{1R*qNtzZ{g}ehI;%yz*a@wPeRz*|Sx!wxF8cKJi zIYKQLz?swYf*yUpwpGJyn*OVt6-@I5#ZYx`rs!V|uMl~fcXZ+el@sH(_}8`==^o<= zFR-W;CU3x%OKxXr+n)Q)Hl^Ir5l9Cj4%IYg2=31i`d(&Y1;a0p+4QnT!M=}||tr~XktxSEowoseQkEp{Wj z4d0+`OBYvHd^w;mQnF;P=I>R!zVq>uNn?5`w=S7`A%L_Au%3bEL-9E{X;1g*CKxUK z>;OTMiwikZ#T~lE8fsk1)U0zi+4|vIAy_mpFhEJo?x^{cfzKEA#|Xv-STzs}@NMuD zQDuq_-%V{b-V>>}{oUd!#yl~LLz0 z6om#nU3zFJlxoM?te~!^TG!oSDH8`^BmjyvZ7nhYi|)>Y?AhWt7}YR^{6c>FC(Cf{ zA8qr}wgvL8ZR`zGB)Q8Qoh_Nob1i^Iz^7S}ZINlW`A(TBtGl(s%=@0h-R@j>mC@9V zl`=^5AB~M3JS$0kow%4_AqtChD$`&U9UL-@`rXn<0bUHn<}3%T*gj7S>N=I2oNR;2 zNMD$)y(;NuFe>;@41i48Fkxh{6B`v3HTI2}p)S4(44p@Dj^T;xSiIBRSrtMvC+5+X zl>Ire9!sP;p0~9lDeXjh#Ih-mxu<0q(z&h6iFtL?Y2+s>J}SE1~Sfh_NIyMnORVs0*N{1nFE@SXd57f7xKNwNFi5>1kNa f2jhKMvtXTRn&^#zeJ;}d)gb;~qJ5bA!n6Jc)FJ)% literal 13405 zcmb`u1yEdFweF54?7jAqXRo!MO}Mh6G#WA?G6)1hla-NB1%aSYfcGpSJn)P0by+^} z0p+49Ee5I>CEf?Vz`BUZsv`n_K8R*vAP_l7Rzg(WGvj#0+b3xzko#{=q5Pzoh%`ndbE=s&Wq%C3pQ;3L$+AGqY;*|F)g~B|=k{B=M$!(mTWa zcG6xe|Ce*Q>-$)ahJSm_*=XTGcNI&2_|_h-T1#iOhzywf}`)IE1oeFM$=x z1~8#eyzQwXr+A0@pI%Ueqq(;l z>=EZyX}7vFxu32^bK1@tk7n@p;L+r5O^=TU{7&aK-JdMY|1YNq z#yct;YhEV3LV(`ebI%oi6EJ*Cz+vodYcu2d`MypMsN>G0*C7Pa?e*>-RAYWQ?wKg`?~y!N<^yWC4kI0f`)& zv|{oyw_H1{EVAQ6neE%+XcH%R%SM!eC8gZ@d>B7}o7n3$=2aRaWXCoW z_#EGR#g5|~7ifBB7xI49Q&iUz!y0P$jpwMay$@Av_w}9c@DOe|U8%IO-Bi9)ovFZy zEZ-*o%u*&cckds#Hp5AAD$B9cllMID^m(P7`&}ck9b9dd=?3@4h@jH7t#pE$8O_-q zljHM7AEuWu;ZpyIUD)t(cMQz++28A8XTkJ7==Opj$|-oz_@Qf+4pY~NHS5b75mY`V zXkAD>GKU8H49KcYFiw{!=lHVg;B!nV>FaV7SbE$4uyiTB_^a=H*1ub_g>UB? z6+owH50XxZ_$+DV%!vl}{bCNSD_Aaes%4cPoL^z;)VceFSN3zWM>5DT_Uh@!b(Z*@ zP`<$fL!W%L&&i6|obpr(V&u->#2@7jVTXhXilIjziTW*<*t$0YsP=gZ^@ol1%D{v!_PG zM|tqTi*0^f?GW;O@Nx7KID3GBVdu5u%N{NgR7tfQgfCIVOd1G{^VVDT%A|$q&%3Oa1T;^%V(vfsI{K$NbWcKDGw!&fv zWR0wg#_eG&ErN-je=1~B_HIzfHxhHl*?ZjQ0y|@+B5dw=@e-uRNYG{0c4vn@Ef3*v zln)oyu_gyG5CyNR#uMrDHcqZ)_kMCU7l-TnTE1=nex~Q zx*-t2lE6%%0@c4hbL6PgdNtT5+>>q`3H{fRrYvA2g#OAlD<2w|>; zYj@cd)osGpxx@_)kzz2E9{A2}{JdWO4iYl6fO?ZSywPdOMB@@qKgrA(f`ttjV4oUd z36b~{uE~*MMKbAD#uUWg6(V*4j;nTKuX1Bwwm`YBc!2L;1M?HhS3vw%Re9EY;Zptm z@l^dQwS6;wpH;RJo$&khgwD{~6K0Rm4A2|1;*$@vMN&oQ!b1wCay>U;leQG__o@U| z{g6XrNXTY?4E2zetcf4HM2WBWo8x;N&q0CwwD4Mhfftrm-*$wo8B3AD1m*nza8n#Z zF!*N8Us$tRWU-Dhgb>>zAIhaD84|(|RmaO;U3qS$FJ5}m2Cc31lN%e%EIuH+E}Y#p z)W|Jzzl&4Fq8)ZbbQ1FLNROX=*P+ZHe&H2pNhYI>LOH2y%6IoPv)P?7I{8U;RynB0 zqT0CoNC$`!$7aFTsB|ah!M-7m`cAF&)6I`@XXpJMSqqun+Ou?%jjb5jy+-F3{#KDa z9{?iG7Z7;YT?>;i%;C>=P-CGYpV4tMAB5AVKE~!Vw)-x{nA1)=(i2Q zUkN7JBJqU+pQy10j5_>jV}?q6L@Wn2%9b@hm>uDE!2(?A{@LGF4}XOz9%zI^O^50o z@swa-`GiRLx$|rf^cB%)Oz0LYH=MnzDpih*Hk+q@!Sj7+JXz&0$cc01OH%wLJ+q7q z=r6}cIb&E~Jqqc@2O(L@4`FUH*DXmGV>Z{N?-+(8yF$K`+I`i*KX4T*h|HZLf@-^` z=M=+uAP}5evt39%I9i8RM;r2C5%UC*DLskhaXf{P${Y8hD2I7F;9Q3}yr>^EppE&n+cTcEELPl{gB0Gqs zV~I%5wC+8c90CRSMoU8+1Z&vsV4jGEdNd88mTD_|(v4`piJcQdi01NoHd`P2ac>*OKQ~{Sl6d z42e=gH|Ekm8LjO?4(DP^RW#&G>9BC^Miu*p)BxmID5QqLs*vCp9hR4e*QFR@bT}Sc zf9^jPGiOq&3@UAaPhdjv^>|jVZZloeY_e(S)06yXfY7wB4#E*Mium|<|9GDpO9rpq zy7iPg>$9Fmm&=@7ZcR6WX4ld*qOA@u-wxtu&8wnsn`I=0wMi+Kn0D2v4hA0AUD=%D zT~@3j`B3*hPl&%n`wkDNkrM2;?D-E4`=p$bwhTQe7xkI7{jc>$oD=3?=9DyhAG14y zk8M4=J9jJDc8%tB(R(y%qxDdgCFn45DKgU%3WB6yZegHu0rzRaL_@BRewiiVak?e{ zyi{VETnohP?kt9hQPrDK7X1ny>gCSkl`vaKjCrqb3D-)Nro#Qwo5J5=fy$*6kKK3# z6f-vUCEc zi1~vJgN1W^9&)D+a%77Ncz$;n=WY_C0_a)i;E4tr_vj;G8%_gf5K9$`Ch##PWzo-w zz#Q*uLWFacOJqX*BCKjolnq~|&NlrazeYPHs!w}5j}0^qB=;$sd&M?zC5liqgx{#! zYsm1?mD>xCnlsaDem0OX#87rjJ(+Adu}H9!}+Msi`!LFSB)Tp7=Y)9`9IsIJh?l^TZ4vDqFaAoWuu)0xhNV zu}oPQ%LMiFEoNx@sO_|A>lu3vt?5_3SaGDWO_U(AQnj8@fF^-E|Gtk!Bk zZp8h9>|JG(6X?#k5|m+KRHf{sUSN4@4-)aWI2yQoI{t-mJ~1DcRGXAEJCDlZjfdKg z9(g7ZRXxb=VK_pg3R5xOFa2DmpR;W|?R-&;6><92UP(*UO!m(D;P|rGwXk}w1aa!) zV5HZwzatq)#QkHKj^doNc0HepjXWUrCoVz|sAke`aQ-*)jMYO(!#k|P$^ulBLZQgB zw@-2=Y`6~$Jq2`Arg%I)h@c#XkIU~zlME9+FiPCq=IpsPjHC?IlX~oRYA(sBhfa#9 zhCmWN4)3EYLbfkC(vlwkCPds#S5H(xQ->!#a)h58vxS_B85_NM5M>+ARYoY9+-yrw z@=3IibCBhA#grF1Lltv&Zb8%bHuEyF95RI zz5nunP+7}1eZ%o&MdE6t&$@RVwiYXQ%3E;C{;U3)dl|Yn^9I>KTtRlB261dW>U~>o z++;1;hb^`Rhl%EEahcWmu{pDm3?QUi75f-zws%T3S>)`1Rmib(WUesZJ_U~7ryd-_k5j;3&j$nO#rWWXyBS^A0OZKV-F+i><04V)jj zH@2Vik^JsdK>;2Q2yDZ5*Y8s0nhiUxz${@q%Q92@@{Jz-;Xx-U<61LizO9!e{tyefo;9>+BxAl@< zdII;yA0s_M`Rm>o082Hk*g*q9B@*y{^TP?aVBVK&Et{H8TsDa(;b$}(e3jY?BwOSo zJ#%_fs!?Asb$z53VSfL7UZK2TcS^@>L;1T?|0`JKUgn^Rc95j#7S`rvzn)1VOC1ds z#+p~Q)a5WVq8vG!5}|o+1rfyheBPX5?p==Fhf`;DBzsT=O47p<<>0ymF8|t-uM-J8eA4~7i&oVvn?&8a`nYy5?pjy zg${n|5amt5eZnisx@8;rtq`$&HGBdBxpqE8d@_;*a@~x2SxjnQZIH-5)pls={ZsA) zx@?h}zC8vaTH*H#N1G*-F$&W|i#}&yIv|Nh>?}n|&3=}xZZjD|vr&(oRGw7)#is^% z0g%g7xVY1MoAf%2-FxpB_#`R(3Vkh`yl+q--4OO7q~H58?}1z<=vu3qpDu7**}5Nt z6bjU|>O+VQ(S!ii`aDnLmpqy9WH?X~QXMm)QeDsX-!6-KWA}Zt+(Y}dR8WSQSKmO=euRyI#h6-d)j?}Q7dLH=usYA-Ui)HlV!PXP0TLS|`fmY=AkR^=HRoJE9H~%w_o2mhc z4IhWQy7RRfz%W68T+}48>LM8!*+Te*s*EYOU7*mA#d*yarGnosqJa23wdpVqcJ;} zk{t#}d|4fKIDjt3Zkfxg^aZQkFPnrJG=T_OdA_5N!Q1X$R?FQV&w^oRT%36i%`YNA z`v1nDV?Ny|EF;tp8szxALuWSUTi_YP-wKLhaEQ+T-utcWbz7sGsXI(s;Ne|orndKA$*n)jG#z;iyY3+vD-YGuVS zl5T`}m>(-%W0?!Y#o+4S!GUsM!ruc4K&WS z%iuWDX@-9)W2*5h1P(Mp%lu{dn1n;;P#^G7estoVs{}FZU4^bFugh`pF0z@x<>k9h z%l=&7F5p#}E#0{ArNg@R4I`bTu_hej_wkrN{nk?m_k8;GoQO?ghmgO%_p*Bwb~MI| z=SWnQ2RkJnKeCx)c2{`V)&Eyg_h`A|_uYLUQI(An;o2;5q}p33#~5uD^XWR1z-p zAYe59AbvS@Jt)|o{QYo-CYX;sP+1xORIgH1!HQ9KNGOsW0weCadkwUi=3Bg30Npw> zKhbjl#hUA=Udp;|$$%Oc$^DC`lkvn#2hF$Mclg+T?MVF(vo0w~A=KNw(1>oH=+vwL z8a14(5*^$U3zNbL`w_R7zTgNA?4c$`oFyqpzfi_f-t6Nc@O?PnV-mZh4Nz9TTDen$ zheOlT4TfXA>H_+28;LDXKZM-{rhhegViH%rV7AY#Mgsb>C0>ijkyt?TU88dD4;6tynr$I2wluIUU>}IPT3m0o@r%pjZa1B{JHm)#X1R zXti=ik9yh$7un+zC4rPOve*8X2>+#gTo?Pbm-2Fj{Nd%9#tbC{wkwDHxe}!!$Q~VP?TP#wF)E_sKVI@oqe=Y$x{Y?50t0wb7Z0}53;Yd zHvrDOcr4J&hOo^8a5rlWxt0$DMeNDp*VY>oMg5K3RMv_jv9S`v zH``wNC8m>-7Qtj*3*}}1Yk%|rAwr00`yC{XNfRVe)%F&YQ@v=M!UfYW3&Gb?_nGzf z@NL8VU!A@sRxxNE!HtMZS{ZX|B3uz#R*P?nQh@Y;qR_nv1c6l%>gi6*Pa?}sz61Jw zNazT}sRXP<(X7C}#26-cWTW93yNac7_V@&|hkhzG8=o1Whupt8m%iR%!E0%uDpug8 z9gMRTBmTYb%gQyHcncG6;u@I<&>FHE9S<4dDun}Q+OKzZ?WXglN5iK?OMwC&l$oHj z#;=@To|VM$E?aVionRM*Fo3p7%I4jUqKhS-h{u4gS#(b=sSnuoGd`9HRIt!83cbbV zc=aEv&(_i2)rQ~rvH3>r=X5G#9ae)jVaU3d-SGpQhbasJSFebyBu|C3QH^J28 zq9cQA=7ou^EVcHzBprD=GuNmjkk^u>E^8EoMc`+%hK*_lOwC|#z~e#)7-E`?ze3k4 zX~tf4n@>(3s|fUsNgQ`>qyUrSeJ=$gprOw=;=Qw8`h{tdvl^;M$KNXd^t5o$_q%Eb zL&STx|K@B+y!L`*YoX$e9KP7j_OTj)r+&B^zJ;(cjV;Dm1uRE2#4HrPM4$0-JUyd1Kn|F8uuD_K9vW5l=RLub18 z0UI!pBaF30>d|HjBq~KUXDx9pEI0w4!2V4C%H&I~ITI6k3-$6=2)p zH7o!2&D@2T#1OgNY%O`-&rkm@|M(xtN)^<|GDhZMv7}M=ljZPVzvTLyBTNA9C;Z^x z=P9|OM1Fp5u4rbJcD)Twmd}N(2EC-jP+@5)%4z3|P({lDeP0c5yM_j2q1N(Gnr(%s zn;U0KON)9j6=rl+f4@}Q?Pg>X@ILQBVd=7OWXQ@tzw@aX>?^;aepjdUI2g=k#HA z*+0+Lm=A|sv>xCQ@&VM@Kin7&gXSwYmiMQ|R8d?UhRb0!iYChw+M(m_eMDqre)93r z(a*V#znuEs$MxE6o@_fKsq9}k6`0bw9r{`P@8kz-qIR>qnJpH+8G?~2+b)nb%d`Xg zBJnOgI3vzZ4_e#~&mJ$wB0t`s(>5@^F2~6Cdgenozw=g@zK#yTEE_)uKt zpUl|3Q3H5s}vt z8!9z5HJg8hNrcJ7!a}heWX~l!I+~V_j^Nm)Ad^Y2;f$=oB!%5Fh7X|mU|%WGH~$4k zEpwjXv)%=z?{~M|EA$e0-4|Uq6n*!om_G_OH`(a|3Qd|1YTQifhL2ikXCS>=y{=#9_88L7v-NTR)$o zgeSDSlm89+|38M`zfKQ?+X_Z{_O+72gUXCL4GR~QTOw~f%IoUX3)4`?tSZ}k{*O80 zRF2mR1~n@Uqi0IB2Hc`O`Te9H9?duwNuu(jUzuWx=^D@5jnMN+d6wdf5G{Qth|TZ| z&0+nj?~Q>*1x#>*eADB_utu|H&2w8alOC>zJiUsPcN0h2gw=M{f5A!ri+laQy)gTU zchnBVgSx>8r%q)dE~mR4zgo*n+ceiK-o7B#{{svC$I~Oh$uoNGU`{|inR_j7RNk8Y zfAjWXpR~=)&7&m*`;!3t_c#Fv^ukZPeN{io%C=qt zOy-+iXmFWyvCp-goY(;1xbi>1 zY>P&zX5Zs}a#E7gUtV8b)Yu zU^o`d#s7pT5|8CTJVQ??AhhL*2G3rBd#*p4Xj?K8cSuJ^=L5)3^0ws1kGRwJ8^h-E za)mw1gUh=u@6&cI!#b;pA9I2_oi#NzTd%hhaeaRCoNB+;VbF2$i(xx2FHfb?zs65P zU43xvafdq;fZn-VA0Yw>iE20=SGoW0d7%FvZ!DOo2p|Oe3b{6c#}5w?Kv$k^X9&>a zdpDx9GonS8BFWbxtVE!kDKoK36uT@lPDKg(9d-QcS(Q>@6?&NkIB$LfL95dvDQ`zs-WtDm?M9OuD(sasvJ*nG^Uwn6XT;o#ai}cT3zA@~{&!OePL5H`XWq0P{s0 z@_~D0we5g@yG`yyeX%OHEVJ}}u>8V1Ia7rTh~zLG%>j^Y?h^xyScM?UpQBWOzybyI zCSz8AHtHlI5mW$y96GToI$+{BX>um6P&%_24^>j!*d1Ogo{B0S&nupohI*8*zgg4c zZO0^lF$i$k1I9u>whNJgeV@j;Ndi0Weeq+s$W!>CE^fzndQ}(Ht?W`+v9Y^2iV;DM zSJRe`Ua>hwLeSB(lzV3p?_)%O}qGXzo8P%ceA;DbOk z{H^0o;NYzhbY-;xx)HAfnmBMfTjeejt=J3RPOs1TH7MIJ$J|93AFp<)Ejp& zxjPsLlq6-1PwXEPBOD8kDP3>u)aPEtExl=SyPcqPoM4riY*j6$Dw%;P@Pisf!By{$E(#CJ6A|G9*Z zpHv~m!U#B|PtA?UNKQ&hVl*A(4kY$OK=BSU*=>s)XpWfayIrL-p6P?BkGNUHyBJN3 zhA+qW`0|r2jg<+BGOGXwzC9B09np&&!lE&D_9Nxf7o0a(%i%F)Pw>>kGgJgw3bLa6s4$rRN)Y|m`bPR`HyR z0QFT?eeYzOYyRsC|K5w8(ui`jxkvgffvfzK!0vFpBnv6#SIvH2F~GaNjY<&vI5N}^ zoKs;7>M>(Ac7BEhzAH*_Zk(Qo%~cu(Z?~@vprXwsR8s63`31BOtOgj>(tJua9*-dK z@~G}joD?RzFT5m zmEi@hC(O}C!+{amIq2@5F!MTH?wGpp%3{%^5h*H0z(y+k95g#-rhvh86?skns=UhA zma2x3^(4b_SmvCP<%hKTI4BAN5sW<&p9t2cBzwSY1qgmh6>5g}eX`d$+;ML;VZ{%5 zasv)!#q3{dRp=KVyu?<2lIY3HE#%xh-0%xM1LI75q#GHCO4uV?l!*UO8+ZL!>S$0$ zYeVoGqZ6k28hdoOovzMxt$Bd+>9c{duFNfA21!L$tvyqNU2#AAA#hRx6)adss4yaF zN0kXHd*k)pz+=U2zRJXEs%h+M-ZXaOptO>7l9#vCKS~Yb1=JARh+1J(iLlDKCOzxY z8KRZXf8Q+ zT=Tt;H6pHdg91g<%;<%MT5(WaCC)qlBB-Asm*pD-L3bPf{6iQG52o|NCHwZF*4W^N z1N!@*3-48BCv^TQaw!MP=6TNFH~NOv1E=8$Dq_8PQ#j40N~LJ^^p9-1I8we_{<+eL zNvV+a{6h*-cK3{);urncnl|dVpyV)f-Bz2oI)Zt@a#q?BL{Jm*Z@<(K*K5RoWQuUn zvHU81e8vHEE^b>}Ovroi~cmIkeHWV0QwD{e?UpPGS{cS|cS}2~V&#hehEvsuPa@Hm4 zc^cy%rg>9%$13)2=4Pbl6K3rzNzB;R z2SO|zCOIixCJqA4bC%0-vM^#Kq-M1J>pO~=F956o-2vDy@nq7nf0ts}Wm9z=HT46c z(z-9{Te#apfkt#c=B{*53>*h)WVICcOQd+qSHu(HoL@{)i*GOXqyG9xdwM-vF-58) zqky_3Q7AhY=Z*q?XAn6dH%U!l6aiIVG0nT|(bbMY7l!@?_KoAipr~#p6f}-;D~|9V ziapxQkDq?d{pNo`2aVgJP>|l-^)(QZ%e|+(S86Vpk|bfCu~B0HT4Bl!e`byJn(MO`j3xLTH^5EK1BuLL@o5v+O}JVFQodw_H9Ay5(nm zo~l|uBUw6lzK<2<%F7JrvG-WXcuo*jvUq*3ETN#hfFB7ALNMlxj`aB$BY*&*O^wzb zrf9oxCx7EBmK=t{()LF9ej--ARIBYu?Yp#K|1|?`CRKqsruBZSqit_aY=%;ez`+AM zhWtynuS)EBysI1y5>ll0g9pCq`aqYM#~Z0tGRaEw$RO3RFn7l+Ub(#E z)6m&D1S<|i{HQo;B$+-%MUSH=1&VO4moK!b)KrWk@Gum1WJedC0J4*NEys;|w&@*Q z_pn66C^~Sb$kj!MQg&3-n&%a<-2X+8D1QIW#N>m7(Y9RCjMyBv=VbEi3Jm_+MlzW^ znIeiCd2P$Dy=%mG1aDfm+axr@6F#oz+c~l*JheMWyS8{#jv)jYVkiWUepJY~gqI5P zR$_|6{40&-poo3ygPdpfA&(^EICF(n=Ixi3ZZyJZVhLqO=}WVThXoo;qtkRQ6wtc# zmh}oe-34K$#1P}V#&;Xi6JwmLI>Vpg!TLccSAU^ZG{+RBRIeW}jplr)jp7BY;PaoInr_UfoCO@f^^FEJxz_S1X5y^ zP^7;1PFFUN1u_ymn6PFAEG?l#uYz>=Jv$&$=oI+HeeuD|W5Oio*I5xLVlUUn(Voi| z7TU@-a=>)@-ncP!bv+5yWXVxumb_q?+;F*?3B+iRGYVG1ScEDIkZhYxvbU1m&vH~K z5FV2RkeTTkNdN4G@b1!7SxAH@Rwb{fV{x>hqSV`4oaK4&m?hfirWRSf7Cm39WcqledJp%{q5+Pw|!v@Y_P;IB-3ePGaJ%s#`a9W!(j#*J zKKpv-@r$J3T0=P@2}W6Pr?**lz2j*y1fYTP;U&AwLe4h^)@L3Z>kj8IhX+MbeqAI} z)uc&K0{eB(r;%XAESzTO7W5AYg!v1!Av=`o#=~cGB8d zXwa9~iXaOy^n)d%$oXOtG<~h3Sf2~C}TWi^W78%ijh1s*1X{Z^QDN1Z3Aenm+xT% z22bgZ1!yU4_X9k4{V(K~%|;UK$zPxKnUAJu*5xTSgBwr1Zi*2Yo)6;2TqCp!?b8N#%aTLm zO)Q{hA(HL^=B_%&GNz@K05Cbu8w~Qma7DY0Q>^cucS4?+yW-R9GLt%+aH|@lmp-1* z!ki|J(&d_}qCFWH4^R00<4A_fWwQPUFZk_vgOtGP)Qi>;?`*{WizDYf%OeGN&WG$f zE#=$Y4?IdeXN{fcV8JYEXK#9Dk)5Dea^qy>sVlK*Jq!@*I`m&PWnIF0Y5t<^6=+`L zSg=42Z@|hxmZVVweCpT}VMV$_Bp)87icbu&=gG^v8nOr87S7Bc{O7JCIpgrdtnK92 gbGlR!TmDdBrS`-629iABUxYxil8O=)V#Z(o2PCdhLjV8( diff --git a/test/ui/views/goldenFiles/gradesDetailsView_evaluation_not_completed.png b/test/ui/views/goldenFiles/gradesDetailsView_evaluation_not_completed.png index c7db3e6bb74390e51bedcce8df4d953c0a45ffd1..450e536e1d49b35f8ac13e017cb0e6aecfbe9986 100644 GIT binary patch literal 2865 zcmb_e3s6&M77l0uL8R1amhh~UC9^9FE26v%5llr|BuM3zAkYv&iHQYGfCPwWi-2fk z9qsU53I%x^TmmEwFM*U-c)#)jblC_bAOgV<2z#wFj1OGs%-)$hcmDgI|D5xG=bZ1H zWKR!QZB2bm5D290b_(GI0;y;L@34j%@F#e=EFbu&T=8;s0ab7fr-8-pD=uzlHGn5p z1DgZ_Y4Y6=&S#^uq(Wp;R+JHEVZPv?dG!&>*Ji)8JMXueG4*QVNld+T?02hrJ&cy* zwcN|&bT@HLm;T}MWABNtbv{R@O#EVC20L|Z&nFQBK9>Sg21bwH@2$Npw3`cM>pko@ z%WXgWxQ8p5C3ZV4#;zbma@f6f7*hOX%+*$N;%MPMcojWgdf?i^7vSRvi)%@KAYD4h z6r+M@QB6wv zZ^Vg5&BYH(Pz|*Kr9HWjX?sRSUfa|9+-&`h*????$TLu!b3z?AV-RH0ffKghv62w) z;E8v*NkP=v2#6{oky-W11c$p3w>J3vq)LXt*m!U0ILx}2gUp57{_J+`yYB&^kGisE?$y$g>o=6Et#I0!p`-Dr?@%#wVWg8wKg~T; zZ4XDIyAd1=3l_NVWczuItsvR7w~1BSNtOr9pdh`_)=suul2KJUd~Q*6`VJ5h^(-%`sEA@hnE^PFCpczm$7r(tXd4#*O19?iBx^^F=< z*U}H1R?UZkwPR%q9DO4zaO(b_4*Z@Wop-_2aqtwzk@Ynp4Rgicf7^_C+uMT0NlCr| zUPt8;{@a@-V~^eh=4}Ze3r`h|&nsYB6CT6me+;#);YbgsT$4)L9RGw{c7+otsr2uA zY8t#9sn+8%J$}Y}sqhYvZ_>X-bobC=`n*XgR|Lb;`bK$AD`(q+$aq>4s0GvI9v8+S z#mYVTAvO%h3*^c2KF?oB&_}sXdluj{Asd)No2_+fh-2K&G+x zlto)t165wia1G9k+`i1FmlW%_88<4Z)pw`S=lpX53Z8!qpo9Y_^LKS?j(?kZU3@^x_Co}0@BEItwiloq@gr3H@8wQ zmnYEBetvpQHZ`QxrD?jn&bYM#wG9SXG#r~$K6&3auy|@}3Q*wh4{5Ryr1~9g+7{k*nwOkxyC%MXrfl)ZunCe`A%ogH(EUwY&0ob6|zl>04%sy z!x{^Cqra_)i4NJi9;#0wM(7tpe8=tV;@6^K3dv*Q)0SjZK)|ohIPkR>PnMtFvKj{B zmA|N6(!N5Qw2xa|8kIy=SLx-!D6&C%2!|jSi@DkSmW%&{(Dm}-6tbb@{ZQa%XJ=pyQx#gmmh*hUk+3}1Xr$==S;KF0|NugZ3dSI6LzWdjB$eGufAmmRvMF^ z=kaPuSL_K;HLR7_v5KoB4mv03p8 zO;ad;G>&5EG&!YXIYJrn#gRx1=^69uz~v?y6C7e*V%J0P<@+|2QAAnC_-sFQ<4C^I z<@LpUa^VW$HH6IdHyRo?@mNpw85>jZtIo{@cK&= Y_35}QG9vwRVC)6CedU3ua0$NtUk50Vc>n+a literal 13405 zcmb`u1yEdFweF54?7jAqXRo!MO}Mh6G#WA?G6)1hla-NB1%aSYfcGpSJn)P0by+^} z0p+49Ee5I>CEf?Vz`BUZsv`n_K8R*vAP_l7Rzg(WGvj#0+b3xzko#{=q5Pzoh%`ndbE=s&Wq%C3pQ;3L$+AGqY;*|F)g~B|=k{B=M$!(mTWa zcG6xe|Ce*Q>-$)ahJSm_*=XTGcNI&2_|_h-T1#iOhzywf}`)IE1oeFM$=x z1~8#eyzQwXr+A0@pI%Ueqq(;l z>=EZyX}7vFxu32^bK1@tk7n@p;L+r5O^=TU{7&aK-JdMY|1YNq z#yct;YhEV3LV(`ebI%oi6EJ*Cz+vodYcu2d`MypMsN>G0*C7Pa?e*>-RAYWQ?wKg`?~y!N<^yWC4kI0f`)& zv|{oyw_H1{EVAQ6neE%+XcH%R%SM!eC8gZ@d>B7}o7n3$=2aRaWXCoW z_#EGR#g5|~7ifBB7xI49Q&iUz!y0P$jpwMay$@Av_w}9c@DOe|U8%IO-Bi9)ovFZy zEZ-*o%u*&cckds#Hp5AAD$B9cllMID^m(P7`&}ck9b9dd=?3@4h@jH7t#pE$8O_-q zljHM7AEuWu;ZpyIUD)t(cMQz++28A8XTkJ7==Opj$|-oz_@Qf+4pY~NHS5b75mY`V zXkAD>GKU8H49KcYFiw{!=lHVg;B!nV>FaV7SbE$4uyiTB_^a=H*1ub_g>UB? z6+owH50XxZ_$+DV%!vl}{bCNSD_Aaes%4cPoL^z;)VceFSN3zWM>5DT_Uh@!b(Z*@ zP`<$fL!W%L&&i6|obpr(V&u->#2@7jVTXhXilIjziTW*<*t$0YsP=gZ^@ol1%D{v!_PG zM|tqTi*0^f?GW;O@Nx7KID3GBVdu5u%N{NgR7tfQgfCIVOd1G{^VVDT%A|$q&%3Oa1T;^%V(vfsI{K$NbWcKDGw!&fv zWR0wg#_eG&ErN-je=1~B_HIzfHxhHl*?ZjQ0y|@+B5dw=@e-uRNYG{0c4vn@Ef3*v zln)oyu_gyG5CyNR#uMrDHcqZ)_kMCU7l-TnTE1=nex~Q zx*-t2lE6%%0@c4hbL6PgdNtT5+>>q`3H{fRrYvA2g#OAlD<2w|>; zYj@cd)osGpxx@_)kzz2E9{A2}{JdWO4iYl6fO?ZSywPdOMB@@qKgrA(f`ttjV4oUd z36b~{uE~*MMKbAD#uUWg6(V*4j;nTKuX1Bwwm`YBc!2L;1M?HhS3vw%Re9EY;Zptm z@l^dQwS6;wpH;RJo$&khgwD{~6K0Rm4A2|1;*$@vMN&oQ!b1wCay>U;leQG__o@U| z{g6XrNXTY?4E2zetcf4HM2WBWo8x;N&q0CwwD4Mhfftrm-*$wo8B3AD1m*nza8n#Z zF!*N8Us$tRWU-Dhgb>>zAIhaD84|(|RmaO;U3qS$FJ5}m2Cc31lN%e%EIuH+E}Y#p z)W|Jzzl&4Fq8)ZbbQ1FLNROX=*P+ZHe&H2pNhYI>LOH2y%6IoPv)P?7I{8U;RynB0 zqT0CoNC$`!$7aFTsB|ah!M-7m`cAF&)6I`@XXpJMSqqun+Ou?%jjb5jy+-F3{#KDa z9{?iG7Z7;YT?>;i%;C>=P-CGYpV4tMAB5AVKE~!Vw)-x{nA1)=(i2Q zUkN7JBJqU+pQy10j5_>jV}?q6L@Wn2%9b@hm>uDE!2(?A{@LGF4}XOz9%zI^O^50o z@swa-`GiRLx$|rf^cB%)Oz0LYH=MnzDpih*Hk+q@!Sj7+JXz&0$cc01OH%wLJ+q7q z=r6}cIb&E~Jqqc@2O(L@4`FUH*DXmGV>Z{N?-+(8yF$K`+I`i*KX4T*h|HZLf@-^` z=M=+uAP}5evt39%I9i8RM;r2C5%UC*DLskhaXf{P${Y8hD2I7F;9Q3}yr>^EppE&n+cTcEELPl{gB0Gqs zV~I%5wC+8c90CRSMoU8+1Z&vsV4jGEdNd88mTD_|(v4`piJcQdi01NoHd`P2ac>*OKQ~{Sl6d z42e=gH|Ekm8LjO?4(DP^RW#&G>9BC^Miu*p)BxmID5QqLs*vCp9hR4e*QFR@bT}Sc zf9^jPGiOq&3@UAaPhdjv^>|jVZZloeY_e(S)06yXfY7wB4#E*Mium|<|9GDpO9rpq zy7iPg>$9Fmm&=@7ZcR6WX4ld*qOA@u-wxtu&8wnsn`I=0wMi+Kn0D2v4hA0AUD=%D zT~@3j`B3*hPl&%n`wkDNkrM2;?D-E4`=p$bwhTQe7xkI7{jc>$oD=3?=9DyhAG14y zk8M4=J9jJDc8%tB(R(y%qxDdgCFn45DKgU%3WB6yZegHu0rzRaL_@BRewiiVak?e{ zyi{VETnohP?kt9hQPrDK7X1ny>gCSkl`vaKjCrqb3D-)Nro#Qwo5J5=fy$*6kKK3# z6f-vUCEc zi1~vJgN1W^9&)D+a%77Ncz$;n=WY_C0_a)i;E4tr_vj;G8%_gf5K9$`Ch##PWzo-w zz#Q*uLWFacOJqX*BCKjolnq~|&NlrazeYPHs!w}5j}0^qB=;$sd&M?zC5liqgx{#! zYsm1?mD>xCnlsaDem0OX#87rjJ(+Adu}H9!}+Msi`!LFSB)Tp7=Y)9`9IsIJh?l^TZ4vDqFaAoWuu)0xhNV zu}oPQ%LMiFEoNx@sO_|A>lu3vt?5_3SaGDWO_U(AQnj8@fF^-E|Gtk!Bk zZp8h9>|JG(6X?#k5|m+KRHf{sUSN4@4-)aWI2yQoI{t-mJ~1DcRGXAEJCDlZjfdKg z9(g7ZRXxb=VK_pg3R5xOFa2DmpR;W|?R-&;6><92UP(*UO!m(D;P|rGwXk}w1aa!) zV5HZwzatq)#QkHKj^doNc0HepjXWUrCoVz|sAke`aQ-*)jMYO(!#k|P$^ulBLZQgB zw@-2=Y`6~$Jq2`Arg%I)h@c#XkIU~zlME9+FiPCq=IpsPjHC?IlX~oRYA(sBhfa#9 zhCmWN4)3EYLbfkC(vlwkCPds#S5H(xQ->!#a)h58vxS_B85_NM5M>+ARYoY9+-yrw z@=3IibCBhA#grF1Lltv&Zb8%bHuEyF95RI zz5nunP+7}1eZ%o&MdE6t&$@RVwiYXQ%3E;C{;U3)dl|Yn^9I>KTtRlB261dW>U~>o z++;1;hb^`Rhl%EEahcWmu{pDm3?QUi75f-zws%T3S>)`1Rmib(WUesZJ_U~7ryd-_k5j;3&j$nO#rWWXyBS^A0OZKV-F+i><04V)jj zH@2Vik^JsdK>;2Q2yDZ5*Y8s0nhiUxz${@q%Q92@@{Jz-;Xx-U<61LizO9!e{tyefo;9>+BxAl@< zdII;yA0s_M`Rm>o082Hk*g*q9B@*y{^TP?aVBVK&Et{H8TsDa(;b$}(e3jY?BwOSo zJ#%_fs!?Asb$z53VSfL7UZK2TcS^@>L;1T?|0`JKUgn^Rc95j#7S`rvzn)1VOC1ds z#+p~Q)a5WVq8vG!5}|o+1rfyheBPX5?p==Fhf`;DBzsT=O47p<<>0ymF8|t-uM-J8eA4~7i&oVvn?&8a`nYy5?pjy zg${n|5amt5eZnisx@8;rtq`$&HGBdBxpqE8d@_;*a@~x2SxjnQZIH-5)pls={ZsA) zx@?h}zC8vaTH*H#N1G*-F$&W|i#}&yIv|Nh>?}n|&3=}xZZjD|vr&(oRGw7)#is^% z0g%g7xVY1MoAf%2-FxpB_#`R(3Vkh`yl+q--4OO7q~H58?}1z<=vu3qpDu7**}5Nt z6bjU|>O+VQ(S!ii`aDnLmpqy9WH?X~QXMm)QeDsX-!6-KWA}Zt+(Y}dR8WSQSKmO=euRyI#h6-d)j?}Q7dLH=usYA-Ui)HlV!PXP0TLS|`fmY=AkR^=HRoJE9H~%w_o2mhc z4IhWQy7RRfz%W68T+}48>LM8!*+Te*s*EYOU7*mA#d*yarGnosqJa23wdpVqcJ;} zk{t#}d|4fKIDjt3Zkfxg^aZQkFPnrJG=T_OdA_5N!Q1X$R?FQV&w^oRT%36i%`YNA z`v1nDV?Ny|EF;tp8szxALuWSUTi_YP-wKLhaEQ+T-utcWbz7sGsXI(s;Ne|orndKA$*n)jG#z;iyY3+vD-YGuVS zl5T`}m>(-%W0?!Y#o+4S!GUsM!ruc4K&WS z%iuWDX@-9)W2*5h1P(Mp%lu{dn1n;;P#^G7estoVs{}FZU4^bFugh`pF0z@x<>k9h z%l=&7F5p#}E#0{ArNg@R4I`bTu_hej_wkrN{nk?m_k8;GoQO?ghmgO%_p*Bwb~MI| z=SWnQ2RkJnKeCx)c2{`V)&Eyg_h`A|_uYLUQI(An;o2;5q}p33#~5uD^XWR1z-p zAYe59AbvS@Jt)|o{QYo-CYX;sP+1xORIgH1!HQ9KNGOsW0weCadkwUi=3Bg30Npw> zKhbjl#hUA=Udp;|$$%Oc$^DC`lkvn#2hF$Mclg+T?MVF(vo0w~A=KNw(1>oH=+vwL z8a14(5*^$U3zNbL`w_R7zTgNA?4c$`oFyqpzfi_f-t6Nc@O?PnV-mZh4Nz9TTDen$ zheOlT4TfXA>H_+28;LDXKZM-{rhhegViH%rV7AY#Mgsb>C0>ijkyt?TU88dD4;6tynr$I2wluIUU>}IPT3m0o@r%pjZa1B{JHm)#X1R zXti=ik9yh$7un+zC4rPOve*8X2>+#gTo?Pbm-2Fj{Nd%9#tbC{wkwDHxe}!!$Q~VP?TP#wF)E_sKVI@oqe=Y$x{Y?50t0wb7Z0}53;Yd zHvrDOcr4J&hOo^8a5rlWxt0$DMeNDp*VY>oMg5K3RMv_jv9S`v zH``wNC8m>-7Qtj*3*}}1Yk%|rAwr00`yC{XNfRVe)%F&YQ@v=M!UfYW3&Gb?_nGzf z@NL8VU!A@sRxxNE!HtMZS{ZX|B3uz#R*P?nQh@Y;qR_nv1c6l%>gi6*Pa?}sz61Jw zNazT}sRXP<(X7C}#26-cWTW93yNac7_V@&|hkhzG8=o1Whupt8m%iR%!E0%uDpug8 z9gMRTBmTYb%gQyHcncG6;u@I<&>FHE9S<4dDun}Q+OKzZ?WXglN5iK?OMwC&l$oHj z#;=@To|VM$E?aVionRM*Fo3p7%I4jUqKhS-h{u4gS#(b=sSnuoGd`9HRIt!83cbbV zc=aEv&(_i2)rQ~rvH3>r=X5G#9ae)jVaU3d-SGpQhbasJSFebyBu|C3QH^J28 zq9cQA=7ou^EVcHzBprD=GuNmjkk^u>E^8EoMc`+%hK*_lOwC|#z~e#)7-E`?ze3k4 zX~tf4n@>(3s|fUsNgQ`>qyUrSeJ=$gprOw=;=Qw8`h{tdvl^;M$KNXd^t5o$_q%Eb zL&STx|K@B+y!L`*YoX$e9KP7j_OTj)r+&B^zJ;(cjV;Dm1uRE2#4HrPM4$0-JUyd1Kn|F8uuD_K9vW5l=RLub18 z0UI!pBaF30>d|HjBq~KUXDx9pEI0w4!2V4C%H&I~ITI6k3-$6=2)p zH7o!2&D@2T#1OgNY%O`-&rkm@|M(xtN)^<|GDhZMv7}M=ljZPVzvTLyBTNA9C;Z^x z=P9|OM1Fp5u4rbJcD)Twmd}N(2EC-jP+@5)%4z3|P({lDeP0c5yM_j2q1N(Gnr(%s zn;U0KON)9j6=rl+f4@}Q?Pg>X@ILQBVd=7OWXQ@tzw@aX>?^;aepjdUI2g=k#HA z*+0+Lm=A|sv>xCQ@&VM@Kin7&gXSwYmiMQ|R8d?UhRb0!iYChw+M(m_eMDqre)93r z(a*V#znuEs$MxE6o@_fKsq9}k6`0bw9r{`P@8kz-qIR>qnJpH+8G?~2+b)nb%d`Xg zBJnOgI3vzZ4_e#~&mJ$wB0t`s(>5@^F2~6Cdgenozw=g@zK#yTEE_)uKt zpUl|3Q3H5s}vt z8!9z5HJg8hNrcJ7!a}heWX~l!I+~V_j^Nm)Ad^Y2;f$=oB!%5Fh7X|mU|%WGH~$4k zEpwjXv)%=z?{~M|EA$e0-4|Uq6n*!om_G_OH`(a|3Qd|1YTQifhL2ikXCS>=y{=#9_88L7v-NTR)$o zgeSDSlm89+|38M`zfKQ?+X_Z{_O+72gUXCL4GR~QTOw~f%IoUX3)4`?tSZ}k{*O80 zRF2mR1~n@Uqi0IB2Hc`O`Te9H9?duwNuu(jUzuWx=^D@5jnMN+d6wdf5G{Qth|TZ| z&0+nj?~Q>*1x#>*eADB_utu|H&2w8alOC>zJiUsPcN0h2gw=M{f5A!ri+laQy)gTU zchnBVgSx>8r%q)dE~mR4zgo*n+ceiK-o7B#{{svC$I~Oh$uoNGU`{|inR_j7RNk8Y zfAjWXpR~=)&7&m*`;!3t_c#Fv^ukZPeN{io%C=qt zOy-+iXmFWyvCp-goY(;1xbi>1 zY>P&zX5Zs}a#E7gUtV8b)Yu zU^o`d#s7pT5|8CTJVQ??AhhL*2G3rBd#*p4Xj?K8cSuJ^=L5)3^0ws1kGRwJ8^h-E za)mw1gUh=u@6&cI!#b;pA9I2_oi#NzTd%hhaeaRCoNB+;VbF2$i(xx2FHfb?zs65P zU43xvafdq;fZn-VA0Yw>iE20=SGoW0d7%FvZ!DOo2p|Oe3b{6c#}5w?Kv$k^X9&>a zdpDx9GonS8BFWbxtVE!kDKoK36uT@lPDKg(9d-QcS(Q>@6?&NkIB$LfL95dvDQ`zs-WtDm?M9OuD(sasvJ*nG^Uwn6XT;o#ai}cT3zA@~{&!OePL5H`XWq0P{s0 z@_~D0we5g@yG`yyeX%OHEVJ}}u>8V1Ia7rTh~zLG%>j^Y?h^xyScM?UpQBWOzybyI zCSz8AHtHlI5mW$y96GToI$+{BX>um6P&%_24^>j!*d1Ogo{B0S&nupohI*8*zgg4c zZO0^lF$i$k1I9u>whNJgeV@j;Ndi0Weeq+s$W!>CE^fzndQ}(Ht?W`+v9Y^2iV;DM zSJRe`Ua>hwLeSB(lzV3p?_)%O}qGXzo8P%ceA;DbOk z{H^0o;NYzhbY-;xx)HAfnmBMfTjeejt=J3RPOs1TH7MIJ$J|93AFp<)Ejp& zxjPsLlq6-1PwXEPBOD8kDP3>u)aPEtExl=SyPcqPoM4riY*j6$Dw%;P@Pisf!By{$E(#CJ6A|G9*Z zpHv~m!U#B|PtA?UNKQ&hVl*A(4kY$OK=BSU*=>s)XpWfayIrL-p6P?BkGNUHyBJN3 zhA+qW`0|r2jg<+BGOGXwzC9B09np&&!lE&D_9Nxf7o0a(%i%F)Pw>>kGgJgw3bLa6s4$rRN)Y|m`bPR`HyR z0QFT?eeYzOYyRsC|K5w8(ui`jxkvgffvfzK!0vFpBnv6#SIvH2F~GaNjY<&vI5N}^ zoKs;7>M>(Ac7BEhzAH*_Zk(Qo%~cu(Z?~@vprXwsR8s63`31BOtOgj>(tJua9*-dK z@~G}joD?RzFT5m zmEi@hC(O}C!+{amIq2@5F!MTH?wGpp%3{%^5h*H0z(y+k95g#-rhvh86?skns=UhA zma2x3^(4b_SmvCP<%hKTI4BAN5sW<&p9t2cBzwSY1qgmh6>5g}eX`d$+;ML;VZ{%5 zasv)!#q3{dRp=KVyu?<2lIY3HE#%xh-0%xM1LI75q#GHCO4uV?l!*UO8+ZL!>S$0$ zYeVoGqZ6k28hdoOovzMxt$Bd+>9c{duFNfA21!L$tvyqNU2#AAA#hRx6)adss4yaF zN0kXHd*k)pz+=U2zRJXEs%h+M-ZXaOptO>7l9#vCKS~Yb1=JARh+1J(iLlDKCOzxY z8KRZXf8Q+ zT=Tt;H6pHdg91g<%;<%MT5(WaCC)qlBB-Asm*pD-L3bPf{6iQG52o|NCHwZF*4W^N z1N!@*3-48BCv^TQaw!MP=6TNFH~NOv1E=8$Dq_8PQ#j40N~LJ^^p9-1I8we_{<+eL zNvV+a{6h*-cK3{);urncnl|dVpyV)f-Bz2oI)Zt@a#q?BL{Jm*Z@<(K*K5RoWQuUn zvHU81e8vHEE^b>}Ovroi~cmIkeHWV0QwD{e?UpPGS{cS|cS}2~V&#hehEvsuPa@Hm4 zc^cy%rg>9%$13)2=4Pbl6K3rzNzB;R z2SO|zCOIixCJqA4bC%0-vM^#Kq-M1J>pO~=F956o-2vDy@nq7nf0ts}Wm9z=HT46c z(z-9{Te#apfkt#c=B{*53>*h)WVICcOQd+qSHu(HoL@{)i*GOXqyG9xdwM-vF-58) zqky_3Q7AhY=Z*q?XAn6dH%U!l6aiIVG0nT|(bbMY7l!@?_KoAipr~#p6f}-;D~|9V ziapxQkDq?d{pNo`2aVgJP>|l-^)(QZ%e|+(S86Vpk|bfCu~B0HT4Bl!e`byJn(MO`j3xLTH^5EK1BuLL@o5v+O}JVFQodw_H9Ay5(nm zo~l|uBUw6lzK<2<%F7JrvG-WXcuo*jvUq*3ETN#hfFB7ALNMlxj`aB$BY*&*O^wzb zrf9oxCx7EBmK=t{()LF9ej--ARIBYu?Yp#K|1|?`CRKqsruBZSqit_aY=%;ez`+AM zhWtynuS)EBysI1y5>ll0g9pCq`aqYM#~Z0tGRaEw$RO3RFn7l+Ub(#E z)6m&D1S<|i{HQo;B$+-%MUSH=1&VO4moK!b)KrWk@Gum1WJedC0J4*NEys;|w&@*Q z_pn66C^~Sb$kj!MQg&3-n&%a<-2X+8D1QIW#N>m7(Y9RCjMyBv=VbEi3Jm_+MlzW^ znIeiCd2P$Dy=%mG1aDfm+axr@6F#oz+c~l*JheMWyS8{#jv)jYVkiWUepJY~gqI5P zR$_|6{40&-poo3ygPdpfA&(^EICF(n=Ixi3ZZyJZVhLqO=}WVThXoo;qtkRQ6wtc# zmh}oe-34K$#1P}V#&;Xi6JwmLI>Vpg!TLccSAU^ZG{+RBRIeW}jplr)jp7BY;PaoInr_UfoCO@f^^FEJxz_S1X5y^ zP^7;1PFFUN1u_ymn6PFAEG?l#uYz>=Jv$&$=oI+HeeuD|W5Oio*I5xLVlUUn(Voi| z7TU@-a=>)@-ncP!bv+5yWXVxumb_q?+;F*?3B+iRGYVG1ScEDIkZhYxvbU1m&vH~K z5FV2RkeTTkNdN4G@b1!7SxAH@Rwb{fV{x>hqSV`4oaK4&m?hfirWRSf7Cm39WcqledJp%{q5+Pw|!v@Y_P;IB-3ePGaJ%s#`a9W!(j#*J zKKpv-@r$J3T0=P@2}W6Pr?**lz2j*y1fYTP;U&AwLe4h^)@L3Z>kj8IhX+MbeqAI} z)uc&K0{eB(r;%XAESzTO7W5AYg!v1!Av=`o#=~cGB8d zXwa9~iXaOy^n)d%$oXOtG<~h3Sf2~C}TWi^W78%ijh1s*1X{Z^QDN1Z3Aenm+xT% z22bgZ1!yU4_X9k4{V(K~%|;UK$zPxKnUAJu*5xTSgBwr1Zi*2Yo)6;2TqCp!?b8N#%aTLm zO)Q{hA(HL^=B_%&GNz@K05Cbu8w~Qma7DY0Q>^cucS4?+yW-R9GLt%+aH|@lmp-1* z!ki|J(&d_}qCFWH4^R00<4A_fWwQPUFZk_vgOtGP)Qi>;?`*{WizDYf%OeGN&WG$f zE#=$Y4?IdeXN{fcV8JYEXK#9Dk)5Dea^qy>sVlK*Jq!@*I`m&PWnIF0Y5t<^6=+`L zSg=42Z@|hxmZVVweCpT}VMV$_Bp)87icbu&=gG^v8nOr87S7Bc{O7JCIpgrdtnK92 gbGlR!TmDdBrS`-629iABUxYxil8O=)V#Z(o2PCdhLjV8( diff --git a/test/ui/views/goldenFiles/notFoundView_1.png b/test/ui/views/goldenFiles/notFoundView_1.png index de47ab31faf5b191e39ea7836f8402c8f868c8b4..07b7d9cc8bf84bc9653cedf4418063d0bb86c7cb 100644 GIT binary patch literal 2552 zcmeHJYfRHu6t8ck!D`F^3oSSojnUavq&(WfBrMoO%O(U^6slHWth`ZLDQy?gi2=$C zfw~lM@v&wb(m^d$Xelaf0j2+e3Kl4ZmRg#&U_ttTKK3`+w=I#xeOR{L{7&vYH#g_r zbI$La+-si`<9&VLJ`f1RmvA)h1O&1M3d+dljo{AdrRLkN^~JG- zq|M+c+kCD90@-ql5O*Yr)?iViD<<`b9;?B3U+-6?o38uBUf4E%VETvhq|29Ec6D|X za1)c&rLk6a`=yYGigIGTU(_#^iBY22qISf9>QVo$m&rqLa;d*~>&V@q1xc5ePEZ0_ zEG9so_c|83QS*zQtnu;ju60x18-tlA6?wLDNFMC$nved+zb^s`UXX1lKDatuQ&v21 zJzP|zA9y)72G3G9v|h!VtzpEQ(Rd`&G2L$I?MtOQuq(Eh|BCB)Q7kx4Wh)KA3SnZ!sK$ zkyoO+BRZVqphi<+5_psI>Dr^c?~Of@{66C|o&_`+}#TEnK~D-6z%8fWrM-G=WfR)?qU9UW9y@nfM-XdT$kH&ZMY z+WqAa3W>4w!a7wBo1<7dEEhfP_>@gfx}A*S=3dNLbtk;a^k1s0t7B-sEX~c$)y9Xi zI0w_<0Ny^)J%W5Qd-z!Y{&!_C@{M4Z65C_><78nRLzzySzOqi8!M$w?i6Iq)(pLW- zfyH7`@7t7@lT%gcj{;r00`=c|zJV^Ka5x-0Bga$XqTj=hQD6&R*YQk&sy@Z<(+^jN zL(c6Nre+J{5Pk1o6#oPZY=Atwyu6&6mWJSRxnu@|fjkNE>Rir6a&~rhb8~Z*OeX6$ z0B`BT3lep9MkS}D@Pf9OA8NH)n(;12POiaYR8Lho?P1vmnphsE6>Mqj72*V%>Fj~Y zRoH}TP-*4uqc1thxe z9n`8P98^LSwJo)5>By^eO$p>#*L?3awEV{5fLevtoW}bRzGWh|4ER$s+*2tV9v%+R zJ>fU3jR$60Y4c--#On1nql7Xl4jbM3Psi~;}QumbG$~TSj;863>d^C+E zrdk#Y=O!Ky3`)y$BOmFQj-VTUvbw!Y%l#;GB5y7sW7aU_5Sm1EiBK(_2gV zQn&36kLYgN5QK(8p*lT>)GcHI+WjVzNoVBUM1l#`HBu+PFU7qMQ#NA5>+9>~i3#{H sCn{s`W51rEL)^jkzi{WBwDhbiVtlhZ^3HJq_ZU`vhkWoazfM}8rFqi@+0YZpkKQ1Nov;70anf}mD`_8I1V9S%z`QjIz!6v-@l-mjW{PcXRafgdrtrX7+~SmJBCd6!PZUX#8Gvyk0x`DK>j z;S)BT^XJcB-QN3x@#8hq*vHy_!M!i`nV@nDwaNkAi;4PA?kctbC7v8Oo#uj6#C%wq z8CWG#aa8b@s)y(dXYA2UG>!s5rrTs5%t)^uw&SFh*JEuuU3cRq!)-fE4tZIhqld#b z{eST#mn1dG>Rz`H0evgVi=?+v%`GilsT!yZEuZ<>IFpjMw6v5VFTfQJ5a4-1$dx8E z6%<|Hsczu&Bcf?b7%;;ERa;>rmi-;xa;b+1w=r`fN&d zO-+9Slj*TsfzDL%3Iqxb^bU;zhhmw6xHGT9f6r)lrF}~8%TF5~9j$&A=lF^`AIs!$ zaBONbI(;msKp>S!s<_8$`x9uQF*4Gq57I)z{yj*`zc;X}ZFqOdt}EbxLbP z%L6SY-8t9=`_@2md8rsonJv2QplC#&B+x&rI!q~END@eWX1^l)r@TuC>$55di^g-}SnO#(?a1oCs zl1RKa=@X1f@hmvGzv*rN7fGu@jXP45b}su_@t@>2PG7zh^&klo6f`Vm%dSQ zeCX)P_>0dh6 zmbC(A#W%UkozsW>zry|hKDtgyIhyV4cYfX8(Uj3U)}LKAr&C4+_O4j8+kuCyX&^*9XA?KXOSCZr?%Of zGnHkX(kdlT3&{FzD6btupLXI87k7h7K)Iw~*D5lY;^l&58*lB<`y>U|^&?;=Qi9W0 zf;>(;HY!_bjnWHktD27}6ey7dMKE;kCC&{U0VCCe@b!8;9#52TrZJrIA%gjeS#;{a z=Alw1QgeT}3X5zsHOfVy4y2_JcV^9r+0#$$Xf&yE4+0^wKtc=6ilSwj%gt(2lk{b- zC0nzu>aMLk$6;6N7H%&N5^pGbIy2vQ00F6~*u(=;f*s%@*axhj6=A9cHexL`J|A0u zlf~k4Rz2n{4pIt>U8&QR<#;N!{j-a&%d?!oqJd~irD%7T@tZ9{Zi5L&8xeUqIXN6o zt3%r;ewTet)|&^R&U$Q-L=x$)S)35ao$|WJ$4}Z=TMHRoI1(7$a)O~d`$#cywpuem zM4@=i&Ek~Q&)rG&1p`8my6XjO^lnX{q3Dk_t7LvhI5uQ8p1hM?_vN5TUBQN1ch@s~`s2&_@i|4h z;`iRymsS4x(!Tod!kbHLD{kB0k11Yv+H40eBOdQgx@rH8H|N+L`SkzqjvqPy?tV4U z`7>)b{Ycw*GS%SNp6p%TzdwA}pPnqWK5SOym-koaTRi=}@mTJOoB5CQ?W)piK0VB8 zU%0>aXI9O>7f-)$S>!vr*th(-{^j)keX{dyqiWw>p1;S~uC9J-?SH*RK+pWk@-KdO z>W)P6pC8SeYlBM5be`4hD6ReUaB1ZCjNL-rme)(9e-~T>>bSRWb7UC<;e@#CXp-UU zjYrq}Pk-Dk86UCxU2s|PzKHKS*I$0lEz9evyxw|t*0Pre-$XEoA2;#kzthIh8G(*Y z-n+cqfBRmxitM-V-}isNSDkkMxgh>TWH4F37~xv;2c)2BNx zU%s5NEHh?j(a}5EeEj^!udWUcpEYwgfBN6L-JAG#8<`*5^EdkVn}|7c=Jed&p1&KgYpY{0h@x{`|NeOu zpMF|&XLotNjI8Y1Kl9q#+c&56_4kL*v$nOBP3|cyC`ia-E>1pkdw=PfzM}^Z9$a%g z>wo&YH@EG!ugaWt?Bd0XGi_JZe0_D*xK?M@=fnRa(L)+b*l&r@nO4kp{b$o1!*lKY9JQbXWB aYuT+0>z)>@_zi5kFnGH9xvX)6h;uumf=j~m??wIS64G)W-PTj)IwyA`^+!3v(-2 zR(yMNbKP}@nBws8aCSd2hoXY#=jO()XWa2@S>~^ECz(8skc;@9@zvGtl==TBYv-ps z=G}(NGA-}zwVYXf)c@Z6WBq*Lvu{tYm3VyiU(M}(dbrK;b0R=&BoM`6X*Y^&jo%vh(ZTfz-eS7!6pR3c5 z^6liK+eg)=AC&mK?xo$^!}j}P`Z8nIntXm@zuLa=6n}E>?Fn!5AFa2mNw4{HFspsx z{`yK&yZTS}!L=k@L`fB&vZQW}&_*uTHKd;6Nv$yxH?z9okJ}2L>pVZUW|Nmd$jMlR=dw7eJ z_v~3#5PPvwt|KTcN1om}yxWT2E~#CKM^KVO&6jyQg= z>eKA|>rCJOdi(9y+TZ{3g$WuO`TM3o#PR*}{#9T1RuJMYdo_Lk|GVp^J3KLC0p;gq z`Tu|XEV|y!ux`8b@#FQSn^1g!>>K>-NtqiXe%Md From f25d1681dac0828687bd6c94bee51610f515fedd Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sat, 9 Mar 2024 00:28:01 -0500 Subject: [PATCH 54/62] Fix workflows --- .github/workflows/dev-workflow.yaml | 6 +++--- .github/workflows/master-workflow.yaml | 6 +++--- .github/workflows/release-workflow.yaml | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dev-workflow.yaml b/.github/workflows/dev-workflow.yaml index 53de5a7e1..204f18ed2 100644 --- a/.github/workflows/dev-workflow.yaml +++ b/.github/workflows/dev-workflow.yaml @@ -54,7 +54,7 @@ jobs: # Get flutter dependencies. - run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs # Check the format of the code and commit the formatted files. - name: Format files in lib and test directories @@ -176,7 +176,7 @@ jobs: if: matrix.target == 'iOS' run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs cd ios pod update flutter clean @@ -202,7 +202,7 @@ jobs: # Get dependencies and decrypt needed files. - run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs - name: Decrypt SignETS certificate and Google Services files run: | diff --git a/.github/workflows/master-workflow.yaml b/.github/workflows/master-workflow.yaml index de751b3ef..d347b70a9 100644 --- a/.github/workflows/master-workflow.yaml +++ b/.github/workflows/master-workflow.yaml @@ -87,7 +87,7 @@ jobs: # Get flutter dependencies. - run : | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs # Check if the code has any errors/warnings - name: Analyze code @@ -178,7 +178,7 @@ jobs: if: matrix.target == 'iOS' run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs cd ios pod install flutter clean @@ -186,7 +186,7 @@ jobs: # Get dependencies and decrypt needed files. - run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs - name: Decrypt SignETS certificate and Google Services files run: | diff --git a/.github/workflows/release-workflow.yaml b/.github/workflows/release-workflow.yaml index 2bf9a93ea..08d0bc9da 100644 --- a/.github/workflows/release-workflow.yaml +++ b/.github/workflows/release-workflow.yaml @@ -49,7 +49,7 @@ jobs: if: matrix.target == 'iOS' run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs cd ios pod install flutter clean @@ -58,7 +58,7 @@ jobs: # Get dependencies and decrypt needed files. - run: | flutter pub get - dart run build_runner build + dart run build_runner build --delete-conflicting-outputs - name: Decrypt certificates files run: | From ddf220213f191046602081bd2ad8fd1d8e5609b8 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sat, 9 Mar 2024 19:35:14 -0500 Subject: [PATCH 55/62] Try to fix grades_details_view_test golden --- test/ui/views/grades_details_view_test.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index 8b783898b..e4000b605 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -236,14 +236,14 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, course, toReturn: courseWithoutSummary); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( child: FeatureDiscovery( - child: GradesDetailsView(course: courseWithoutSummary)))); + child: GradesDetailsView(course: course)))); await tester.pumpAndSettle(const Duration(seconds: 1)); await expectLater(find.byType(GradesDetailsView), @@ -254,14 +254,14 @@ void main() { (WidgetTester tester) async { setupFlutterToastMock(tester); CourseRepositoryMock.stubGetCourseSummary( - courseRepositoryMock, courseWithoutSummary, + courseRepositoryMock, course, toReturn: courseWithEvaluationNotCompleted); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( child: FeatureDiscovery( - child: GradesDetailsView(course: courseWithoutSummary)))); + child: GradesDetailsView(course: course)))); await tester.pumpAndSettle(const Duration(seconds: 1)); await expectLater( From eb722a34b0115aca3d6dc045efcbc4fce1a4e3e4 Mon Sep 17 00:00:00 2001 From: XavierPaquet-Rapold Date: Sun, 10 Mar 2024 00:36:58 +0000 Subject: [PATCH 56/62] [BOT] Applying format. --- test/ui/views/grades_details_view_test.dart | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test/ui/views/grades_details_view_test.dart b/test/ui/views/grades_details_view_test.dart index e4000b605..25b850973 100644 --- a/test/ui/views/grades_details_view_test.dart +++ b/test/ui/views/grades_details_view_test.dart @@ -235,15 +235,13 @@ void main() { testWidgets("if there is no grades available", (WidgetTester tester) async { setupFlutterToastMock(tester); - CourseRepositoryMock.stubGetCourseSummary( - courseRepositoryMock, course, + CourseRepositoryMock.stubGetCourseSummary(courseRepositoryMock, course, toReturn: courseWithoutSummary); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery( - child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: course)))); await tester.pumpAndSettle(const Duration(seconds: 1)); await expectLater(find.byType(GradesDetailsView), @@ -253,15 +251,13 @@ void main() { testWidgets("if in the evaluation period and evaluation not completed", (WidgetTester tester) async { setupFlutterToastMock(tester); - CourseRepositoryMock.stubGetCourseSummary( - courseRepositoryMock, course, + CourseRepositoryMock.stubGetCourseSummary(courseRepositoryMock, course, toReturn: courseWithEvaluationNotCompleted); tester.binding.window.physicalSizeTestValue = const Size(800, 1410); await tester.pumpWidget(localizedWidget( - child: FeatureDiscovery( - child: GradesDetailsView(course: course)))); + child: FeatureDiscovery(child: GradesDetailsView(course: course)))); await tester.pumpAndSettle(const Duration(seconds: 1)); await expectLater( From 238ae35d1378f38edf18df50f96bc10d764be5d1 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Sat, 9 Mar 2024 19:48:11 -0500 Subject: [PATCH 57/62] Try fixing grade_details_view_test --- lib/ui/views/grade_details_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/views/grade_details_view.dart b/lib/ui/views/grade_details_view.dart index bf642dfb4..a8ef76bbd 100644 --- a/lib/ui/views/grade_details_view.dart +++ b/lib/ui/views/grade_details_view.dart @@ -130,7 +130,7 @@ class _GradesDetailsViewState extends State if (model.isBusy) { return const Center(child: CircularProgressIndicator()); } else if (model.course.inReviewPeriod && - !(model.course.reviewCompleted ?? false)) { + !(model.course.reviewCompleted ?? true)) { return Center( child: GradeNotAvailable( key: const Key("EvaluationNotCompleted"), From 56a2a38cf4757d252e49424cd531b208e026b39c Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Tue, 12 Mar 2024 16:08:52 -0400 Subject: [PATCH 58/62] Fix course evaluation bug and set appVersion --- lib/core/managers/course_repository.dart | 7 +++++-- lib/core/viewmodels/more_viewmodel.dart | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/core/managers/course_repository.dart b/lib/core/managers/course_repository.dart index 26ca53ea6..b7f393496 100644 --- a/lib/core/managers/course_repository.dart +++ b/lib/core/managers/course_repository.dart @@ -510,8 +510,11 @@ class CourseRepository { /// Get the evaluation for a course or null if not found. CourseReview? _getReviewForCourse( Course course, Map> reviews) { + // Todo: changer pour firstWhereOrNull après update de Collection final review = reviews[course.session]?.where((element) => - element.acronym == course.acronym && element.group == course.group); - return review?.length == 1 ? review?.first : null; + element.acronym == course.acronym && element.group == course.group); + return review?.isNotEmpty ?? false + ? review?.first + : null; } } diff --git a/lib/core/viewmodels/more_viewmodel.dart b/lib/core/viewmodels/more_viewmodel.dart index e932f0752..0f3112816 100644 --- a/lib/core/viewmodels/more_viewmodel.dart +++ b/lib/core/viewmodels/more_viewmodel.dart @@ -60,7 +60,8 @@ class MoreViewModel extends FutureViewModel { Future futureToRun() async { try { setBusy(true); - await PackageInfo.fromPlatform(); + final packageInfo = await PackageInfo.fromPlatform(); + _appVersion = packageInfo.version; } catch (error) { onError(error); } finally { From 8a03d5af3d702018b88d375ae74ee5f7ddcc5c67 Mon Sep 17 00:00:00 2001 From: XavierPaquet-Rapold Date: Tue, 12 Mar 2024 20:10:28 +0000 Subject: [PATCH 59/62] [BOT] Applying format. --- lib/core/managers/course_repository.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/core/managers/course_repository.dart b/lib/core/managers/course_repository.dart index b7f393496..6e7cb68ab 100644 --- a/lib/core/managers/course_repository.dart +++ b/lib/core/managers/course_repository.dart @@ -512,9 +512,7 @@ class CourseRepository { Course course, Map> reviews) { // Todo: changer pour firstWhereOrNull après update de Collection final review = reviews[course.session]?.where((element) => - element.acronym == course.acronym && element.group == course.group); - return review?.isNotEmpty ?? false - ? review?.first - : null; + element.acronym == course.acronym && element.group == course.group); + return review?.isNotEmpty ?? false ? review?.first : null; } } From 6e544f9a9e8968cb4595606111389fd5c4d21076 Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Tue, 12 Mar 2024 23:49:32 -0400 Subject: [PATCH 60/62] Add analytics --- lib/ui/views/dashboard_view.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ui/views/dashboard_view.dart b/lib/ui/views/dashboard_view.dart index 77b66873e..a214ab5e1 100644 --- a/lib/ui/views/dashboard_view.dart +++ b/lib/ui/views/dashboard_view.dart @@ -493,6 +493,7 @@ class _DashboardViewState extends State // Should not happen becase dismiss card will not be called if the card is null. if (model.cards == null) { + _analyticsService.logError("Dashboard", "Cards list is null"); throw Exception("Cards is null"); } From a199f96c4bc552015b75af9d76537d74b180234e Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Tue, 12 Mar 2024 23:53:14 -0400 Subject: [PATCH 61/62] Chang log --- lib/ui/views/dashboard_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/views/dashboard_view.dart b/lib/ui/views/dashboard_view.dart index a214ab5e1..a9e77a21a 100644 --- a/lib/ui/views/dashboard_view.dart +++ b/lib/ui/views/dashboard_view.dart @@ -493,7 +493,7 @@ class _DashboardViewState extends State // Should not happen becase dismiss card will not be called if the card is null. if (model.cards == null) { - _analyticsService.logError("Dashboard", "Cards list is null"); + _analyticsService.logError(tag, "Cards list is null"); throw Exception("Cards is null"); } From f2e374ebd216cc4e672de9fecec4413d3394103d Mon Sep 17 00:00:00 2001 From: Xavier Paquet-Rapold Date: Wed, 13 Mar 2024 22:22:17 -0400 Subject: [PATCH 62/62] Add analytics --- lib/core/managers/user_repository.dart | 2 ++ lib/core/services/navigation_service.dart | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/lib/core/managers/user_repository.dart b/lib/core/managers/user_repository.dart index a4eae1e80..5d9980769 100644 --- a/lib/core/managers/user_repository.dart +++ b/lib/core/managers/user_repository.dart @@ -185,6 +185,8 @@ class UserRepository { try { final password = await _secureStorage.read(key: passwordSecureKey); if (password == null) { + _analyticsService.logEvent( + tag, "Trying to acquire password but not authenticated"); throw const ApiException(prefix: tag, message: "Not authenticated"); } return password; diff --git a/lib/core/services/navigation_service.dart b/lib/core/services/navigation_service.dart index a9e12f7c2..18f714a93 100644 --- a/lib/core/services/navigation_service.dart +++ b/lib/core/services/navigation_service.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; // Project imports: +import 'package:notredame/core/services/analytics_service.dart'; import 'package:notredame/core/constants/router_paths.dart'; import 'package:notredame/core/services/remote_config_service.dart'; import 'package:notredame/locator.dart'; @@ -14,10 +15,15 @@ import 'package:notredame/locator.dart'; /// Navigation service who doesn't use the BuildContext which allow us to call it from anywhere. class NavigationService { + static const String tag = "NavigationService"; + final RemoteConfigService remoteConfigService = locator(); final GlobalKey _navigatorKey = GlobalKey(); + /// Will be used to report event and error. + final AnalyticsService _analyticsService = locator(); + GlobalKey get navigatorKey => _navigatorKey; /// Pop the last route of the navigator if possible @@ -36,6 +42,7 @@ class NavigationService { final currentState = _navigatorKey.currentState; if (currentState == null) { + _analyticsService.logError(tag, "Navigator state is null"); return Future.error("Navigator state is null"); } @@ -53,6 +60,7 @@ class NavigationService { Object? arguments]) { final currentState = _navigatorKey.currentState; if (currentState == null) { + _analyticsService.logError(tag, "Navigator state is null"); return Future.error("Navigator state is null"); }