HTTPSCallableTests.swift 5.8 KB

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