Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/google_sign_in/google_sign_in_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.2.6

* Switches to an internal method channel, rather than the default.

## 5.2.5

* Splits from `video_player` as a federated implementation.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

/** Google sign-in plugin for Flutter. */
public class GoogleSignInPlugin implements MethodCallHandler, FlutterPlugin, ActivityAware {
private static final String CHANNEL_NAME = "plugins.flutter.io/google_sign_in";
private static final String CHANNEL_NAME = "plugins.flutter.io/google_sign_in_android";

private static final String METHOD_INIT = "init";
private static final String METHOD_SIGN_IN_SILENTLY = "signInSilently";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ void main() {
final GoogleSignInPlatform signIn = GoogleSignInPlatform.instance;
expect(signIn, isNotNull);
});

testWidgets('Method channel handler is present', (WidgetTester tester) async {
// isSignedIn can be called without initialization, so use it to validate
// that the native method handler is present (e.g., that the channel name
// is correct).
final GoogleSignInPlatform signIn = GoogleSignInPlatform.instance;
await expectLater(signIn.isSignedIn(), completes);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// 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 'dart:async';

import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter/services.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';

import 'src/utils.dart';

/// Android implementation of [GoogleSignInPlatform].
class GoogleSignInAndroid extends GoogleSignInPlatform {
/// This is only exposed for test purposes. It shouldn't be used by clients of
/// the plugin as it may break or change at any time.
@visibleForTesting
MethodChannel channel =
const MethodChannel('plugins.flutter.io/google_sign_in_android');

/// Registers this class as the default instance of [GoogleSignInPlatform].
static void registerWith() {
GoogleSignInPlatform.instance = GoogleSignInAndroid();
}

@override
Future<void> init({
List<String> scopes = const <String>[],
SignInOption signInOption = SignInOption.standard,
String? hostedDomain,
String? clientId,
}) {
return channel.invokeMethod<void>('init', <String, dynamic>{
'signInOption': signInOption.toString(),
'scopes': scopes,
'hostedDomain': hostedDomain,
'clientId': clientId,
});
}

@override
Future<GoogleSignInUserData?> signInSilently() {
return channel
.invokeMapMethod<String, dynamic>('signInSilently')
.then(getUserDataFromMap);
}

@override
Future<GoogleSignInUserData?> signIn() {
return channel
.invokeMapMethod<String, dynamic>('signIn')
.then(getUserDataFromMap);
}

@override
Future<GoogleSignInTokenData> getTokens(
{required String email, bool? shouldRecoverAuth = true}) {
return channel
.invokeMapMethod<String, dynamic>('getTokens', <String, dynamic>{
'email': email,
'shouldRecoverAuth': shouldRecoverAuth,
}).then((Map<String, dynamic>? result) => getTokenDataFromMap(result!));
}

@override
Future<void> signOut() {
return channel.invokeMapMethod<String, dynamic>('signOut');
}

@override
Future<void> disconnect() {
return channel.invokeMapMethod<String, dynamic>('disconnect');
}

@override
Future<bool> isSignedIn() async {
return (await channel.invokeMethod<bool>('isSignedIn'))!;
}

@override
Future<void> clearAuthCache({String? token}) {
return channel.invokeMethod<void>(
'clearAuthCache',
<String, String?>{'token': token},
);
}

@override
Future<bool> requestScopes(List<String> scopes) async {
return (await channel.invokeMethod<bool>(
'requestScopes',
<String, List<String>>{'scopes': scopes},
))!;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';

/// Converts user data coming from native code into the proper platform interface type.
GoogleSignInUserData? getUserDataFromMap(Map<String, dynamic>? data) {
if (data == null) {
return null;
}
return GoogleSignInUserData(
email: data['email']! as String,
id: data['id']! as String,
displayName: data['displayName'] as String?,
photoUrl: data['photoUrl'] as String?,
idToken: data['idToken'] as String?,
serverAuthCode: data['serverAuthCode'] as String?);
}

/// Converts token data coming from native code into the proper platform interface type.
GoogleSignInTokenData getTokenDataFromMap(Map<String, dynamic> data) {
return GoogleSignInTokenData(
idToken: data['idToken'] as String?,
accessToken: data['accessToken'] as String?,
serverAuthCode: data['serverAuthCode'] as String?,
);
}
5 changes: 3 additions & 2 deletions packages/google_sign_in/google_sign_in_android/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@ name: google_sign_in_android
description: Android implementation of the google_sign_in plugin.
repository: https://github.com/flutter/plugins/tree/main/packages/google_sign_in/google_sign_in_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22
version: 5.2.5
version: 5.2.6

environment:
sdk: ">=2.14.0 <3.0.0"
flutter: ">=2.5.0"
flutter: ">=2.8.0"

flutter:
plugin:
implements: google_sign_in
platforms:
android:
dartPluginClass: GoogleSignInAndroid
package: io.flutter.plugins.googlesignin
pluginClass: GoogleSignInPlugin

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// 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_android/google_sign_in_android.dart';
import 'package:google_sign_in_android/src/utils.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.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();

final GoogleSignInAndroid googleSignIn = GoogleSignInAndroid();
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);
channel.setMockMethodCallHandler((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('registered instance', () {
GoogleSignInAndroid.registerWith();
expect(GoogleSignInPlatform.instance, isA<GoogleSignInAndroid>());
});

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<Function, Matcher> tests = <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',
}),
() {
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 Function f in tests.keys) {
f();
}

expect(log, tests.values);
});
}
4 changes: 4 additions & 0 deletions packages/google_sign_in/google_sign_in_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.2.6

* Switches to an internal method channel, rather than the default.

## 5.2.5

* Splits from `video_player` as a federated implementation.
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ void main() {
final GoogleSignInPlatform signIn = GoogleSignInPlatform.instance;
expect(signIn, isNotNull);
});

testWidgets('Method channel handler is present', (WidgetTester tester) async {
// isSignedIn can be called without initialization, so use it to validate
// that the native method handler is present (e.g., that the channel name
// is correct).
final GoogleSignInPlatform signIn = GoogleSignInPlatform.instance;
await expectLater(signIn.isSignedIn(), completes);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,35 +73,8 @@ - (void)testDisconnect {
OCMVerify([self.mockSignIn disconnect]);
}

- (void)testClearAuthCache {
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"clearAuthCache"
arguments:nil];

XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin handleMethodCall:methodCall
result:^(id result) {
XCTAssertNil(result);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}

#pragma mark - Init

- (void)testInitGamesSignInUnsupported {
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"init"
arguments:@{@"signInOption" : @"SignInOption.games"}];

XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin handleMethodCall:methodCall
result:^(FlutterError *result) {
XCTAssertEqualObjects(result.code, @"unsupported-options");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}

- (void)testInitGoogleServiceInfoPlist {
FlutterMethodCall *methodCall = [FlutterMethodCall
methodCallWithMethodName:@"init"
Expand Down
Loading