Skip to content

Commit

Permalink
add login view model unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Ida631 committed Nov 29, 2024
1 parent 613b063 commit 0d7cdc4
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 18 deletions.
16 changes: 0 additions & 16 deletions lib/presentation/settings/viewModels/login_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,6 @@ class LoginViewModel extends ChangeNotifier {
}

// Function to handle Google Sign-Out
Future<void> signOut() async {
final GoogleSignIn googleSignIn;
if (kIsWeb) {
googleSignIn = GoogleSignIn(
clientId: GOOGLE_SIGNIN_CLIENT_ID_WEB,
scopes: <String>['email', 'openid'],
);
} else {
googleSignIn = GoogleSignIn(
scopes: <String>['email', 'openid'],
);
}

await googleSignIn.signOut();
notifyListeners();
}

Future<String> syncUser(String? displayName, String email, String? photoUrl) async {
final accessToken = await authUseCase.syncUser(displayName, email, photoUrl);
Expand Down
25 changes: 25 additions & 0 deletions packages/domain/lib/mocks/auth_usecase_mock.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:mockito/mockito.dart';

import '../usecases/auth_usecase.dart';

class MockAuthUseCase extends Mock implements AuthUseCase {
@override
Future<String> login(String email, String password) =>
super.noSuchMethod(Invocation.method(#login, [email, password]),
returnValue: Future.value(''),
returnValueForMissingStub: Future.value(''));

@override
Future<bool> validateGoogleToken(String idToken) =>
super.noSuchMethod(Invocation.method(#validateGoogleToken, [idToken]),
returnValue: Future.value(true),
returnValueForMissingStub: Future.value(true));

@override
Future<String> syncUser(String? displayName, String email, String? photoUrl) =>
super.noSuchMethod(Invocation.method(#syncUser, [displayName, email, photoUrl]),
returnValue: Future.value(''),
returnValueForMissingStub: Future.value(''));


}
1 change: 1 addition & 0 deletions packages/domain/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies:
sdk: flutter
uuid: ^4.5.1
composite_calculator: ^1.0.1
mockito: ^5.4.0
infrastructure:
path: ../infrastructure

Expand Down
176 changes: 174 additions & 2 deletions test/login_view_model_test.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,181 @@
import 'package:domain/mocks/auth_usecase_mock.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:swiftcomp/presentation/settings/viewModels/login_view_model.dart';

void main() {
group('LoginViewModel Tests', () {
test('false', () async {
expect(false, false);
group('togglePasswordVisibility', () {
test('should toggle obscureText and notify listeners', () {

final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

// Initially true
expect(loginViewModel.obscureText, true);

// Toggle
loginViewModel.togglePasswordVisibility();
expect(loginViewModel.obscureText, false);

// Toggle back
loginViewModel.togglePasswordVisibility();
expect(loginViewModel.obscureText, true);
});
});
});


group('updateButtonState', () {

final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

test('should enable button when email and password are valid', () {
loginViewModel.updateButtonState('[email protected]', 'password123');
expect(loginViewModel.isButtonEnabled, true);
});

test('should disable button when email is invalid', () {
loginViewModel.updateButtonState('invalid-email', 'password123');
expect(loginViewModel.isButtonEnabled, false);
});

test('should disable button when password is empty', () {
loginViewModel.updateButtonState('[email protected]', '');
expect(loginViewModel.isButtonEnabled, false);
});

test('should disable button when password length is less than 6', () {
loginViewModel.updateButtonState('[email protected]', '12345');
expect(loginViewModel.isButtonEnabled, false);
});
});

group('login', () {
test('should set isLoading to true during login process', () async {
final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

const email = '[email protected]';
const password = 'password123';
when(mockAuthUseCase.login(email, password)).thenAnswer((_) async => 'accessToken');

final future = loginViewModel.login(email, password);

expect(loginViewModel.isLoading, true);
await future;
expect(loginViewModel.isLoading, false);
});

test('should return access token on successful login', () async {

final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

const email = '[email protected]';
const password = 'password123';
const accessToken = 'accessToken';
when(mockAuthUseCase.login(email, password)).thenAnswer((_) async => accessToken);

final result = await loginViewModel.login(email, password);
expect(result, accessToken);
expect(loginViewModel.errorMessage, null);
});

test('should set error message on login failure', () async {

final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

const email = '[email protected]';
const password = 'password123';
when(mockAuthUseCase.login(email, password)).thenThrow(Exception('Login error'));

final result = await loginViewModel.login(email, password);
expect(result, null);
expect(loginViewModel.errorMessage, 'Login failed: Exception: Login error');
});
});

group('validateGoogleToken', () {
test('should return true when token validation is successful', () async {
final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();

const idToken = "1234567";

when(mockAuthUseCase.validateGoogleToken(idToken)).thenAnswer((_) async => true);

final result = await mockAuthUseCase.validateGoogleToken(idToken);

expect(result, true);
verify(mockAuthUseCase.validateGoogleToken(idToken)).called(1);
});

test('should return false when token validation fails', () async {
final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();

const idToken = "1234567";

when(mockAuthUseCase.validateGoogleToken(idToken)).thenAnswer((_) async => false);

final result = await mockAuthUseCase.validateGoogleToken(idToken);

expect(result, false);
verify(mockAuthUseCase.validateGoogleToken(idToken)).called(1);
});

test('should throw an exception on error during token validation', () async {
final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();

const idToken = "1234567";

when(mockAuthUseCase.validateGoogleToken(idToken)).thenThrow(Exception('Validation error'));

expect(
() async => await mockAuthUseCase.validateGoogleToken(idToken),
throwsA(isA<Exception>()),
);
verify(mockAuthUseCase.validateGoogleToken(idToken)).called(1);
});
});

group('syncUser', () {
test('should return access token when user data is synced successfully', () async {
final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

const displayName = 'Test User';
const email = '[email protected]';
const photoUrl = 'http://example.com/photo.jpg';

when(mockAuthUseCase.syncUser(displayName, email, photoUrl))
.thenAnswer((_) async => 'mockAccessToken');

final result = await loginViewModel.syncUser(displayName, email, photoUrl);

expect(result, 'mockAccessToken');
verify(mockAuthUseCase.syncUser(displayName, email, photoUrl)).called(1);
});

test('should throw an exception when syncUser fails', () async {
final MockAuthUseCase mockAuthUseCase = MockAuthUseCase();
final LoginViewModel loginViewModel = LoginViewModel(authUseCase: mockAuthUseCase);

const displayName = 'Test User';
const email = '[email protected]';
const photoUrl = 'http://example.com/photo.jpg';

when(mockAuthUseCase.syncUser(displayName, email, photoUrl))
.thenThrow(Exception('Sync failed'));

expect(
() async => await loginViewModel.syncUser(displayName, email, photoUrl),
throwsA(isA<Exception>()),
);
verify(mockAuthUseCase.syncUser(displayName, email, photoUrl)).called(1);
});
});


}

0 comments on commit 0d7cdc4

Please sign in to comment.