Skip to content

Commit

Permalink
Refactor: Decouple ViewModel by Moving UI Logic to View (#2306)
Browse files Browse the repository at this point in the history
* Refactor: Decouple ViewModel by Moving UI Logic to View

* refactoring app_settings_view_model and app_seetings_page

* writing test for missing lines
  • Loading branch information
Dante291 authored Jan 6, 2024
1 parent 0f20349 commit 6ac0633
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 123 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import 'package:flutter/material.dart';
import 'package:talawa/enums/enums.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/services/navigation_service.dart';
import 'package:talawa/view_model/base_view_model.dart';
import 'package:talawa/widgets/custom_alert_dialog.dart';
import 'package:talawa/widgets/talawa_error_dialog.dart';
import 'package:url_launcher/url_launcher_string.dart';

/// ViewModel for the App Settings functionality.
///
/// This ViewModel handles the logic and data for the application settings.
class AppSettingViewModel extends BaseModel {
// Services
final _navigationService = locator<NavigationService>();
// final _appLanguageService = locator<AppLanguage>();

/// This method destroys the user's session or sign out the user from app, The function asks for the confimation in Custom Alert Dialog.
Expand All @@ -22,9 +15,9 @@ class AppSettingViewModel extends BaseModel {
///
/// **returns**:
/// * `Future<void>`: Resolves when user logout
Future<void> logout(BuildContext context) async {
Future<void> logout() async {
// push custom alert dialog with the confirmation message.
_navigationService.pushDialog(logoutDialog());
await userConfig.userLogOut();
}

/// Launches a website using the provided URL.
Expand All @@ -36,41 +29,4 @@ class AppSettingViewModel extends BaseModel {
/// * `Future<bool>`: A [Future] that resolves to a [bool] value indicating
/// whether the website launch was successful.
Future<bool> launchWebsite(String url) async => await launchUrlString(url);

/// Creates a custom alert dialog for the logout confirmation.
///
/// This dialog prompts the user with a confirmation message for logout.
/// The dialog provides options to logout or cancel the operation.
///
/// **params**:
/// None
///
/// **returns**:
/// * `Widget`: A [Widget] representing the custom logout confirmation dialog.
Widget logoutDialog() {
return CustomAlertDialog(
reverse: true,
dialogSubTitle: 'Are you sure you want to logout?',
successText: 'Logout',
success: () async {
await userConfig.userLogOut();
navigationService.pop();
if (userConfig.loggedIn) {
navigationService.pushDialog(
const TalawaErrorDialog(
'Unable to logout, please try again.',
key: Key('TalawaError'),
messageType: MessageType.error,
),
);
} else {
navigationService.removeAllAndPush(
'/selectLang',
'/',
arguments: '0',
);
}
},
);
}
}
33 changes: 32 additions & 1 deletion lib/views/after_auth_screens/app_settings/app_settings_page.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import 'package:flutter/material.dart';
import 'package:talawa/constants/routing_constants.dart';
import 'package:talawa/enums/enums.dart';
import 'package:talawa/locator.dart';
import 'package:talawa/services/size_config.dart';
import 'package:talawa/utils/app_localization.dart';
import 'package:talawa/view_model/after_auth_view_models/settings_view_models/app_setting_view_model.dart';
import 'package:talawa/views/base_view.dart';
import 'package:talawa/widgets/custom_alert_dialog.dart';
import 'package:talawa/widgets/lang_switch.dart';
import 'package:talawa/widgets/talawa_error_dialog.dart';
import 'package:talawa/widgets/theme_switch.dart';

/// Widget representing the App Settings page.
Expand Down Expand Up @@ -262,6 +265,7 @@ class AppSettingsPage extends StatelessWidget {
children: [
customDivider(context: context),
TextButton(
key: const Key('Logout'),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
Expand Down Expand Up @@ -289,7 +293,34 @@ class AppSettingsPage extends StatelessWidget {
),
onPressed: () {
userConfig.loggedIn
? model.logout(context)
? showDialog(
context: context,
builder: (context) {
return CustomAlertDialog(
reverse: true,
dialogSubTitle: 'Are you sure you want to logout?',
successText: 'LogOut',
success: () async {
try {
await model.logout();
navigationService.pop();
navigationService.removeAllAndPush(
'/selectLang',
'/',
);
} catch (e) {
navigationService.pushDialog(
const TalawaErrorDialog(
'Unable to logout, please try again.',
key: Key('TalawaError'),
messageType: MessageType.error,
),
);
}
},
);
},
)
: navigationService.pushScreen(
Routes.setUrlScreen,
arguments: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,17 @@

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart';
import 'package:mockito/mockito.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:talawa/models/organization/org_info.dart';
import 'package:talawa/models/user/user_info.dart';
import 'package:talawa/router.dart' as router;
import 'package:talawa/services/size_config.dart';
import 'package:talawa/utils/app_localization.dart';
import 'package:talawa/view_model/after_auth_view_models/settings_view_models/app_setting_view_model.dart';
import 'package:talawa/view_model/lang_view_model.dart';
import 'package:talawa/views/base_view.dart';
import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
import '../../../helpers/test_helpers.dart';
import '../../../helpers/test_locator.dart';
import '../../../router_test.dart';

class MockUrlLauncher extends Mock
with MockPlatformInterfaceMixin
Expand Down Expand Up @@ -64,74 +57,7 @@ void main() async {

test('Test logout function.', () {
final model = AppSettingViewModel();
final context = MockBuildContext();
model.logout(context);
});

testWidgets("Test logout dialog when logout successful.", (tester) async {
const userLoggedin = false;
when(userConfig.loggedIn).thenAnswer((_) => userLoggedin);
final model = AppSettingViewModel();

final widget = BaseView<AppLanguage>(
onModelReady: (model) => model.initialize(),
builder: (context, langModel, child) {
return MaterialApp(
locale: const Locale('en'),
localizationsDelegates: [
const AppLocalizationsDelegate(isTest: true),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: Scaffold(
body: model.logoutDialog(),
),
navigatorKey: navigationService.navigatorKey,
onGenerateRoute: router.generateRoute,
);
},
);

await tester.pumpWidget(widget);
await tester.pumpAndSettle();

await tester.tap(find.textContaining('Logout'));
await tester.pumpAndSettle();

verify(navigationService.navigatorKey);
});

testWidgets("Test logout dialog when logout unsuccessful.", (tester) async {
final model = AppSettingViewModel();
const userLoggedIn = true;
when(userConfig.loggedIn).thenAnswer((_) => userLoggedIn);

final widget = BaseView<AppLanguage>(
onModelReady: (model) => model.initialize(),
builder: (context, langModel, child) {
return MaterialApp(
locale: const Locale('en'),
localizationsDelegates: [
const AppLocalizationsDelegate(isTest: true),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: Scaffold(
body: model.logoutDialog(),
),
navigatorKey: navigationService.navigatorKey,
onGenerateRoute: router.generateRoute,
);
},
);

await tester.pumpWidget(widget);
await tester.pumpAndSettle();

await tester.tap(find.textContaining('Logout'));
await tester.pumpAndSettle();

verify(navigationService.navigatorKey);
model.logout();
});

test('test for launchWebsite method', () async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:talawa/services/graphql_config.dart';
import 'package:talawa/services/navigation_service.dart';
import 'package:talawa/services/size_config.dart';
import 'package:talawa/utils/app_localization.dart';
import 'package:talawa/view_model/after_auth_view_models/settings_view_models/app_setting_view_model.dart';
import 'package:talawa/view_model/lang_view_model.dart';
import 'package:talawa/view_model/theme_view_model.dart';
import 'package:talawa/views/after_auth_screens/app_settings/app_settings_page.dart';
Expand Down Expand Up @@ -271,7 +272,10 @@ Future<void> main() async {
await tester.pumpWidget(createChangePassScreenDark());
await tester.pumpAndSettle();

final logoutButton = find.textContaining('Logout');
await tester.tap(find.byKey(const Key('Logout')));
await tester.pumpAndSettle();

final logoutButton = find.textContaining('LogOut');
await tester.tap(logoutButton);

unregisterServices();
Expand All @@ -288,5 +292,21 @@ Future<void> main() async {

verify(navigationService.navigatorKey);
});
testWidgets('Test if Logout is unsuccessful.', (tester) async {
final model = AppSettingViewModel();
when(model.logout()).thenThrow(Exception('Test error'));

const userLoggedIn = true;
when(userConfig.loggedIn).thenAnswer((_) => userLoggedIn);

await tester.pumpWidget(createChangePassScreenDark());
await tester.pumpAndSettle();

await tester.tap(find.byKey(const Key('Logout')));
await tester.pumpAndSettle();

final logoutButton = find.textContaining('LogOut');
await tester.tap(logoutButton);
});
});
}

0 comments on commit 6ac0633

Please sign in to comment.