blob: 8e27c39a841b4b9f122597885b6c837fb883ef8c [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 Flutter;
@import XCTest;
@import google_sign_in_ios;
@import google_sign_in_ios.Test;
@import GoogleSignIn;
// OCMock library doesn't generate a valid modulemap.
#import <OCMock/OCMock.h>
@interface FLTGoogleSignInPluginTest : XCTestCase
@property(strong, nonatomic) NSObject<FlutterBinaryMessenger> *mockBinaryMessenger;
@property(strong, nonatomic) NSObject<FlutterPluginRegistrar> *mockPluginRegistrar;
@property(strong, nonatomic) FLTGoogleSignInPlugin *plugin;
@property(strong, nonatomic) id mockSignIn;
@end
@implementation FLTGoogleSignInPluginTest
- (void)setUp {
[super setUp];
self.mockBinaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
self.mockPluginRegistrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar));
id mockSignIn = OCMClassMock([GIDSignIn class]);
self.mockSignIn = mockSignIn;
OCMStub(self.mockPluginRegistrar.messenger).andReturn(self.mockBinaryMessenger);
self.plugin = [[FLTGoogleSignInPlugin alloc] initWithSignIn:mockSignIn];
[FLTGoogleSignInPlugin registerWithRegistrar:self.mockPluginRegistrar];
}
- (void)testSignOut {
FlutterError *error;
[self.plugin signOutWithError:&error];
OCMVerify([self.mockSignIn signOut]);
XCTAssertNil(error);
}
- (void)testDisconnect {
[[self.mockSignIn stub] disconnectWithCallback:[OCMArg invokeBlockWithArgs:[NSNull null], nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin disconnectWithCompletion:^(FlutterError *error) {
XCTAssertNil(error);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testDisconnectIgnoresError {
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeHasNoAuthInKeychain
userInfo:nil];
[[self.mockSignIn stub] disconnectWithCallback:[OCMArg invokeBlockWithArgs:error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"expect result returns true"];
[self.plugin disconnectWithCompletion:^(FlutterError *error) {
XCTAssertNil(error);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
#pragma mark - Init
- (void)testInitNoClientIdError {
// Init plugin without GoogleService-Info.plist.
self.plugin = [[FLTGoogleSignInPlugin alloc] initWithSignIn:self.mockSignIn
withGoogleServiceProperties:nil];
// init call does not provide a clientId.
FSIInitParams *params = [FSIInitParams makeWithScopes:@[]
hostedDomain:nil
clientId:nil
serverClientId:nil];
FlutterError *error;
[self.plugin initializeSignInWithParameters:params error:&error];
XCTAssertEqualObjects(error.code, @"missing-config");
}
- (void)testInitGoogleServiceInfoPlist {
FSIInitParams *params = [FSIInitParams makeWithScopes:@[]
hostedDomain:@"example.com"
clientId:nil
serverClientId:nil];
FlutterError *error;
[self.plugin initializeSignInWithParameters:params error:&error];
XCTAssertNil(error);
// Initialization values used in the next sign in request.
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error){
}];
OCMVerify([self.mockSignIn
signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
// Set in example app GoogleService-Info.plist.
return
[configuration.hostedDomain isEqualToString:@"example.com"] &&
[configuration.clientID
isEqualToString:
@"479882132969-9i9aqik3jfjd7qhci1nqf0bm2g71rm1u.apps.googleusercontent.com"] &&
[configuration.serverClientID isEqualToString:@"YOUR_SERVER_CLIENT_ID"];
}]
presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
hint:nil
additionalScopes:OCMOCK_ANY
callback:OCMOCK_ANY]);
}
- (void)testInitDynamicClientIdNullDomain {
// Init plugin without GoogleService-Info.plist.
self.plugin = [[FLTGoogleSignInPlugin alloc] initWithSignIn:self.mockSignIn
withGoogleServiceProperties:nil];
FSIInitParams *params = [FSIInitParams makeWithScopes:@[]
hostedDomain:nil
clientId:@"mockClientId"
serverClientId:nil];
FlutterError *error;
[self.plugin initializeSignInWithParameters:params error:&error];
XCTAssertNil(error);
// Initialization values used in the next sign in request.
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error){
}];
OCMVerify([self.mockSignIn
signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
return configuration.hostedDomain == nil &&
[configuration.clientID isEqualToString:@"mockClientId"];
}]
presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
hint:nil
additionalScopes:OCMOCK_ANY
callback:OCMOCK_ANY]);
}
- (void)testInitDynamicServerClientIdNullDomain {
FSIInitParams *params = [FSIInitParams makeWithScopes:@[]
hostedDomain:nil
clientId:nil
serverClientId:@"mockServerClientId"];
FlutterError *error;
[self.plugin initializeSignInWithParameters:params error:&error];
XCTAssertNil(error);
// Initialization values used in the next sign in request.
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error){
}];
OCMVerify([self.mockSignIn
signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
return configuration.hostedDomain == nil &&
[configuration.serverClientID isEqualToString:@"mockServerClientId"];
}]
presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
hint:nil
additionalScopes:OCMOCK_ANY
callback:OCMOCK_ANY]);
}
#pragma mark - Is signed in
- (void)testIsNotSignedIn {
OCMStub([self.mockSignIn hasPreviousSignIn]).andReturn(NO);
FlutterError *error;
NSNumber *result = [self.plugin isSignedInWithError:&error];
XCTAssertNil(error);
XCTAssertFalse(result.boolValue);
}
- (void)testIsSignedIn {
OCMStub([self.mockSignIn hasPreviousSignIn]).andReturn(YES);
FlutterError *error;
NSNumber *result = [self.plugin isSignedInWithError:&error];
XCTAssertNil(error);
XCTAssertTrue(result.boolValue);
}
#pragma mark - Sign in silently
- (void)testSignInSilently {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([mockUser userID]).andReturn(@"mockID");
[[self.mockSignIn stub]
restorePreviousSignInWithCallback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin signInSilentlyWithCompletion:^(FSIUserData *user, FlutterError *error) {
XCTAssertNil(error);
XCTAssertNotNil(user);
XCTAssertNil(user.displayName);
XCTAssertNil(user.email);
XCTAssertEqualObjects(user.userId, @"mockID");
XCTAssertNil(user.photoUrl);
XCTAssertNil(user.serverAuthCode);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testSignInSilentlyWithError {
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeHasNoAuthInKeychain
userInfo:nil];
[[self.mockSignIn stub]
restorePreviousSignInWithCallback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin signInSilentlyWithCompletion:^(FSIUserData *user, FlutterError *error) {
XCTAssertNil(user);
XCTAssertEqualObjects(error.code, @"sign_in_required");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
#pragma mark - Sign in
- (void)testSignIn {
id mockUser = OCMClassMock([GIDGoogleUser class]);
id mockUserProfile = OCMClassMock([GIDProfileData class]);
OCMStub([mockUserProfile name]).andReturn(@"mockDisplay");
OCMStub([mockUserProfile email]).andReturn(@"mock@example.com");
OCMStub([mockUserProfile hasImage]).andReturn(YES);
OCMStub([mockUserProfile imageURLWithDimension:1337])
.andReturn([NSURL URLWithString:@"https://example.com/profile.png"]);
OCMStub([mockUser profile]).andReturn(mockUserProfile);
OCMStub([mockUser userID]).andReturn(@"mockID");
OCMStub([mockUser serverAuthCode]).andReturn(@"mockAuthCode");
[[self.mockSignIn expect]
signInWithConfiguration:[OCMArg checkWithBlock:^BOOL(GIDConfiguration *configuration) {
return [configuration.clientID
isEqualToString:
@"479882132969-9i9aqik3jfjd7qhci1nqf0bm2g71rm1u.apps.googleusercontent.com"];
}]
presentingViewController:[OCMArg isKindOfClass:[FlutterViewController class]]
hint:nil
additionalScopes:@[]
callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error) {
XCTAssertNil(error);
XCTAssertEqualObjects(user.displayName, @"mockDisplay");
XCTAssertEqualObjects(user.email, @"mock@example.com");
XCTAssertEqualObjects(user.userId, @"mockID");
XCTAssertEqualObjects(user.photoUrl, @"https://example.com/profile.png");
XCTAssertEqualObjects(user.serverAuthCode, @"mockAuthCode");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
OCMVerifyAll(self.mockSignIn);
}
- (void)testSignInWithInitializedScopes {
FlutterError *error;
[self.plugin
initializeSignInWithParameters:[FSIInitParams makeWithScopes:@[ @"initial1", @"initial2" ]
hostedDomain:nil
clientId:nil
serverClientId:nil]
error:&error];
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([mockUser userID]).andReturn(@"mockID");
[[self.mockSignIn expect]
signInWithConfiguration:OCMOCK_ANY
presentingViewController:OCMOCK_ANY
hint:nil
additionalScopes:[OCMArg checkWithBlock:^BOOL(NSArray<NSString *> *scopes) {
return [[NSSet setWithArray:scopes]
isEqualToSet:[NSSet setWithObjects:@"initial1", @"initial2", nil]];
}]
callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error) {
XCTAssertNil(error);
XCTAssertEqualObjects(user.userId, @"mockID");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
OCMVerifyAll(self.mockSignIn);
}
- (void)testSignInAlreadyGranted {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([mockUser userID]).andReturn(@"mockID");
[[self.mockSignIn stub]
signInWithConfiguration:OCMOCK_ANY
presentingViewController:OCMOCK_ANY
hint:nil
additionalScopes:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeScopesAlreadyGranted
userInfo:nil];
[[self.mockSignIn stub] addScopes:OCMOCK_ANY
presentingViewController:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error) {
XCTAssertNil(error);
XCTAssertEqualObjects(user.userId, @"mockID");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testSignInError {
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeCanceled
userInfo:nil];
[[self.mockSignIn stub]
signInWithConfiguration:OCMOCK_ANY
presentingViewController:OCMOCK_ANY
hint:nil
additionalScopes:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *error) {
XCTAssertNil(user);
XCTAssertEqualObjects(error.code, @"sign_in_canceled");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testSignInException {
OCMExpect([self.mockSignIn signInWithConfiguration:OCMOCK_ANY
presentingViewController:OCMOCK_ANY
hint:OCMOCK_ANY
additionalScopes:OCMOCK_ANY
callback:OCMOCK_ANY])
.andThrow([NSException exceptionWithName:@"MockName" reason:@"MockReason" userInfo:nil]);
__block FlutterError *error;
XCTAssertThrows(
[self.plugin signInWithCompletion:^(FSIUserData *user, FlutterError *signInError) {
XCTAssertNil(user);
error = signInError;
}]);
XCTAssertEqualObjects(error.code, @"google_sign_in");
XCTAssertEqualObjects(error.message, @"MockReason");
XCTAssertEqualObjects(error.details, @"MockName");
}
#pragma mark - Get tokens
- (void)testGetTokens {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
OCMStub([mockAuthentication idToken]).andReturn(@"mockIdToken");
OCMStub([mockAuthentication accessToken]).andReturn(@"mockAccessToken");
[[mockAuthentication stub]
doWithFreshTokens:[OCMArg invokeBlockWithArgs:mockAuthentication, [NSNull null], nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin getAccessTokenWithCompletion:^(FSITokenData *token, FlutterError *error) {
XCTAssertNil(error);
XCTAssertEqualObjects(token.idToken, @"mockIdToken");
XCTAssertEqualObjects(token.accessToken, @"mockAccessToken");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testGetTokensNoAuthKeychainError {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeHasNoAuthInKeychain
userInfo:nil];
[[mockAuthentication stub]
doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin getAccessTokenWithCompletion:^(FSITokenData *token, FlutterError *error) {
XCTAssertNil(token);
XCTAssertEqualObjects(error.code, @"sign_in_required");
XCTAssertEqualObjects(error.message, kGIDSignInErrorDomain);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testGetTokensCancelledError {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeCanceled
userInfo:nil];
[[mockAuthentication stub]
doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin getAccessTokenWithCompletion:^(FSITokenData *token, FlutterError *error) {
XCTAssertNil(token);
XCTAssertEqualObjects(error.code, @"sign_in_canceled");
XCTAssertEqualObjects(error.message, kGIDSignInErrorDomain);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testGetTokensURLError {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorTimedOut userInfo:nil];
[[mockAuthentication stub]
doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin getAccessTokenWithCompletion:^(FSITokenData *token, FlutterError *error) {
XCTAssertNil(token);
XCTAssertEqualObjects(error.code, @"network_error");
XCTAssertEqualObjects(error.message, NSURLErrorDomain);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testGetTokensUnknownError {
id mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
id mockAuthentication = OCMClassMock([GIDAuthentication class]);
NSError *error = [NSError errorWithDomain:@"BogusDomain" code:42 userInfo:nil];
[[mockAuthentication stub]
doWithFreshTokens:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
OCMStub([mockUser authentication]).andReturn(mockAuthentication);
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin getAccessTokenWithCompletion:^(FSITokenData *token, FlutterError *error) {
XCTAssertNil(token);
XCTAssertEqualObjects(error.code, @"sign_in_failed");
XCTAssertEqualObjects(error.message, @"BogusDomain");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
#pragma mark - Request scopes
- (void)testRequestScopesResultErrorIfNotSignedIn {
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeNoCurrentUser
userInfo:nil];
[[self.mockSignIn stub] addScopes:@[ @"mockScope1" ]
presentingViewController:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin requestScopes:@[ @"mockScope1" ]
completion:^(NSNumber *success, FlutterError *error) {
XCTAssertNil(success);
XCTAssertEqualObjects(error.code, @"sign_in_required");
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testRequestScopesIfNoMissingScope {
NSError *error = [NSError errorWithDomain:kGIDSignInErrorDomain
code:kGIDSignInErrorCodeScopesAlreadyGranted
userInfo:nil];
[[self.mockSignIn stub] addScopes:@[ @"mockScope1" ]
presentingViewController:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin requestScopes:@[ @"mockScope1" ]
completion:^(NSNumber *success, FlutterError *error) {
XCTAssertNil(error);
XCTAssertTrue(success.boolValue);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testRequestScopesWithUnknownError {
NSError *error = [NSError errorWithDomain:@"BogusDomain" code:42 userInfo:nil];
[[self.mockSignIn stub] addScopes:@[ @"mockScope1" ]
presentingViewController:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:[NSNull null], error, nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin requestScopes:@[ @"mockScope1" ]
completion:^(NSNumber *success, FlutterError *error) {
XCTAssertNil(error);
XCTAssertFalse(success.boolValue);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testRequestScopesException {
OCMExpect([self.mockSignIn addScopes:@[] presentingViewController:OCMOCK_ANY callback:OCMOCK_ANY])
.andThrow([NSException exceptionWithName:@"MockName" reason:@"MockReason" userInfo:nil]);
[self.plugin requestScopes:@[]
completion:^(NSNumber *success, FlutterError *error) {
XCTAssertNil(success);
XCTAssertEqualObjects(error.code, @"request_scopes");
XCTAssertEqualObjects(error.message, @"MockReason");
XCTAssertEqualObjects(error.details, @"MockName");
}];
}
- (void)testRequestScopesReturnsFalseIfOnlySubsetGranted {
GIDGoogleUser *mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
NSArray<NSString *> *requestedScopes = @[ @"mockScope1", @"mockScope2" ];
// Only grant one of the two requested scopes.
OCMStub(mockUser.grantedScopes).andReturn(@[ @"mockScope1" ]);
[[self.mockSignIn stub] addScopes:requestedScopes
presentingViewController:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin requestScopes:requestedScopes
completion:^(NSNumber *success, FlutterError *error) {
XCTAssertNil(error);
XCTAssertFalse(success.boolValue);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
- (void)testRequestsInitializedScopes {
FSIInitParams *params = [FSIInitParams makeWithScopes:@[ @"initial1", @"initial2" ]
hostedDomain:nil
clientId:nil
serverClientId:nil];
FlutterError *error;
[self.plugin initializeSignInWithParameters:params error:&error];
XCTAssertNil(error);
// Include one of the initially requested scopes.
NSArray<NSString *> *addedScopes = @[ @"initial1", @"addScope1", @"addScope2" ];
[self.plugin requestScopes:addedScopes
completion:^(NSNumber *success, FlutterError *error){
}];
// All four scopes are requested.
[[self.mockSignIn verify]
addScopes:[OCMArg checkWithBlock:^BOOL(NSArray<NSString *> *scopes) {
return [[NSSet setWithArray:scopes]
isEqualToSet:[NSSet setWithObjects:@"initial1", @"initial2",
@"addScope1", @"addScope2", nil]];
}]
presentingViewController:OCMOCK_ANY
callback:OCMOCK_ANY];
}
- (void)testRequestScopesReturnsTrueIfGranted {
GIDGoogleUser *mockUser = OCMClassMock([GIDGoogleUser class]);
OCMStub([self.mockSignIn currentUser]).andReturn(mockUser);
NSArray<NSString *> *requestedScopes = @[ @"mockScope1", @"mockScope2" ];
// Grant both of the requested scopes.
OCMStub(mockUser.grantedScopes).andReturn(requestedScopes);
[[self.mockSignIn stub] addScopes:requestedScopes
presentingViewController:OCMOCK_ANY
callback:[OCMArg invokeBlockWithArgs:mockUser, [NSNull null], nil]];
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
[self.plugin requestScopes:requestedScopes
completion:^(NSNumber *success, FlutterError *error) {
XCTAssertNil(error);
XCTAssertTrue(success.boolValue);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:5.0 handler:nil];
}
@end