Files
firebase-ios-sdk/FirebaseFunctions/Tests/Unit/FunctionsErrorTests.swift
T

187 lines
6.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
@testable import FirebaseFunctions
import XCTest
final class FunctionsErrorTests: XCTestCase {
func testInitWithCode() {
let error = FunctionsError(.permissionDenied)
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
XCTAssertEqual(nsError.code, 7)
XCTAssertEqual(nsError.localizedDescription, "PERMISSION DENIED")
XCTAssertEqual(nsError.userInfo.count, 1)
}
func testInitWithCodeAndUserInfo() {
let error = FunctionsError(.unimplemented, userInfo: ["TEST_Key": "TEST_Value"])
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
XCTAssertEqual(nsError.code, 12)
XCTAssertEqual(
nsError.localizedDescription,
"The operation couldn’t be completed. (com.firebase.functions error 12.)"
)
XCTAssertEqual(nsError.userInfo.count, 1)
XCTAssertEqual(nsError.userInfo["TEST_Key"] as? String, "TEST_Value")
}
func testInitWithOKStatusCodeAndNoErrorBody() {
// The error should be `nil`.
let error = FunctionsError(
httpStatusCode: 200,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: nil,
serializer: FunctionsSerializer()
)
XCTAssertNil(error)
}
func testInitWithErrorStatusCodeAndNoErrorBody() {
// The error should be inferred from the HTTP status code.
let error = FunctionsError(
httpStatusCode: 429,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: nil,
serializer: FunctionsSerializer()
)
guard let error else { return XCTFail("Unexpected `nil` value") }
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
XCTAssertEqual(nsError.code, 8)
XCTAssertEqual(nsError.localizedDescription, "RESOURCE EXHAUSTED")
XCTAssertEqual(nsError.userInfo.count, 3)
}
func testInitWithOKStatusCodeAndIncompleteErrorBody() {
// The status code in the error body takes precedence over the HTTP status code.
let responseData = #"{ "error": { "status": "OUT_OF_RANGE" } }"#.data(using: .utf8)!
let error = FunctionsError(
httpStatusCode: 200,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: responseData,
serializer: FunctionsSerializer()
)
guard let error else { return XCTFail("Unexpected `nil` value") }
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
XCTAssertEqual(nsError.code, 11)
XCTAssertEqual(nsError.localizedDescription, "OUT OF RANGE")
XCTAssertEqual(nsError.userInfo.count, 3)
}
func testInitWithErrorStatusCodeAndErrorBody() {
// The status code in the error body takes precedence over the HTTP status code.
let responseData =
#"{ "error": { "status": "OUT_OF_RANGE", "message": "TEST_ErrorMessage", "details": 123 } }"#
.data(using: .utf8)!
let error = FunctionsError(
httpStatusCode: 499,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: responseData,
serializer: FunctionsSerializer()
)
guard let error else { return XCTFail("Unexpected `nil` value") }
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
XCTAssertEqual(nsError.code, 11)
XCTAssertEqual(nsError.localizedDescription, "TEST_ErrorMessage")
XCTAssertEqual(nsError.userInfo.count, 4)
XCTAssertEqual(nsError.userInfo["details"] as? Int, 123)
}
func testInitWithErrorStatusCodeAndOKErrorBody() {
// When the status code in the error body is `OK`, error should be `nil` regardless of the HTTP
// status code.
let responseData =
#"{ "error": { "status": "OK", "message": "TEST_ErrorMessage", "details": 123 } }"#
.data(using: .utf8)!
let error = FunctionsError(
httpStatusCode: 401,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: responseData,
serializer: FunctionsSerializer()
)
XCTAssertNil(error)
}
func testInitWithErrorStatusCodeAndIncompleteErrorBody() {
// The error name is not in the body; it should be inferred from the HTTP status code.
let responseData = #"{ "error": { "message": "TEST_ErrorMessage", "details": null } }"#
.data(using: .utf8)!
let error = FunctionsError(
httpStatusCode: 403,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: responseData,
serializer: FunctionsSerializer()
)
guard let error else { return XCTFail("Unexpected `nil` value") }
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
XCTAssertEqual(nsError.code, 7) // `permissionDenied`, inferred from the HTTP status code
XCTAssertEqual(nsError.localizedDescription, "TEST_ErrorMessage")
XCTAssertEqual(nsError.userInfo.count, 4)
XCTAssertEqual(nsError.userInfo["details"] as? NSNull, NSNull())
}
func testInitWithErrorStatusCodeAndInvalidErrorBody() {
// An unsupported status code in the error body should result in the rest of the body ignored.
let responseData =
#"{ "error": { "status": "TEST_UNKNOWN_ERROR", "message": "TEST_ErrorMessage", "details": 123 } }"#
.data(using: .utf8)!
let error = FunctionsError(
httpStatusCode: 503,
region: "my-region",
url: URL(string: "https://example.com/fake_func")!,
body: responseData,
serializer: FunctionsSerializer()
)
guard let error else { return XCTFail("Unexpected `nil` value") }
let nsError = error as NSError
XCTAssertEqual(nsError.domain, "com.firebase.functions")
// Currently, `internal` is used as the fallback error code. Is this correct?
// Seems like we could get more information from the HTTP status code in such cases.
XCTAssertEqual(nsError.code, 13)
XCTAssertEqual(nsError.localizedDescription, "INTERNAL")
XCTAssertEqual(nsError.userInfo.count, 1)
}
}