SignInWithGameCenterTests.swift 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. import Combine
  16. import XCTest
  17. import FirebaseAuth
  18. class SignInWithGameCenterTests: XCTestCase {
  19. override class func setUp() {
  20. FirebaseApp.configureForTests()
  21. }
  22. override class func tearDown() {
  23. FirebaseApp.app()?.delete { success in
  24. if success {
  25. print("Shut down app successfully.")
  26. } else {
  27. print("💥 There was a problem when shutting down the app..")
  28. }
  29. }
  30. }
  31. fileprivate static let expectedAPIURL =
  32. "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signInWithGameCenter?key=APIKEY"
  33. fileprivate static let testAPI = "APIKEY"
  34. fileprivate static let idTokenKey = "idToken"
  35. fileprivate static let idToken = "IDTOKEN"
  36. fileprivate static let refreshTokenKey = "refreshToken"
  37. fileprivate static let refreshToken = "PUBLICKEYURL"
  38. fileprivate static let localIDKey = "localId"
  39. fileprivate static let localID = "LOCALID"
  40. fileprivate static let playerIDKey = "playerId"
  41. fileprivate static let playerID = "PLAYERID"
  42. fileprivate static let approximateExpirationDateKey = "expiresIn"
  43. fileprivate static let approximateExpirationDate = "3600"
  44. fileprivate static let isNewUserKey = "isNewUser"
  45. fileprivate static let isNewUser = true
  46. fileprivate static let displayNameKey = "displayName"
  47. fileprivate static let displayName = "DISPLAYNAME"
  48. fileprivate static let publicKeyURLKey = "publicKeyUrl"
  49. fileprivate static let publicKeyURL = "PUBLICKEYURL"
  50. fileprivate static let signatureKey = "signature"
  51. fileprivate static let signature = "AAAABBBBCCCC"
  52. fileprivate static let saltKey = "salt"
  53. fileprivate static let salt = "AAAA"
  54. fileprivate static let timestampKey = "timestamp"
  55. fileprivate static let timestamp: UInt64 = 12_345_678
  56. fileprivate static let accessTokenKey = "idToken"
  57. fileprivate static let accessToken = "ACCESSTOKEN"
  58. class MockBackendRPCIssuer: NSObject, FIRAuthBackendRPCIssuer {
  59. var requestURL: URL?
  60. var requestData: Data?
  61. var decodedRequest: [String: Any]?
  62. var contentType: String?
  63. var handler: FIRAuthBackendRPCIssuerCompletionHandler?
  64. func asyncPostToURL(with requestConfiguration: FIRAuthRequestConfiguration, url URL: URL,
  65. body: Data?, contentType: String,
  66. completionHandler handler: @escaping FIRAuthBackendRPCIssuerCompletionHandler) {
  67. requestURL = URL
  68. if let body = body {
  69. requestData = body
  70. let json = try! JSONSerialization
  71. .jsonObject(with: body, options: []) as! [String: Any]
  72. decodedRequest = json
  73. }
  74. self.contentType = contentType
  75. self.handler = handler
  76. }
  77. @discardableResult
  78. func respond(withJSON JSON: [String: Any]) throws -> Data {
  79. let data = try JSONSerialization.data(
  80. withJSONObject: JSON,
  81. options: JSONSerialization.WritingOptions.prettyPrinted
  82. )
  83. XCTAssertNotNil(handler)
  84. handler?(data, nil)
  85. return data
  86. }
  87. }
  88. override func setUp() {
  89. do {
  90. try Auth.auth().signOut()
  91. } catch {}
  92. }
  93. func testRequestResponseEncoding() {
  94. // given
  95. let RPCIssuer = MockBackendRPCIssuer()
  96. FIRAuthBackend.setDefaultBackendImplementationWith(RPCIssuer)
  97. let signature = Data(base64Encoded: Self.signature)!
  98. let salt = Data(base64Encoded: Self.salt)!
  99. let requestConfiguration = FIRAuthRequestConfiguration(apiKey: Self.testAPI, appID: "appID")!
  100. let request = FIRSignInWithGameCenterRequest(
  101. playerID: Self.playerID,
  102. publicKeyURL: URL(string: Self.publicKeyURL)!,
  103. signature: signature,
  104. salt: salt,
  105. timestamp: Self.timestamp,
  106. displayName: Self.displayName,
  107. requestConfiguration: requestConfiguration
  108. )!
  109. request.accessToken = Self.accessToken
  110. var cancellables = Set<AnyCancellable>()
  111. let signInWithGameCenterExpectation = expectation(description: "Sign in Game Center")
  112. // when
  113. FIRAuthBackend.signIn(withGameCenter: request)
  114. .sink { completion in
  115. switch completion {
  116. case .finished:
  117. print("Finished")
  118. case let .failure(error):
  119. XCTFail("💥 Something went wrong: \(error)")
  120. }
  121. } receiveValue: { response in
  122. XCTAssertEqual(RPCIssuer.requestURL?.absoluteString, Self.expectedAPIURL)
  123. XCTAssertNotNil(RPCIssuer.decodedRequest)
  124. XCTAssertEqual(
  125. RPCIssuer.decodedRequest?[Self.playerIDKey] as? String,
  126. Self.playerID
  127. )
  128. XCTAssertEqual(
  129. RPCIssuer.decodedRequest?[Self.publicKeyURLKey] as? String,
  130. Self.publicKeyURL
  131. )
  132. XCTAssertEqual(
  133. RPCIssuer.decodedRequest?[Self.signatureKey] as? String,
  134. Self.signature
  135. )
  136. XCTAssertEqual(RPCIssuer.decodedRequest?[Self.saltKey] as? String, Self.salt)
  137. XCTAssertEqual(
  138. RPCIssuer.decodedRequest?[Self.timestampKey] as? UInt64,
  139. Self.timestamp
  140. )
  141. XCTAssertEqual(
  142. RPCIssuer.decodedRequest?[Self.accessTokenKey] as? String,
  143. Self.accessToken
  144. )
  145. XCTAssertEqual(
  146. RPCIssuer.decodedRequest?[Self.displayNameKey] as? String,
  147. Self.displayName
  148. )
  149. XCTAssertNotNil(response)
  150. XCTAssertEqual(response.idToken, Self.idToken)
  151. XCTAssertEqual(response.refreshToken, Self.refreshToken)
  152. XCTAssertEqual(response.localID, Self.localID)
  153. XCTAssertEqual(response.playerID, Self.playerID)
  154. XCTAssertEqual(response.isNewUser, Self.isNewUser)
  155. XCTAssertEqual(response.displayName, Self.displayName)
  156. signInWithGameCenterExpectation.fulfill()
  157. }
  158. .store(in: &cancellables)
  159. let jsonDictionary: [String: Any] = [
  160. "idToken": Self.idToken,
  161. "refreshToken": Self.refreshToken,
  162. "localId": Self.localID,
  163. "playerId": Self.playerID,
  164. "expiresIn": Self.approximateExpirationDate,
  165. "isNewUser": Self.isNewUser,
  166. "displayName": Self.displayName,
  167. ]
  168. try! RPCIssuer.respond(withJSON: jsonDictionary)
  169. // then
  170. wait(for: [signInWithGameCenterExpectation], timeout: expectationTimeout)
  171. }
  172. }