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

Remove Authorization argument in ConfigurationLoader.getConfig method #1361

Merged
merged 8 commits into from
Jul 16, 2024
4 changes: 2 additions & 2 deletions Sources/BraintreeCore/BTAPIClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ import Foundation
/// cached on subsequent calls for better performance.
@_documentation(visibility: private)
public func fetchOrReturnRemoteConfiguration(_ completion: @escaping (BTConfiguration?, Error?) -> Void) {
configurationLoader.getConfig(authorization) { [weak self] configuration, error in
configurationLoader.getConfig { [weak self] configuration, error in
guard let self else {
completion(nil, BTAPIClientError.deallocated)
return
Expand All @@ -116,7 +116,7 @@ import Foundation
}

func fetchConfiguration() async throws -> BTConfiguration {
try await configurationLoader.getConfig(authorization)
try await configurationLoader.getConfig()
}

/// Fetches a customer's vaulted payment method nonces.
Expand Down
11 changes: 5 additions & 6 deletions Sources/BraintreeCore/ConfigurationLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@ class ConfigurationLoader {
/// 3. If fetching the configuration fails, it returns an error.
///
/// - Parameters:
/// - authorization: An `ClientAuthorization` object required to access the configuration.
/// - completion: A completion handler that is called with the fetched or cached `BTConfiguration` object or an `Error`.
///
/// - Completion:
/// - `BTConfiguration?`: The configuration object if it is successfully fetched or retrieved from the cache.
/// - `Error?`: An error object if fetching the configuration fails or if the instance is deallocated.
@_documentation(visibility: private)
func getConfig(_ authorization: ClientAuthorization, completion: @escaping (BTConfiguration?, Error?) -> Void) {
if let cachedConfig = try? configurationCache.getFromCache(authorization: authorization.bearer) {
func getConfig(completion: @escaping (BTConfiguration?, Error?) -> Void) {
if let cachedConfig = try? configurationCache.getFromCache(authorization: http.authorization.bearer) {
completion(cachedConfig, nil)
return
}
Expand All @@ -56,17 +55,17 @@ class ConfigurationLoader {
} else {
let configuration = BTConfiguration(json: body)

try? configurationCache.putInCache(authorization: authorization.bearer, configuration: configuration)
try? configurationCache.putInCache(authorization: http.authorization.bearer, configuration: configuration)

completion(configuration, nil)
return
}
}
}

func getConfig(_ authorization: ClientAuthorization) async throws -> BTConfiguration {
func getConfig() async throws -> BTConfiguration {
try await withCheckedThrowingContinuation { continuation in
getConfig(authorization) { configuration, error in
getConfig { configuration, error in
if let error {
continuation.resume(throwing: error)
} else if let configuration {
Expand Down
25 changes: 9 additions & 16 deletions UnitTests/BraintreeCoreTests/ConfigurationLoader_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ class ConfigurationLoader_Tests: XCTestCase {
func testGetConfig_whenCached_returnsConfigFromCache() {
let sampleJSON = ["test": "value", "environment": "fake-env1"]
try? ConfigurationCache.shared.putInCache(authorization: "development_tokenization_key", configuration: BTConfiguration(json: BTJSON(value: sampleJSON)))
let mockClientAuthorization = MockClientAuthorization(bearer: "development_tokenization_key")

let expectation = expectation(description: "Callback invoked")
sut.getConfig(mockClientAuthorization) { configuration, error in
sut.getConfig { configuration, error in
XCTAssertEqual(configuration?.environment, "fake-env1")
XCTAssertEqual(configuration?.json?["test"].asString(), "value")
XCTAssertNil(self.mockHTTP.lastRequestEndpoint)
Expand All @@ -37,10 +36,9 @@ class ConfigurationLoader_Tests: XCTestCase {

func testGetConfig_performsGETWithCorrectPayload() {
mockHTTP.stubRequest(withMethod: "GET", toEndpoint: "/v1/configuration", respondWith: [] as [Any?], statusCode: 200)
let mockClientAuthorization = MockClientAuthorization()


let expectation = expectation(description: "Callback invoked")
sut.getConfig(mockClientAuthorization) { _,_ in
sut.getConfig { _, _ in
XCTAssertEqual(self.mockHTTP.lastRequestEndpoint, "v1/configuration")
XCTAssertEqual(self.mockHTTP.lastRequestParameters?["configVersion"] as? String, "3")
expectation.fulfill()
Expand All @@ -52,10 +50,9 @@ class ConfigurationLoader_Tests: XCTestCase {
func testGetConfig_canGetRemoteConfiguration() {
mockHTTP.cannedConfiguration = BTJSON(value: ["test": true])
mockHTTP.cannedStatusCode = 200
let mockClientAuthorization = MockClientAuthorization()

let expectation = expectation(description: "Fetch configuration")
sut.getConfig(mockClientAuthorization) { configuration, error in
sut.getConfig { configuration, error in
XCTAssertNotNil(configuration)
XCTAssertNil(error)
XCTAssertGreaterThanOrEqual(self.mockHTTP.GETRequestCount, 1)
Expand All @@ -75,10 +72,9 @@ class ConfigurationLoader_Tests: XCTestCase {
respondWith: ["error_message": "Something bad happened"],
statusCode: 503
)
let mockClientAuthorization = MockClientAuthorization()


let expectation = expectation(description: "Callback invoked")
sut.getConfig(mockClientAuthorization) { configuration, error in
sut.getConfig { configuration, error in
guard let error = error as NSError? else { return }
XCTAssertNil(configuration)
XCTAssertEqual(error.domain, BTAPIClientError.errorDomain)
Expand All @@ -93,11 +89,10 @@ class ConfigurationLoader_Tests: XCTestCase {
func testGetConfig_whenNetworkHasError_returnsNetworkErrorInCallback() {
ConfigurationCache.shared.cacheInstance.removeAllObjects()
let mockError: NSError = NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotConnectToHost)
let mockClientAuthorization = MockClientAuthorization()
mockHTTP.stubRequest(withMethod: "GET", toEndpoint: "/client_api/v1/configuration", respondWithError: mockError)

let expectation = expectation(description: "Fetch configuration")
sut.getConfig(mockClientAuthorization) { configuration, error in
sut.getConfig { configuration, error in
// BTAPIClient fetches the config when initialized so there can potentially be 2 requests here
XCTAssertLessThanOrEqual(self.mockHTTP.GETRequestCount, 2)
XCTAssertNil(configuration)
Expand All @@ -111,10 +106,9 @@ class ConfigurationLoader_Tests: XCTestCase {
func testGetConfig_returnsConfiguration() async throws {
mockHTTP.cannedConfiguration = BTJSON(value: ["test": true])
mockHTTP.cannedStatusCode = 200
let mockClientAuthorization = MockClientAuthorization()

let asyncTask = Task {
return try await sut.getConfig(mockClientAuthorization)
return try await sut.getConfig()
}

let returnedConfig = try await asyncTask.value
Expand All @@ -124,11 +118,10 @@ class ConfigurationLoader_Tests: XCTestCase {

func testGetConfig_returnsNetworkErrorInCallback() async throws {
let mockError: NSError = NSError(domain: NSURLErrorDomain, code: NSURLErrorCannotConnectToHost)
let mockClientAuthorization = MockClientAuthorization()
mockHTTP.stubRequest(withMethod: "GET", toEndpoint: "/client_api/v1/configuration", respondWithError: mockError)

let asyncTask = Task {
return try await sut.getConfig(mockClientAuthorization)
return try await sut.getConfig()
}

do {
Expand Down
4 changes: 2 additions & 2 deletions UnitTests/BraintreeCoreTests/MockConfigurationLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ class MockConfigurationLoader: ConfigurationLoader {
super.init(http: http)
}

override func getConfig(_ authorization: ClientAuthorization, completion: @escaping (BTConfiguration?, Error?) -> Void) {
override func getConfig(completion: @escaping (BTConfiguration?, Error?) -> Void) {
if let error = mockError {
completion(nil, error)
} else {
completion(mockConfig, nil)
}
}

override func getConfig(_ authorization: ClientAuthorization) async throws -> BTConfiguration {
override func getConfig() async throws -> BTConfiguration {
if let error = mockError {
throw error
} else if let config = mockConfig {
Expand Down
Loading