HTTPSCallableTests.swift 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 FirebaseCore
  17. import FirebaseFunctionsCombineSwift
  18. @testable import FirebaseFunctionsTestingSupport
  19. import XCTest
  20. // hardcoded in FIRHTTPSCallable.m
  21. private let kFunctionsTimeout: TimeInterval = 70.0
  22. private let expectationTimeout: TimeInterval = 2
  23. class MockFunctions: Functions {
  24. var mockCallFunction: () throws -> HTTPSCallableResult?
  25. var verifyParameters: ((_ name: String, _ data: Any?, _ timeout: TimeInterval) throws -> Void)?
  26. override func callFunction(_ name: String,
  27. with data: Any?,
  28. timeout: TimeInterval,
  29. completion: @escaping (HTTPSCallableResult?, Error?) -> Void) {
  30. do {
  31. try verifyParameters?(name, data, timeout)
  32. let result = try mockCallFunction()
  33. completion(result, nil)
  34. } catch {
  35. completion(nil, error)
  36. }
  37. }
  38. }
  39. class HTTPSCallableTests: XCTestCase {
  40. override func setUp() {
  41. super.setUp()
  42. if FirebaseApp.app() == nil {
  43. let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
  44. gcmSenderID: "00000000000000000-00000000000-000000000")
  45. FirebaseApp.configure(options: options)
  46. }
  47. }
  48. func testCallWithoutParametersSuccess() {
  49. // given
  50. var cancellables = Set<AnyCancellable>()
  51. let httpsFunctionWasCalledExpectation = expectation(description: "HTTPS Function was called")
  52. let functionWasCalledExpectation = expectation(description: "Function was called")
  53. let functions = MockFunctions.functions()
  54. let expectedResult = "mockResult w/o parameters"
  55. functions.mockCallFunction = {
  56. httpsFunctionWasCalledExpectation.fulfill()
  57. return HTTPSCallableResultFake(data: expectedResult)
  58. }
  59. let dummyFunction = functions.httpsCallable("dummyFunction")
  60. // when
  61. dummyFunction.call()
  62. .sink { completion in
  63. switch completion {
  64. case .finished:
  65. print("Finished")
  66. case let .failure(error):
  67. XCTFail("💥 Something went wrong: \(error)")
  68. }
  69. } receiveValue: { functionResult in
  70. guard let result = functionResult.data as? String else {
  71. XCTFail("Expected String data")
  72. return
  73. }
  74. XCTAssertEqual(result, expectedResult)
  75. functionWasCalledExpectation.fulfill()
  76. }
  77. .store(in: &cancellables)
  78. // then
  79. wait(
  80. for: [functionWasCalledExpectation, httpsFunctionWasCalledExpectation],
  81. timeout: expectationTimeout
  82. )
  83. }
  84. func testCallWithParametersSuccess() {
  85. // given
  86. var cancellables = Set<AnyCancellable>()
  87. let httpsFunctionWasCalledExpectation = expectation(description: "HTTPS Function was called")
  88. let functionWasCalledExpectation = expectation(description: "Function was called")
  89. let functions = MockFunctions.functions()
  90. let inputParameter = "input parameter"
  91. let expectedResult = "mockResult w/ parameters: \(inputParameter)"
  92. functions.verifyParameters = { name, data, timeout in
  93. XCTAssertEqual(name as String, "dummyFunction")
  94. XCTAssertEqual(data as? String, inputParameter)
  95. XCTAssertEqual(timeout as TimeInterval, kFunctionsTimeout)
  96. }
  97. functions.mockCallFunction = {
  98. httpsFunctionWasCalledExpectation.fulfill()
  99. return HTTPSCallableResultFake(data: expectedResult)
  100. }
  101. let dummyFunction = functions.httpsCallable("dummyFunction")
  102. // when
  103. dummyFunction.call(inputParameter)
  104. .sink { completion in
  105. switch completion {
  106. case .finished:
  107. print("Finished")
  108. case let .failure(error):
  109. XCTFail("💥 Something went wrong: \(error)")
  110. }
  111. } receiveValue: { functionResult in
  112. guard let result = functionResult.data as? String else {
  113. XCTFail("Expected String data")
  114. return
  115. }
  116. XCTAssertEqual(result, expectedResult)
  117. functionWasCalledExpectation.fulfill()
  118. }
  119. .store(in: &cancellables)
  120. // then
  121. wait(
  122. for: [httpsFunctionWasCalledExpectation, functionWasCalledExpectation],
  123. timeout: expectationTimeout
  124. )
  125. }
  126. func testCallWithParametersFailure() {
  127. // given
  128. var cancellables = Set<AnyCancellable>()
  129. let httpsFunctionWasCalledExpectation = expectation(description: "HTTPS Function was called")
  130. let functionCallFailedExpectation = expectation(description: "Function call failed")
  131. let functions = MockFunctions.functions()
  132. let inputParameter = "input parameter"
  133. functions.verifyParameters = { name, data, timeout in
  134. XCTAssertEqual(name as String, "dummyFunction")
  135. XCTAssertEqual(data as? String, inputParameter)
  136. XCTAssertEqual(timeout as TimeInterval, kFunctionsTimeout)
  137. }
  138. functions.mockCallFunction = {
  139. httpsFunctionWasCalledExpectation.fulfill()
  140. throw NSError(domain: FunctionsErrorDomain,
  141. code: FunctionsErrorCode.internal.rawValue,
  142. userInfo: [NSLocalizedDescriptionKey: "Response is missing data field."])
  143. }
  144. let dummyFunction = functions.httpsCallable("dummyFunction")
  145. // when
  146. dummyFunction.call(inputParameter)
  147. .sink { completion in
  148. if case let .failure(error as NSError) = completion {
  149. // Verify user mismatch error.
  150. XCTAssertEqual(error.code, FunctionsErrorCode.internal.rawValue)
  151. functionCallFailedExpectation.fulfill()
  152. }
  153. } receiveValue: { functionResult in
  154. XCTFail("💥 result unexpected")
  155. }
  156. .store(in: &cancellables)
  157. // then
  158. wait(
  159. for: [functionCallFailedExpectation, httpsFunctionWasCalledExpectation],
  160. timeout: expectationTimeout
  161. )
  162. }
  163. }