diff --git a/Directions Example/ViewController.swift b/Directions Example/ViewController.swift index 43d891a23..f610c6c55 100644 --- a/Directions Example/ViewController.swift +++ b/Directions Example/ViewController.swift @@ -70,45 +70,49 @@ class ViewController: UIViewController, MBDrawingViewDelegate { options.routeShapeResolution = .full options.attributeOptions = [.congestionLevel, .maximumSpeedLimit] - Directions.shared.calculate(options) { (response, error) in - if let error = error { + Directions.shared.calculate(options) { (session, result) in + + switch (result) { + case let .failure(error): print("Error calculating directions: \(error)") return - } - - if let route = response.routes?.first, let leg = route.legs.first { - print("Route via \(leg):") - - let distanceFormatter = LengthFormatter() - let formattedDistance = distanceFormatter.string(fromMeters: route.distance) - - let travelTimeFormatter = DateComponentsFormatter() - travelTimeFormatter.unitsStyle = .short - let formattedTravelTime = travelTimeFormatter.string(from: route.expectedTravelTime) - - print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)") - - for step in leg.steps { - let direction = step.maneuverDirection?.rawValue ?? "none" - print("\(step.instructions) [\(step.maneuverType) \(direction)]") - if step.distance > 0 { - let formattedDistance = distanceFormatter.string(fromMeters: step.distance) - print("— \(step.transportType) for \(formattedDistance) —") + case let .success(response): + if let route = response.routes?.first, let leg = route.legs.first { + print("Route via \(leg):") + + let distanceFormatter = LengthFormatter() + let formattedDistance = distanceFormatter.string(fromMeters: route.distance) + + let travelTimeFormatter = DateComponentsFormatter() + travelTimeFormatter.unitsStyle = .short + let formattedTravelTime = travelTimeFormatter.string(from: route.expectedTravelTime) + + print("Distance: \(formattedDistance); ETA: \(formattedTravelTime!)") + + for step in leg.steps { + let direction = step.maneuverDirection?.rawValue ?? "none" + print("\(step.instructions) [\(step.maneuverType) \(direction)]") + if step.distance > 0 { + let formattedDistance = distanceFormatter.string(fromMeters: step.distance) + print("— \(step.transportType) for \(formattedDistance) —") + } } - } - - if var routeCoordinates = route.shape?.coordinates, routeCoordinates.count > 0 { - // Convert the route’s coordinates into a polyline. - let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: UInt(routeCoordinates.count)) - - // Add the polyline to the map. - self.mapView.addAnnotation(routeLine) - // Fit the viewport to the polyline. - let camera = self.mapView.cameraThatFitsShape(routeLine, direction: 0, edgePadding: .zero) - self.mapView.setCamera(camera, animated: true) + if var routeCoordinates = route.shape?.coordinates, routeCoordinates.count > 0 { + // Convert the route’s coordinates into a polyline. + let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: UInt(routeCoordinates.count)) + + // Add the polyline to the map. + self.mapView.addAnnotation(routeLine) + + // Fit the viewport to the polyline. + let camera = self.mapView.cameraThatFitsShape(routeLine, direction: 0, edgePadding: .zero) + self.mapView.setCamera(camera, animated: true) + } } } + + } } @@ -144,8 +148,10 @@ class ViewController: UIViewController, MBDrawingViewDelegate { func makeMatchRequest(locations: [CLLocationCoordinate2D]) { let matchOptions = MatchOptions(coordinates: locations) - Directions.shared.calculate(matchOptions) { (response, error) in - if let error = error { + Directions.shared.calculate(matchOptions) { (session, result) in + + switch result { + case let .failure(error): let errorString = """ ⚠️ Error Enountered. ⚠️ Failure Reason: \(error.failureReason ?? "") @@ -155,19 +161,19 @@ class ViewController: UIViewController, MBDrawingViewDelegate { """ print(errorString) return + case let .success(response): + guard let matches = response.matches, let match = matches.first else { return } + if let annotations = self.mapView.annotations { + self.mapView.removeAnnotations(annotations) + } + + var routeCoordinates = match.shape!.coordinates + let coordCount = UInt(routeCoordinates.count) + let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: coordCount) + self.mapView.addAnnotation(routeLine) + self.drawingView?.reset() } - - guard let matches = response.matches, let match = matches.first else { return } - - if let annotations = self.mapView.annotations { - self.mapView.removeAnnotations(annotations) - } - - var routeCoordinates = match.shape!.coordinates - let coordCount = UInt(routeCoordinates.count) - let routeLine = MGLPolyline(coordinates: &routeCoordinates, count: coordCount) - self.mapView.addAnnotation(routeLine) - self.drawingView?.reset() + } } } diff --git a/Sources/MapboxDirections/Directions.swift b/Sources/MapboxDirections/Directions.swift index 5f6decba1..ffc65ddc1 100644 --- a/Sources/MapboxDirections/Directions.swift +++ b/Sources/MapboxDirections/Directions.swift @@ -57,23 +57,33 @@ let userAgent: String = { Each result produced by the directions object is stored in a `Route` object. Depending on the `RouteOptions` object you provide, each route may include detailed information suitable for turn-by-turn directions, or it may include only high-level information such as the distance, estimated travel time, and name of each leg of the trip. The waypoints that form the request may be conflated with nearby locations, as appropriate; the resulting waypoints are provided to the closure. */ open class Directions: NSObject { + + /** + A tuple type representing the direction session that was generated from the request. + + - parameter options: A `DirectionsOptions ` object representing the request parameter options. + + - parameter credentials: A object containing the credentials used to make the request. + */ + public typealias Session = (options: DirectionsOptions, credentials: DirectionsCredentials) + /** A closure (block) to be called when a directions request is complete. - - parameter response: A `RouteResponse` object that contains the entire payload of the Directions API solution. See `RouteResponse.swift` for more information. + - parameter session: A `Directions.Session` object containing session information - - parameter error: The error that occurred, or `nil` if the solution was obtained successfully. + - parameter result: A `Result` enum that represents the `RouteResponse` if the request returned successfully, or the error if it did not. */ - public typealias RouteCompletionHandler = (_ response: RouteResponse, _ error: DirectionsError?) -> Void + public typealias RouteCompletionHandler = (_ session: Session, _ result: Result) -> Void /** A closure (block) to be called when a map matching request is complete. - - parameter response: A `MapMatchingResponse` object that contains the entire payload of the Directions Map Matching API solution. See `MapMatchingResponse.swift` for more information. - - - parameter error: The error that occurred, or `nil` if the solution was obtained successfully. + - parameter session: A `Directions.Session` object containing session information + + - parameter result: A `Result` enum that represents the `MapMatchingResponse` if the request returned successfully, or the error if it did not. */ - public typealias MatchCompletionHandler = (_ response: MapMatchingResponse, _ error: DirectionsError?) -> Void + public typealias MatchCompletionHandler = (_ session: Session, _ result: Result) -> Void // MARK: Creating a Directions Object @@ -117,29 +127,27 @@ open class Directions: NSObject { */ @discardableResult open func calculate(_ options: RouteOptions, completionHandler: @escaping RouteCompletionHandler) -> URLSessionDataTask { options.fetchStartDate = Date() + let session = (options: options as DirectionsOptions, credentials: self.credentials) let request = urlRequest(forCalculating: options) let requestTask = URLSession.shared.dataTask(with: request) { (possibleData, possibleResponse, possibleError) in if let urlError = possibleError as? URLError { - let response = RouteResponse(httpResponse: possibleResponse as? HTTPURLResponse, options: .route(options), credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, .network(urlError)) + completionHandler(session, .failure(.network(urlError))) } return } - guard let response = possibleResponse, ["application/json", "text/html"].contains(response.mimeType), let httpResponse = response as? HTTPURLResponse else { - let response = RouteResponse(httpResponse: possibleResponse as? HTTPURLResponse, options: .route(options), credentials: self.credentials) + guard let response = possibleResponse, ["application/json", "text/html"].contains(response.mimeType) else { DispatchQueue.main.async { - completionHandler(response, .invalidResponse(possibleResponse)) + completionHandler(session, .failure(.invalidResponse(possibleResponse))) } return } guard let data = possibleData else { - let response = RouteResponse(httpResponse: httpResponse, options: .route(options), credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, .noData) + completionHandler(session, .failure(.noData)) } return } @@ -152,20 +160,17 @@ open class Directions: NSObject { guard let disposition = try? decoder.decode(ResponseDisposition.self, from: data) else { let apiError = DirectionsError(code: nil, message: nil, response: possibleResponse, underlyingError: possibleError) - let response = RouteResponse(httpResponse: httpResponse, options: .route(options), credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, apiError) + completionHandler(session, .failure(apiError)) } return } guard (disposition.code == nil && disposition.message == nil) || disposition.code == "Ok" else { let apiError = DirectionsError(code: disposition.code, message: disposition.message, response: response, underlyingError: possibleError) - let response = RouteResponse(httpResponse: httpResponse, options: .route(options), credentials: self.credentials) - DispatchQueue.main.async { - completionHandler(response, apiError) + completionHandler(session, .failure(apiError)) } return } @@ -173,19 +178,18 @@ open class Directions: NSObject { let result = try decoder.decode(RouteResponse.self, from: data) guard result.routes != nil else { DispatchQueue.main.async { - completionHandler(result, .unableToRoute) + completionHandler(session, .failure(.unableToRoute)) } return } DispatchQueue.main.async { - completionHandler(result, nil) + completionHandler(session, .success(result)) } } catch { DispatchQueue.main.async { let bailError = DirectionsError(code: nil, message: nil, response: response, underlyingError: error) - let response = RouteResponse(httpResponse: httpResponse, options: .route(options), credentials: self.credentials) - completionHandler(response, bailError) + completionHandler(session, .failure(bailError)) } } } @@ -209,30 +213,28 @@ open class Directions: NSObject { */ @discardableResult open func calculate(_ options: MatchOptions, completionHandler: @escaping MatchCompletionHandler) -> URLSessionDataTask { options.fetchStartDate = Date() + let session = (options: options as DirectionsOptions, credentials: self.credentials) let request = urlRequest(forCalculating: options) let requestTask = URLSession.shared.dataTask(with: request) { (possibleData, possibleResponse, possibleError) in if let urlError = possibleError as? URLError { - let response = MapMatchingResponse(httpResponse: possibleResponse as? HTTPURLResponse, options: options, credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, .network(urlError)) + completionHandler(session, .failure(.network(urlError))) } return } - guard let response = possibleResponse, response.mimeType == "application/json", let httpResponse = response as? HTTPURLResponse else { - let response = MapMatchingResponse(httpResponse: possibleResponse as? HTTPURLResponse, options: options, credentials: self.credentials) + guard let response = possibleResponse, response.mimeType == "application/json" else { DispatchQueue.main.async { - completionHandler(response, .invalidResponse(possibleResponse)) + completionHandler(session, .failure(.invalidResponse(possibleResponse))) } return } guard let data = possibleData else { - let response = MapMatchingResponse(httpResponse: httpResponse, options: options, credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, .noData) + completionHandler(session, .failure(.noData)) } return } @@ -245,20 +247,16 @@ open class Directions: NSObject { .credentials: self.credentials] guard let disposition = try? decoder.decode(ResponseDisposition.self, from: data) else { let apiError = DirectionsError(code: nil, message: nil, response: possibleResponse, underlyingError: possibleError) - let response = MapMatchingResponse(httpResponse: httpResponse, options: options, credentials: self.credentials) - DispatchQueue.main.async { - completionHandler(response, apiError) + completionHandler(session, .failure(apiError)) } return } guard disposition.code == "Ok" else { let apiError = DirectionsError(code: disposition.code, message: disposition.message, response: response, underlyingError: possibleError) - let response = MapMatchingResponse(httpResponse: httpResponse, options: options, credentials: self.credentials) - DispatchQueue.main.async { - completionHandler(response, apiError) + completionHandler(session, .failure(apiError)) } return } @@ -267,19 +265,18 @@ open class Directions: NSObject { guard response.matches != nil else { DispatchQueue.main.async { - completionHandler(response, .unableToRoute) + completionHandler(session, .failure(.unableToRoute)) } return } DispatchQueue.main.async { - completionHandler(response, nil) + completionHandler(session, .success(response)) } } catch { DispatchQueue.main.async { let caughtError = DirectionsError.unknown(response: response, underlying: error, code: nil, message: nil) - let response = MapMatchingResponse(httpResponse: httpResponse, options: options, credentials: self.credentials) - completionHandler(response, caughtError) + completionHandler(session, .failure(caughtError)) } } } @@ -303,29 +300,27 @@ open class Directions: NSObject { */ @discardableResult open func calculateRoutes(matching options: MatchOptions, completionHandler: @escaping RouteCompletionHandler) -> URLSessionDataTask { options.fetchStartDate = Date() + let session = (options: options as DirectionsOptions, credentials: self.credentials) let request = urlRequest(forCalculating: options) let requestTask = URLSession.shared.dataTask(with: request) { (possibleData, possibleResponse, possibleError) in if let urlError = possibleError as? URLError { - let response = RouteResponse(httpResponse: possibleResponse as? HTTPURLResponse, options: .match(options), credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, .network(urlError)) + completionHandler(session, .failure(.network(urlError))) } return } - guard let response = possibleResponse, ["application/json", "text/html"].contains(response.mimeType), let httpResponse = response as? HTTPURLResponse else { - let response = RouteResponse(httpResponse: possibleResponse as? HTTPURLResponse, options: .match(options), credentials: self.credentials) + guard let response = possibleResponse, ["application/json", "text/html"].contains(response.mimeType) else { DispatchQueue.main.async { - completionHandler(response, .invalidResponse(possibleResponse)) + completionHandler(session, .failure(.invalidResponse(possibleResponse))) } return } guard let data = possibleData else { - let response = RouteResponse(httpResponse: httpResponse, options: .match(options), credentials: self.credentials) DispatchQueue.main.async { - completionHandler(response, .noData) + completionHandler(session, .failure(.noData)) } return } @@ -339,20 +334,16 @@ open class Directions: NSObject { guard let disposition = try? decoder.decode(ResponseDisposition.self, from: data) else { let apiError = DirectionsError(code: nil, message: nil, response: possibleResponse, underlyingError: possibleError) - let response = RouteResponse(httpResponse: httpResponse, options: .match(options), credentials: self.credentials) - DispatchQueue.main.async { - completionHandler(response, apiError) + completionHandler(session, .failure(apiError)) } return } guard disposition.code == "Ok" else { let apiError = DirectionsError(code: disposition.code, message: disposition.message, response: response, underlyingError: possibleError) - let response = RouteResponse(httpResponse: httpResponse, options: .match(options), credentials: self.credentials) - DispatchQueue.main.async { - completionHandler(response, apiError) + completionHandler(session, .failure(apiError)) } return } @@ -362,19 +353,18 @@ open class Directions: NSObject { let routeResponse = try RouteResponse(matching: result, options: options, credentials: self.credentials) guard routeResponse.routes != nil else { DispatchQueue.main.async { - completionHandler(routeResponse, .unableToRoute) + completionHandler(session, .failure(.unableToRoute)) } return } DispatchQueue.main.async { - completionHandler(routeResponse, nil) + completionHandler(session, .success(routeResponse)) } } catch { DispatchQueue.main.async { let bailError = DirectionsError(code: nil, message: nil, response: response, underlyingError: error) - let response = RouteResponse(httpResponse: httpResponse, options: .match(options), credentials: self.credentials) - completionHandler(response, bailError) + completionHandler(session, .failure(bailError)) } } } diff --git a/Sources/MapboxDirections/DirectionsCredentials.swift b/Sources/MapboxDirections/DirectionsCredentials.swift index ccdba001d..3b47787ae 100644 --- a/Sources/MapboxDirections/DirectionsCredentials.swift +++ b/Sources/MapboxDirections/DirectionsCredentials.swift @@ -31,11 +31,11 @@ public struct DirectionsCredentials: Equatable { - parameter accessToken: Optional. An access token to provide. If this value is nil, the SDK will attempt to find a token from your app's `info.plist`. - parameter host: Optional. A parameter to pass a custom host. If `nil` is provided, the SDK will attempt to find a host from your app's `info.plist`, and barring that will default to `https://api.mapbox.com`. */ - public init(accessToken: String? = nil, host: URL? = nil) { - self.accessToken = accessToken ?? defaultAccessToken + public init(accessToken token: String? = nil, host: URL? = nil) { + let accessToken = token ?? defaultAccessToken precondition(accessToken != nil && !accessToken!.isEmpty, "A Mapbox access token is required. Go to . In Info.plist, set the MGLMapboxAccessToken key to your access token, or use the Directions(accessToken:host:) initializer.") - + self.accessToken = accessToken if let host = host { self.host = host } else if let defaultHostString = defaultApiEndPointURLString, let defaultHost = URL(string: defaultHostString) { diff --git a/Sources/MapboxDirections/RouteOptions.swift b/Sources/MapboxDirections/RouteOptions.swift index 3563c3c21..01a825be8 100644 --- a/Sources/MapboxDirections/RouteOptions.swift +++ b/Sources/MapboxDirections/RouteOptions.swift @@ -72,7 +72,12 @@ open class RouteOptions: DirectionsOptions { try super.init(from: decoder) } - internal convenience init(matchOptions: MatchOptions) { + /** + Initializes an equivalent route options object from a match options object. Desirable for building a navigation experience from map matching. + + - parameter matchOptions: The `MatchOptions` that is being used to convert to a `RouteOptions` object. + */ + public convenience init(matchOptions: MatchOptions) { self.init(waypoints: matchOptions.waypoints, profileIdentifier: matchOptions.profileIdentifier) self.includesSteps = matchOptions.includesSteps self.shapeFormat = matchOptions.shapeFormat diff --git a/Sources/MapboxDirections/RouteResponse.swift b/Sources/MapboxDirections/RouteResponse.swift index 2a5155f22..121e5863a 100644 --- a/Sources/MapboxDirections/RouteResponse.swift +++ b/Sources/MapboxDirections/RouteResponse.swift @@ -9,7 +9,7 @@ public struct RouteResponse { public let httpResponse: HTTPURLResponse? public let identifier: String? - public let routes: [Route]? + public var routes: [Route]? public let waypoints: [Waypoint]? public let options: ResponseOptions @@ -49,18 +49,22 @@ extension RouteResponse: Codable { let encoder = JSONEncoder() decoder.userInfo[.options] = options + decoder.userInfo[.credentials] = credentials - let routes: [Route]? = try response.matches?.compactMap({ (match) -> Route? in - let json = try encoder.encode(match) - let route = try decoder.decode(Route.self, from: json) - return route - }) - - let waypoints: [Waypoint]? = try response.tracepoints?.compactMap({ (trace) -> Waypoint? in - let json = try encoder.encode(trace) - let waypoint = try decoder.decode(Waypoint.self, from: json) - return waypoint - }) + var routes: [Route]? + + if let matches = response.matches { + let matchesData = try encoder.encode(matches) + routes = try decoder.decode([Route].self, from: matchesData) + } + + var waypoints: [Waypoint]? + + if let tracepoints = response.tracepoints { + let filtered = tracepoints.compactMap { $0 } + let tracepointsData = try encoder.encode(filtered) + waypoints = try decoder.decode([Waypoint].self, from: tracepointsData) + } self.init(httpResponse: response.httpResponse, identifier: nil, routes: routes, waypoints: waypoints, options: .match(options), credentials: credentials) } diff --git a/Tests/MapboxDirectionsTests/AnnotationTests.swift b/Tests/MapboxDirectionsTests/AnnotationTests.swift index b00193ab0..1004c5567 100644 --- a/Tests/MapboxDirectionsTests/AnnotationTests.swift +++ b/Tests/MapboxDirectionsTests/AnnotationTests.swift @@ -38,14 +38,19 @@ class AnnotationTests: XCTestCase { options.routeShapeResolution = .full options.attributeOptions = [.distance, .expectedTravelTime, .speed, .congestionLevel, .maximumSpeedLimit] var route: Route? - let task = Directions(credentials: BogusCredentials).calculate(options) { (response, error) in - XCTAssertNil(error, "Error: \(error!.localizedDescription)") - - XCTAssertNotNil(response.routes) - XCTAssertEqual(response.routes!.count, 1) - route = response.routes!.first! + let task = Directions(credentials: BogusCredentials).calculate(options) { (session, disposition) in - expectation.fulfill() + switch disposition { + case let .failure(error): + XCTFail("Error! \(error)") + case let .success(response): + XCTAssertNotNil(response.routes) + XCTAssertEqual(response.routes!.count, 1) + route = response.routes!.first! + + expectation.fulfill() + } + } XCTAssertNotNil(task) diff --git a/Tests/MapboxDirectionsTests/DirectionsTests.swift b/Tests/MapboxDirectionsTests/DirectionsTests.swift index 2239facfb..e325a08c3 100644 --- a/Tests/MapboxDirectionsTests/DirectionsTests.swift +++ b/Tests/MapboxDirectionsTests/DirectionsTests.swift @@ -91,11 +91,15 @@ class DirectionsTests: XCTestCase { let directions = Directions(credentials: BogusCredentials) let opts = RouteOptions(locations: [one, two]) - directions.calculate(opts, completionHandler: { (response, error) in - expectation.fulfill() - XCTAssertNil(response.routes, "Unexpected route response") - XCTAssertNotNil(error, "No error returned") + directions.calculate(opts, completionHandler: { (session, result) in + + guard case let .failure(error) = result else { + XCTFail("Expecting error, none returned.") + return + } + XCTAssertEqual(error, .requestTooLarge) + expectation.fulfill() }) wait(for: [expectation], timeout: 2.0) } @@ -113,16 +117,19 @@ class DirectionsTests: XCTestCase { let directions = Directions(credentials: BogusCredentials) let opts = RouteOptions(locations: [one, two]) - directions.calculate(opts, completionHandler: { (response, error) in - expectation.fulfill() - XCTAssertNil(response.routes, "Unexpected route response") - XCTAssertNotNil(error, "No error returned") - switch error { - case .invalidResponse?: - break // pass - default: - XCTFail("Wrong type of error.") + directions.calculate(opts, completionHandler: { (session, result) in + defer { expectation.fulfill() } + + guard case let .failure(error) = result else { + XCTFail("Expecting an error, none returned. \(result)") + return + } + + guard case .invalidResponse(_) = error else { + XCTFail("Wrong error type returned.") + return } + }) wait(for: [expectation], timeout: 2.0) } @@ -157,20 +164,20 @@ class DirectionsTests: XCTestCase { let directions = Directions(credentials: BogusCredentials) let opts = RouteOptions(locations: [one, two]) - directions.calculate(opts, completionHandler: { (response, error) in - expectation.fulfill() - XCTAssertNil(response.routes, "Unexpected route response") + directions.calculate(opts, completionHandler: { (session, result) in + defer { expectation.fulfill() } - guard let error = error else { - XCTFail("Missing 'no connection' error.") + guard case let .failure(error) = result else { + XCTFail("Error expected, none returned. \(result)") return } - if case DirectionsError.network(let urlError) = error { - XCTAssertEqual(urlError, notConnected) - } else { - XCTFail("correct error not found") + guard case let .network(err) = error else { + XCTFail("Wrong error type returned. \(error)") + return } + + XCTAssertEqual(err, notConnected) }) wait(for: [expectation], timeout: 2.0) } diff --git a/Tests/MapboxDirectionsTests/MatchTests.swift b/Tests/MapboxDirectionsTests/MatchTests.swift index c97fdd04e..a3ecc834a 100644 --- a/Tests/MapboxDirectionsTests/MatchTests.swift +++ b/Tests/MapboxDirectionsTests/MatchTests.swift @@ -35,9 +35,13 @@ class MatchTests: XCTestCase { matchOptions.includesSteps = true matchOptions.routeShapeResolution = .full - let task = Directions(credentials: BogusCredentials).calculate(matchOptions) { (resp, error) in - XCTAssertNil(error, "Error: \(error!)") + let task = Directions(credentials: BogusCredentials).calculate(matchOptions) { (session, result) in + guard case let .success(resp) = result else { + XCTFail("Encountered unexpected error. \(result)") + return + } + response = resp expectation.fulfill() @@ -120,8 +124,12 @@ class MatchTests: XCTestCase { matchOptions.includesSteps = true matchOptions.routeShapeResolution = .full - let task = Directions(credentials: BogusCredentials).calculate(matchOptions) { (resp, error) in - XCTAssertNil(error, "Error: \(error!)") + let task = Directions(credentials: BogusCredentials).calculate(matchOptions) { (session, result) in + guard case let .success(resp) = result else { + XCTFail("Encountered unexpected error. \(result)") + return + } + response = resp expectation.fulfill() } diff --git a/Tests/MapboxDirectionsTests/RoutableMatchTests.swift b/Tests/MapboxDirectionsTests/RoutableMatchTests.swift index a9f61eb47..7d84bd592 100644 --- a/Tests/MapboxDirectionsTests/RoutableMatchTests.swift +++ b/Tests/MapboxDirectionsTests/RoutableMatchTests.swift @@ -35,12 +35,16 @@ class RoutableMatchTest: XCTestCase { waypoint.separatesLegs = false } - let task = Directions(credentials: BogusCredentials).calculateRoutes(matching: matchOptions) { (response, error) in - XCTAssertNil(error, "Error: \(error!)") - - routeResponse = response + let task = Directions(credentials: BogusCredentials).calculateRoutes(matching: matchOptions) { (session, result) in - expectation.fulfill() + switch (result) { + case let .failure(error): + XCTFail("Error: \(error)") + case let .success(response): + routeResponse = response + expectation.fulfill() + } + } XCTAssertNotNil(task) diff --git a/Tests/MapboxDirectionsTests/V5Tests.swift b/Tests/MapboxDirectionsTests/V5Tests.swift index 0f9fb5d77..27303721c 100644 --- a/Tests/MapboxDirectionsTests/V5Tests.swift +++ b/Tests/MapboxDirectionsTests/V5Tests.swift @@ -48,12 +48,15 @@ class V5Tests: XCTestCase { options.locale = Locale(identifier: "en_US") options.includesExitRoundaboutManeuver = true var response: RouteResponse! - let task = Directions(credentials: BogusCredentials).calculate(options) { (resp, error) in - XCTAssertNil(error, "Error: \(error!)") - - response = resp + let task = Directions(credentials: BogusCredentials).calculate(options) { (session, result) in - expectation.fulfill() + switch result { + case let .failure(error): + XCTFail("Error: \(error)") + case let .success(resp): + response = resp + expectation.fulfill() + } } XCTAssertNotNil(task) @@ -246,9 +249,11 @@ class V5Tests: XCTestCase { options.includesExitRoundaboutManeuver = true var route: Route? - let task = Directions(credentials: BogusCredentials).calculate(options) { (response, error) in - XCTAssertNil(error, "Error: \(error!)") - + let task = Directions(credentials: BogusCredentials).calculate(options) { (session, result) in + guard case let .success(response) = result else { + XCTFail("Encountered unexpected error. \(result)") + return + } XCTAssertEqual(response.waypoints?.count, 3) XCTAssertNotNil(response.routes) diff --git a/Tests/MapboxDirectionsTests/VisualInstructionTests.swift b/Tests/MapboxDirectionsTests/VisualInstructionTests.swift index 8a4dde9a6..58d1e000b 100644 --- a/Tests/MapboxDirectionsTests/VisualInstructionTests.swift +++ b/Tests/MapboxDirectionsTests/VisualInstructionTests.swift @@ -96,12 +96,16 @@ class VisualInstructionsTests: XCTestCase { options.distanceMeasurementSystem = .imperial options.includesVisualInstructions = true var response: RouteResponse! - let task = Directions(credentials: BogusCredentials).calculate(options) { (resp, error) in - XCTAssertNil(error, "Error: \(error!.localizedDescription)") + let task = Directions(credentials: BogusCredentials).calculate(options) { (session, result) in - response = resp + switch result { + case let .failure(error): + XCTFail("Error! \(error)") + case let .success(resp): + response = resp + expectation.fulfill() + } - expectation.fulfill() } XCTAssertNotNil(task) @@ -189,12 +193,14 @@ class VisualInstructionsTests: XCTestCase { options.includesVisualInstructions = true var response: RouteResponse! - let task = Directions(credentials: BogusCredentials).calculate(options) { (resp, error) in - XCTAssertNil(error, "Error: \(error!.localizedDescription)") - - response = resp - - expectation.fulfill() + let task = Directions(credentials: BogusCredentials).calculate(options) { (session, result) in + switch result { + case let .failure(error): + XCTFail("Error! \(error)") + case let .success(resp): + response = resp + expectation.fulfill() + } } XCTAssertNotNil(task) @@ -262,8 +268,12 @@ class VisualInstructionsTests: XCTestCase { options.includesVisualInstructions = true var response: RouteResponse! - let task = Directions(credentials: BogusCredentials).calculate(options) { (resp, error) in - XCTAssertNil(error, "Error: \(error!.localizedDescription)") + let task = Directions(credentials: BogusCredentials).calculate(options) { (session, result) in + + guard case let .success(resp) = result else { + XCTFail("Encountered unexpected error. \(result)") + return + } response = resp