blob: 0837f6d5d02cb368c26222fec5b4849a03026379 [file] [log] [blame]
// Copyright 2013 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 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:google_sign_in_platform_interface/src/utils.dart';
const Map<String, String> kUserData = <String, String>{
'email': 'john.doe@gmail.com',
'id': '8162538176523816253123',
'photoUrl': 'https://lh5.googleusercontent.com/photo.jpg',
'displayName': 'John Doe',
'idToken': '123',
'serverAuthCode': '789',
};
const Map<dynamic, dynamic> kTokenData = <String, dynamic>{
'idToken': '123',
'accessToken': '456',
'serverAuthCode': '789',
};
const Map<String, dynamic> kDefaultResponses = <String, dynamic>{
'init': null,
'signInSilently': kUserData,
'signIn': kUserData,
'signOut': null,
'disconnect': null,
'isSignedIn': true,
'getTokens': kTokenData,
'requestScopes': true,
};
final GoogleSignInUserData? kUser = getUserDataFromMap(kUserData);
final GoogleSignInTokenData kToken =
getTokenDataFromMap(kTokenData as Map<String, dynamic>);
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('$MethodChannelGoogleSignIn', () {
final MethodChannelGoogleSignIn googleSignIn = MethodChannelGoogleSignIn();
final MethodChannel channel = googleSignIn.channel;
final List<MethodCall> log = <MethodCall>[];
late Map<String, dynamic>
responses; // Some tests mutate some kDefaultResponses
setUp(() {
responses = Map<String, dynamic>.from(kDefaultResponses);
_ambiguate(TestDefaultBinaryMessengerBinding.instance)!
.defaultBinaryMessenger
.setMockMethodCallHandler(channel, (MethodCall methodCall) {
log.add(methodCall);
final dynamic response = responses[methodCall.method];
if (response != null && response is Exception) {
return Future<dynamic>.error('$response');
}
return Future<dynamic>.value(response);
});
log.clear();
});
test('signInSilently transforms platform data to GoogleSignInUserData',
() async {
final dynamic response = await googleSignIn.signInSilently();
expect(response, kUser);
});
test('signInSilently Exceptions -> throws', () async {
responses['signInSilently'] = Exception('Not a user');
expect(googleSignIn.signInSilently(),
throwsA(isInstanceOf<PlatformException>()));
});
test('signIn transforms platform data to GoogleSignInUserData', () async {
final dynamic response = await googleSignIn.signIn();
expect(response, kUser);
});
test('signIn Exceptions -> throws', () async {
responses['signIn'] = Exception('Not a user');
expect(googleSignIn.signIn(), throwsA(isInstanceOf<PlatformException>()));
});
test('getTokens transforms platform data to GoogleSignInTokenData',
() async {
final dynamic response = await googleSignIn.getTokens(
email: 'example@example.com', shouldRecoverAuth: false);
expect(response, kToken);
expect(
log[0],
isMethodCall('getTokens', arguments: <String, dynamic>{
'email': 'example@example.com',
'shouldRecoverAuth': false,
}));
});
test('Other functions pass through arguments to the channel', () async {
final Map<void Function(), Matcher> tests = <void Function(), Matcher>{
() {
googleSignIn.init(
hostedDomain: 'example.com',
scopes: <String>['two', 'scopes'],
signInOption: SignInOption.games,
clientId: 'fakeClientId');
}: isMethodCall('init', arguments: <String, dynamic>{
'hostedDomain': 'example.com',
'scopes': <String>['two', 'scopes'],
'signInOption': 'SignInOption.games',
'clientId': 'fakeClientId',
'serverClientId': null,
'forceCodeForRefreshToken': false,
}),
() {
googleSignIn.getTokens(
email: 'example@example.com', shouldRecoverAuth: false);
}: isMethodCall('getTokens', arguments: <String, dynamic>{
'email': 'example@example.com',
'shouldRecoverAuth': false,
}),
() {
googleSignIn.clearAuthCache(token: 'abc');
}: isMethodCall('clearAuthCache', arguments: <String, dynamic>{
'token': 'abc',
}),
() {
googleSignIn.requestScopes(<String>['newScope', 'anotherScope']);
}: isMethodCall('requestScopes', arguments: <String, dynamic>{
'scopes': <String>['newScope', 'anotherScope'],
}),
googleSignIn.signOut: isMethodCall('signOut', arguments: null),
googleSignIn.disconnect: isMethodCall('disconnect', arguments: null),
googleSignIn.isSignedIn: isMethodCall('isSignedIn', arguments: null),
};
for (final void Function() f in tests.keys) {
f();
}
expect(log, tests.values);
});
test('initWithParams passes through arguments to the channel', () async {
await googleSignIn.initWithParams(const SignInInitParameters(
hostedDomain: 'example.com',
scopes: <String>['two', 'scopes'],
signInOption: SignInOption.games,
clientId: 'fakeClientId',
serverClientId: 'fakeServerClientId',
forceCodeForRefreshToken: true));
expect(log, <Matcher>[
isMethodCall('init', arguments: <String, dynamic>{
'hostedDomain': 'example.com',
'scopes': <String>['two', 'scopes'],
'signInOption': 'SignInOption.games',
'clientId': 'fakeClientId',
'serverClientId': 'fakeServerClientId',
'forceCodeForRefreshToken': true,
}),
]);
});
});
}
/// This allows a value of type T or T? to be treated as a value of type T?.
///
/// We use this so that APIs that have become non-nullable can still be used
/// with `!` and `?` on the stable branch.
T? _ambiguate<T>(T? value) => value;