| // Copyright 2019 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:flutter_dashboard/service/google_authentication.dart'; |
| |
| import 'package:flutter_test/flutter_test.dart'; |
| import 'package:google_sign_in/google_sign_in.dart'; |
| import 'package:mockito/mockito.dart'; |
| |
| import '../utils/fake_google_account.dart'; |
| import '../utils/mocks.dart'; |
| |
| void main() { |
| group('GoogleSignInService not signed in', () { |
| late GoogleSignInService authService; |
| GoogleSignIn? mockSignIn; |
| |
| setUp(() { |
| mockSignIn = MockGoogleSignIn(); |
| when(mockSignIn!.onCurrentUserChanged).thenAnswer((_) => const Stream<GoogleSignInAccount>.empty()); |
| when(mockSignIn!.isSignedIn()).thenAnswer((_) => Future<bool>.value(false)); |
| when(mockSignIn!.signInSilently()).thenAnswer((_) => Future<GoogleSignInAccount?>.value(null)); |
| authService = GoogleSignInService(googleSignIn: mockSignIn); |
| }); |
| |
| tearDown(() { |
| clearInteractions(mockSignIn); |
| }); |
| |
| test('not authenticated', () async { |
| expect(authService.isAuthenticated, false); |
| }); |
| |
| test('no user information', () { |
| expect(authService.user, null); |
| }); |
| |
| test('sign in silently called', () async { |
| verify(mockSignIn!.signInSilently()).called(1); |
| }); |
| }); |
| |
| group('GoogleSignInService sign in', () { |
| late GoogleSignInService authService; |
| late GoogleSignIn mockSignIn; |
| late StreamController<GoogleSignInAccount> userChanged; |
| |
| final GoogleSignInAccount testAccount = FakeGoogleSignInAccount(); |
| |
| // Pushes a change to the userChanged Stream controller that we can await for it to propagate. |
| Future<void> pushUserChanged(GoogleSignInAccount? account) { |
| userChanged.add(testAccount); |
| // Let the change to the stream propagate to the object... |
| return Future<void>.delayed(Duration.zero); |
| } |
| |
| setUp(() { |
| userChanged = StreamController<GoogleSignInAccount>.broadcast(); |
| |
| mockSignIn = MockGoogleSignIn(); |
| when(mockSignIn.signIn()).thenAnswer((_) => Future<GoogleSignInAccount>.value(testAccount)); |
| when(mockSignIn.signInSilently()).thenAnswer((_) => Future<GoogleSignInAccount>.value(testAccount)); |
| when(mockSignIn.currentUser).thenReturn(testAccount); |
| when(mockSignIn.isSignedIn()).thenAnswer((_) => Future<bool>.value(true)); |
| when(mockSignIn.onCurrentUserChanged).thenAnswer((_) => userChanged.stream); |
| |
| authService = GoogleSignInService(googleSignIn: mockSignIn); |
| }); |
| |
| test('is authenticated after sign in from Google Sign In button', () async { |
| await pushUserChanged(testAccount); |
| |
| expect(authService.isAuthenticated, isTrue); |
| expect(authService.user, testAccount); |
| }); |
| |
| test('there is user information after successful sign in', () async { |
| await pushUserChanged(testAccount); |
| |
| expect(authService.user, isNotNull); |
| expect(authService.user!.displayName, 'Dr. Test'); |
| expect(authService.user!.email, 'test@flutter.dev'); |
| expect(authService.user!.id, 'test123'); |
| expect( |
| authService.user!.photoUrl, |
| 'https://lh3.googleusercontent.com/-ukEAtRyRhw8/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3rfhID9XACtdb9q_xK43VSXQvBV11Q.CMID', |
| ); |
| }); |
| |
| test('signIn method also works, but should be deprecated!', () async { |
| await authService.signIn(); |
| |
| expect(authService.isAuthenticated, true); |
| expect(authService.user, testAccount); |
| }); |
| |
| test('id token available with logged in user', () async { |
| final GoogleSignInAccount testAccountWithAuthentication = FakeGoogleSignInAccount() |
| ..authentication = Future<GoogleSignInAuthentication>.value(FakeGoogleSignInAuthentication()); |
| authService.user = testAccountWithAuthentication; |
| |
| expect(await authService.idToken, 'id123'); |
| }); |
| |
| test('is not authenticated after failure in sign in', () async { |
| when(mockSignIn.signInSilently()).thenAnswer((_) => Future<GoogleSignInAccount?>.value(null)); |
| when(mockSignIn.signIn()).thenAnswer((_) => Future<GoogleSignInAccount?>.value(null)); |
| |
| await authService.signIn(); |
| |
| expect(authService.user, null); |
| }); |
| |
| test('clearUser removes the user without calling signOut', () async { |
| await pushUserChanged(testAccount); |
| |
| expect(authService.isAuthenticated, isTrue); |
| expect(authService.user, testAccount); |
| |
| await authService.clearUser(); |
| |
| expect(authService.isAuthenticated, isFalse); |
| expect(authService.user, isNull); |
| verifyNever(mockSignIn.signOut()); |
| }); |
| }); |
| } |
| |
| class FakeGoogleSignInAuthentication implements GoogleSignInAuthentication { |
| @override |
| String get accessToken => 'access123'; |
| |
| @override |
| String get idToken => 'id123'; |
| |
| @override |
| String get serverAuthCode => 'serverAuth123'; |
| } |