Skip to content

Commit 33bd33a

Browse files
authored
Merge pull request #4 from adborbas/adborbas/handle_unexpected_response
Handle unexpected response from AlphaVantage
2 parents 3f5c6eb + 1504344 commit 33bd33a

File tree

5 files changed

+53
-14
lines changed

5 files changed

+53
-14
lines changed

Sources/AlphaSwiftage/Private/AlphaVantageResponseSerializer.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,15 @@ struct AlphaVantageResponseSerializer<T: Decodable>: ResponseSerializer {
1717
return .success(result)
1818
} catch {
1919
if let data = data {
20-
let error = try! JSONDecoder().decode(AlphaVantageAPIError.self, from: data)
21-
return .failure(.apiError(error))
20+
do {
21+
let error = try JSONDecoder().decode(AlphaVantageAPIError.self, from: data)
22+
return .failure(.apiError(error))
23+
} catch {
24+
if let response = String(data: data, encoding: .utf8) {
25+
return .failure(.unexpectedResponse(response))
26+
}
27+
return .failure(.unknown(error))
28+
}
2229
}
2330

2431
return .failure(.unknown(error))

Sources/AlphaSwiftage/Public/AlphaVantageError.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Foundation
99

1010
public enum AlphaVantageError: Error {
1111
case apiError(AlphaVantageAPIError)
12+
case unexpectedResponse(String)
1213
case unknown(Error)
1314
}
1415

Tests/AlphaVantageServiceTests.swift

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ final class AlphaVantageServiceTests: XCTestCase {
7777

7878
func testSymbolSearchFailure() async {
7979
// Given
80-
let expectedError = AlphaVantageAPIError(message: "Invalid API call.")
80+
let expectedError: AlphaVantageError = .apiError(AlphaVantageAPIError(message: "Invalid API call."))
8181
let keyword = "whatever"
8282
let service = givenService()
8383
given(response: .symbolSearchFailure, for: "https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=\(keyword)&apikey=\(apiKey)")
@@ -86,17 +86,20 @@ final class AlphaVantageServiceTests: XCTestCase {
8686
let result = await service.symbolSearch(keywords: keyword)
8787

8888
// Then
89-
switch result {
90-
case .success:
91-
XCTFail("Expected error but got success!")
92-
case .failure(let error):
93-
switch error {
94-
case .apiError(let apiError):
95-
XCTAssertEqual(apiError, expectedError)
96-
case .unknown(let error):
97-
XCTFail("Expected apiError but got: \(error.localizedDescription)")
98-
}
99-
}
89+
await assertError(result, expectedError: expectedError)
90+
}
91+
92+
func test_unexpectedResponse() async {
93+
// Given
94+
let symbol = "vwce"
95+
let service = givenService()
96+
given(response: .unexpectedResponse, for: "https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=\(symbol)&apikey=\(apiKey)")
97+
98+
// When
99+
let result = await service.quote(for: symbol)
100+
101+
// Then
102+
await assertError(result, expectedError: .unexpectedResponse("{\n \"this\": [\"is\", \"unexpected\"]\n}\n"))
100103
}
101104

102105
private func given(response: MockResponse, for url: String) {
@@ -119,4 +122,28 @@ final class AlphaVantageServiceTests: XCTestCase {
119122
XCTFail("Expected success but got error: \(error)")
120123
}
121124
}
125+
126+
private func assertError<T>(_ result: Result<T, AlphaVantageError>, expectedError: AlphaVantageError) async {
127+
switch result {
128+
case .success:
129+
XCTFail("Expected error but got success!")
130+
case .failure(let error):
131+
XCTAssertEqual(error, expectedError, "Expected \(expectedError) but got: \(error)")
132+
}
133+
}
134+
}
135+
136+
extension AlphaVantageError: Equatable {
137+
public static func == (lhs: AlphaVantageError, rhs: AlphaVantageError) -> Bool {
138+
switch (lhs, rhs) {
139+
case (.apiError(let lhsError), .apiError(let rhsError)):
140+
return lhsError == rhsError
141+
case (.unexpectedResponse(let lhsResponse), .unexpectedResponse(let rhsResponse)):
142+
return lhsResponse == rhsResponse
143+
case (.unknown(let lhsError), .unknown(let rhsError)):
144+
return lhsError.localizedDescription == rhsError.localizedDescription
145+
default:
146+
return false
147+
}
148+
}
122149
}

Tests/MockResponse.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ enum MockResponse: String {
1313
case currencyExchangeRate = "mockCurrencyExchangeRateeResponse"
1414
case symbolSearchSuccess = "mockSymbolSearchSuccess"
1515
case symbolSearchFailure = "mockSymbolSearchFailure"
16+
case unexpectedResponse = "mockUnexpectedResponse"
1617

1718
var resourcePath: URL {
1819
return Bundle.test.url(forResource: "Resources/\(rawValue)", withExtension: "json")!
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"this": ["is", "unexpected"]
3+
}

0 commit comments

Comments
 (0)