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

186 lines
6.5 KiB
Swift
Raw Normal View History

2024-09-10 20:27:09 +02:00
// 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")!,
2024-09-10 20:27:09 +02:00
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")!,
2024-09-10 20:27:09 +02:00
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)
2024-09-10 20:27:09 +02:00
}
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")!,
2024-09-10 20:27:09 +02:00
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)
2024-09-10 20:27:09 +02:00
}
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")!,
2024-09-10 20:27:09 +02:00
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)
2024-09-10 20:27:09 +02:00
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")!,
2024-09-10 20:27:09 +02:00
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")!,
2024-09-10 20:27:09 +02:00
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)
2024-09-10 20:27:09 +02:00
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")!,
2024-09-10 20:27:09 +02:00
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)
}
}