Skip to content

Commit

Permalink
Merge pull request #314 from mapbox/jerrad/no-response-fix
Browse files Browse the repository at this point in the history
No Response Fix
  • Loading branch information
1ec5 authored Nov 21, 2018
2 parents 3ec65f3 + 188e546 commit 688e732
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
9 changes: 7 additions & 2 deletions MapboxDirections/MBDirections.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
typealias JSONDictionary = [String: Any]

/// Indicates that an error occurred in MapboxDirections.
public let MBDirectionsErrorDomain = "MBDirectionsErrorDomain"
public let MBDirectionsErrorDomain = "com.mapbox.directions.ErrorDomain"

/// The Mapbox access token specified in the main application bundle’s Info.plist.
let defaultAccessToken = Bundle.main.object(forInfoDictionaryKey: "MGLMapboxAccessToken") as? String
Expand Down Expand Up @@ -249,7 +249,7 @@ open class Directions: NSObject {

let apiStatusCode = json["code"] as? String
let apiMessage = json["message"] as? String
guard data != nil && error == nil && ((apiStatusCode == nil && apiMessage == nil) || apiStatusCode == "Ok") else {
guard !json.isEmpty, data != nil, error == nil && ((apiStatusCode == nil && apiMessage == nil) || apiStatusCode == "Ok") else {
let apiError = Directions.informativeError(describing: json, response: response, underlyingError: error as NSError?)
DispatchQueue.main.async {
errorHandler(apiError)
Expand Down Expand Up @@ -299,6 +299,11 @@ open class Directions: NSObject {
case (404, "ProfileNotFound"):
failureReason = "Unrecognized profile identifier."
recoverySuggestion = "Make sure the profileIdentifier option is set to one of the provided constants, such as MBDirectionsProfileIdentifierAutomobile."

case (413, _):
failureReason = "The request is too large."
recoverySuggestion = "Try specifying fewer waypoints or giving the waypoints shorter names."

case (429, _):
if let timeInterval = response.rateLimitInterval, let maximumCountOfRequests = response.rateLimit {
let intervalFormatter = DateComponentsFormatter()
Expand Down
70 changes: 69 additions & 1 deletion MapboxDirectionsTests/DirectionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,32 @@ import OHHTTPStubs
@testable import MapboxDirections

let BogusToken = "pk.feedCafeDadeDeadBeef-BadeBede.FadeCafeDadeDeed-BadeBede"
let BadResponse = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>413 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: RAf2XH13mMVxQ96Z1cVQMPrd-hJoVA6LfaWVFDbdN2j-J1VkzaPvZg==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>
"""

class DirectionsTests: XCTestCase {
override func setUp() {
// Make sure tests run in all time zones
NSTimeZone.default = TimeZone(secondsFromGMT: 0)!
}

override func tearDown() {
OHHTTPStubs.removeAllStubs()
super.tearDown()
Expand All @@ -21,6 +40,55 @@ class DirectionsTests: XCTestCase {
XCTAssertEqual(directions.apiEndpoint.absoluteString, "https://api.mapbox.com")
}

func testKnownBadResponse() {
let pass = "The operation couldn’t be completed. The request is too large."

OHHTTPStubs.stubRequests(passingTest: { (request) -> Bool in
return request.url!.absoluteString.contains("https://api.mapbox.com/directions")
}) { (_) -> OHHTTPStubsResponse in
return OHHTTPStubsResponse(data: BadResponse.data(using: .utf8)!, statusCode: 413, headers: ["Content-Type" : "text/html"])
}
let expectation = XCTestExpectation(description: "Async callback")
let one = CLLocation(coordinate: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0))
let two = CLLocation(coordinate: CLLocationCoordinate2D(latitude: 2.0, longitude: 2.0))

let directions = Directions(accessToken: BogusToken)
let opts = RouteOptions(locations: [one, two])
directions.calculate(opts, completionHandler: { (waypoints, routes, error) in
expectation.fulfill()
XCTAssertNil(routes, "Unexpected route response")
XCTAssertNotNil(error, "No error returned")
XCTAssertNil(error?.userInfo[NSUnderlyingErrorKey])
XCTAssertEqual(error?.localizedDescription, pass, "Wrong type of error received")
})
wait(for: [expectation], timeout: 2.0)
}

func testUnknownBadResponse() {
let pass = "The operation couldn’t be completed. server error"

OHHTTPStubs.stubRequests(passingTest: { (request) -> Bool in
return request.url!.absoluteString.contains("https://api.mapbox.com/directions")
}) { (_) -> OHHTTPStubsResponse in
let message = "Enhance your calm, John Spartan."
return OHHTTPStubsResponse(data: message.data(using: .utf8)!, statusCode: 420, headers: ["Content-Type" : "text/plain"])
}
let expectation = XCTestExpectation(description: "Async callback")
let one = CLLocation(coordinate: CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0))
let two = CLLocation(coordinate: CLLocationCoordinate2D(latitude: 2.0, longitude: 2.0))

let directions = Directions(accessToken: BogusToken)
let opts = RouteOptions(locations: [one, two])
directions.calculate(opts, completionHandler: { (waypoints, routes, error) in
expectation.fulfill()
XCTAssertNil(routes, "Unexpected route response")
XCTAssertNotNil(error, "No error returned")
XCTAssertNil(error?.userInfo[NSUnderlyingErrorKey])
XCTAssertEqual(error?.localizedDescription, pass, "Wrong type of error received")
})
wait(for: [expectation], timeout: 2.0)
}

func testRateLimitErrorParsing() {
let json = ["message" : "Hit rate limit"]

Expand Down

0 comments on commit 688e732

Please sign in to comment.