Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functions Codable after sharing implementation with RTDB #9091

Merged
merged 7 commits into from
Dec 16, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import FirebaseFunctions
import FirebaseFunctionsTestingSupport
import XCTest

/// This file was intitialized as a direct port of the Objective C
/// This file was initialized as a direct port of the Objective C
/// FirebaseFunctions/Tests/Integration/FIRIntegrationTests.m
///
/// The tests require the emulator to be running with `FirebaseFunctions/Backend/start.sh synchronous`
Expand Down
8 changes: 4 additions & 4 deletions FirebaseFunctionsSwift/Sources/Codable/Callable+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public struct Callable<Request: Encodable, Response: Decodable> {
///
/// - Parameter data: Parameters to pass to the trigger.
/// - Parameter completion: The block to call when the HTTPS request has completed.
public func call(_ data: Request,
public func call(_ data: Request? = nil,
paulb777 marked this conversation as resolved.
Show resolved Hide resolved
completion: @escaping (Result<Response, Error>)
-> Void) {
paulb777 marked this conversation as resolved.
Show resolved Hide resolved
do {
Expand Down Expand Up @@ -119,7 +119,7 @@ public struct Callable<Request: Encodable, Response: Decodable> {
/// - Parameters:
/// - data: Parameters to pass to the trigger.
/// - completion: The block to call when the HTTPS request has completed.
public func callAsFunction(_ data: Request,
public func callAsFunction(_ data: Request? = nil,
completion: @escaping (Result<Response, Error>)
-> Void) {
call(data, completion: completion)
Expand All @@ -146,7 +146,7 @@ public struct Callable<Request: Encodable, Response: Decodable> {
///
/// - Returns: The decoded `Response` value
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
public func call(_ data: Request,
public func call(_ data: Request? = nil,
encoder: FirebaseDataEncoder = FirebaseDataEncoder(),
decoder: FirebaseDataDecoder =
FirebaseDataDecoder()) async throws -> Response {
Expand Down Expand Up @@ -175,7 +175,7 @@ public struct Callable<Request: Encodable, Response: Decodable> {
/// - data: Parameters to pass to the trigger.
/// - Returns: The decoded `Response` value
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
public func callAsFunction(_ data: Request) async throws -> Response {
public func callAsFunction(_ data: Request? = nil) async throws -> Response {
return try await call(data)
}
#endif
Expand Down
89 changes: 65 additions & 24 deletions FirebaseFunctionsSwift/Tests/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import FirebaseFunctionsSwift
import FirebaseFunctionsTestingSupport
import XCTest

/// This file was intitialized as a direct port of the Objective C
/// FirebaseFunctions/Tests/Integration/FIRIntegrationTests.m
/// This file was intitialized as a direct port of `FirebaseFunctionsSwift/Tests/IntegrationTests.swift`
/// which itself was ported from the Objective C `FirebaseFunctions/Tests/Integration/FIRIntegrationTests.m`
///
/// The tests require the emulator to be running with `FirebaseFunctions/Backend/start.sh synchronous`
/// The Firebase Functions called in the tests are implemented in `FirebaseFunctions/Backend/index.js`.
Expand Down Expand Up @@ -75,7 +75,7 @@ class IntegrationTests: XCTestCase {
functions.useLocalhost()
}

func testData() throws {
func testData() {
let expectation = expectation(description: #function)
let data = DataTestRequest(
bool: true,
Expand All @@ -97,10 +97,10 @@ class IntegrationTests: XCTestCase {
code: 42
)
XCTAssertEqual(response, expected)
expectation.fulfill()
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}
Expand Down Expand Up @@ -131,7 +131,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testScalar() throws {
func testScalar() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"scalarTest",
Expand All @@ -142,10 +142,10 @@ class IntegrationTests: XCTestCase {
do {
let response = try result.get()
XCTAssertEqual(response, 76)
expectation.fulfill()
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}
Expand All @@ -172,7 +172,7 @@ class IntegrationTests: XCTestCase {

#endif

func testToken() throws {
func testToken() {
// Recreate functions with a token.
let functions = FunctionsFake(
projectID: "functions-integration-test",
Expand All @@ -193,10 +193,10 @@ class IntegrationTests: XCTestCase {
do {
let data = try result.get()
XCTAssertEqual(data, [:])
expectation.fulfill()
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}
Expand Down Expand Up @@ -224,7 +224,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testFCMToken() throws {
func testFCMToken() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"FCMTokenTest",
Expand All @@ -235,10 +235,10 @@ class IntegrationTests: XCTestCase {
do {
let data = try result.get()
XCTAssertEqual(data, [:])
expectation.fulfill()
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}
Expand All @@ -257,7 +257,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testNull() throws {
func testNull() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"nullTest",
Expand All @@ -268,10 +268,10 @@ class IntegrationTests: XCTestCase {
do {
let data = try result.get()
XCTAssertEqual(data, nil)
expectation.fulfill()
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}
Expand All @@ -294,11 +294,40 @@ class IntegrationTests: XCTestCase {
// If no parameters are required, then the non-typed API
// is more appropriate since it specifically avoids defining
// type.
// func testParameterless() {
// }
//
//
func testMissingResult() throws {
func testParameterless() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"nullTest",
requestAs: Int?.self,
responseAs: Int?.self
)
function.call { result in
do {
let data = try result.get()
XCTAssertEqual(data, nil)
} catch {
XCTAssert(false, "Failed to unwrap the function result: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}

#if compiler(>=5.5) && canImport(_Concurrency)
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
func testParameterlessAsync() async throws {
let function = functions.httpsCallable(
"nullTest",
requestAs: Int?.self,
responseAs: Int?.self
)

let data = try await function.call()
XCTAssertEqual(data, nil)
}
#endif

func testMissingResult() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"missingResultTest",
Expand All @@ -313,7 +342,9 @@ class IntegrationTests: XCTestCase {
XCTAssertEqual(FunctionsErrorCode.internal.rawValue, error.code)
XCTAssertEqual("Response is missing data field.", error.localizedDescription)
expectation.fulfill()
return
}
XCTFail("Failed to throw error for missing result")
}
waitForExpectations(timeout: 5)
}
Expand All @@ -337,7 +368,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testUnhandledError() throws {
func testUnhandledError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"unhandledErrorTest",
Expand All @@ -352,7 +383,9 @@ class IntegrationTests: XCTestCase {
XCTAssertEqual(FunctionsErrorCode.internal.rawValue, error.code)
XCTAssertEqual("INTERNAL", error.localizedDescription)
expectation.fulfill()
return
}
XCTFail("Failed to throw error for missing result")
}
XCTAssert(true)
waitForExpectations(timeout: 5)
Expand All @@ -377,7 +410,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testUnknownError() throws {
func testUnknownError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"unknownErrorTest",
Expand All @@ -392,7 +425,9 @@ class IntegrationTests: XCTestCase {
XCTAssertEqual(FunctionsErrorCode.internal.rawValue, error.code)
XCTAssertEqual("INTERNAL", error.localizedDescription)
expectation.fulfill()
return
}
XCTFail("Failed to throw error for missing result")
}
waitForExpectations(timeout: 5)
}
Expand All @@ -416,7 +451,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testExplicitError() throws {
func testExplicitError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"explicitErrorTest",
Expand All @@ -433,7 +468,9 @@ class IntegrationTests: XCTestCase {
XCTAssertEqual(["start": 10 as Int32, "end": 20 as Int32, "long": 30],
error.userInfo[FunctionsErrorDetailsKey] as! [String: Int32])
expectation.fulfill()
return
}
XCTFail("Failed to throw error for missing result")
}
waitForExpectations(timeout: 5)
}
Expand All @@ -459,7 +496,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testHttpError() throws {
func testHttpError() {
let expectation = expectation(description: #function)
let function = functions.httpsCallable(
"httpErrorTest",
Expand All @@ -474,7 +511,9 @@ class IntegrationTests: XCTestCase {
let error = error as NSError
XCTAssertEqual(FunctionsErrorCode.invalidArgument.rawValue, error.code)
expectation.fulfill()
return
}
XCTFail("Failed to throw error for missing result")
}
waitForExpectations(timeout: 5)
}
Expand All @@ -497,7 +536,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testTimeout() throws {
func testTimeout() {
let expectation = expectation(description: #function)
var function = functions.httpsCallable(
"timeoutTest",
Expand All @@ -514,7 +553,9 @@ class IntegrationTests: XCTestCase {
XCTAssertEqual("DEADLINE EXCEEDED", error.localizedDescription)
XCTAssertNil(error.userInfo[FunctionsErrorDetailsKey])
expectation.fulfill()
return
}
XCTFail("Failed to throw error for missing result")
}
waitForExpectations(timeout: 5)
}
Expand All @@ -540,7 +581,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testCallAsFunction() throws {
func testCallAsFunction() {
let expectation = expectation(description: #function)
let data = DataTestRequest(
bool: true,
Expand Down Expand Up @@ -596,7 +637,7 @@ class IntegrationTests: XCTestCase {
}
#endif

func testInferredTypes() throws {
func testInferredTypes() {
let expectation = expectation(description: #function)
let data = DataTestRequest(
bool: true,
Expand Down