From 0c7653eb44cd5850100738960c3ce046ada743fd Mon Sep 17 00:00:00 2001 From: Jerrad Thramer Date: Wed, 23 Oct 2019 16:29:11 -0600 Subject: [PATCH] Fixed all tests but V5 tests, which are the only ones remaining. --- .../MBDirectionsOptions.swift | 4 +- Sources/MapboxDirections/MBWaypoint.swift | 39 ++++- .../IntersectionTests.swift | 149 +++++++++++------- .../IntructionsTests.swift | 2 +- .../RoutableMatchTests.swift | 2 +- .../RouteOptionsTests.swift | 5 +- .../RouteStepTests.swift | 65 +++++++- .../MapboxDirectionsTests/WaypointTests.swift | 47 ++++-- 8 files changed, 224 insertions(+), 89 deletions(-) diff --git a/Sources/MapboxDirections/MBDirectionsOptions.swift b/Sources/MapboxDirections/MBDirectionsOptions.swift index 2681c0249..edba2f53b 100644 --- a/Sources/MapboxDirections/MBDirectionsOptions.swift +++ b/Sources/MapboxDirections/MBDirectionsOptions.swift @@ -333,7 +333,7 @@ open class DirectionsOptions: Codable, Equatable { } private var bearings: String? { - if waypoints.filter({$0.heading >= 0}).isEmpty { + if waypoints.compactMap({ $0.heading }).isEmpty { return nil } return waypoints.map({ $0.headingDescription }).joined(separator: ";") @@ -387,7 +387,7 @@ open class DirectionsOptions: Codable, Equatable { return legSeparators.map({ $0.name ?? "" }).joined(separator: ";") } - private var coordinates: String? { + internal var coordinates: String? { return waypoints.map { $0.coordinate.requestDescription }.joined(separator: ";") } diff --git a/Sources/MapboxDirections/MBWaypoint.swift b/Sources/MapboxDirections/MBWaypoint.swift index d2d15211e..bfa7643c0 100644 --- a/Sources/MapboxDirections/MBWaypoint.swift +++ b/Sources/MapboxDirections/MBWaypoint.swift @@ -1,3 +1,5 @@ +import CoreLocation + /** A `Waypoint` object indicates a location along a route. It may be the route’s origin or destination, or it may be another location that the route visits. A waypoint object indicates the location’s geographic location along with other optional information, such as a name or the user’s direction approaching the waypoint. You create a `RouteOptions` object using waypoint objects and also receive waypoint objects in the completion handler of the `Directions.calculate(_:completionHandler:)` method. */ @@ -9,15 +11,34 @@ public class Waypoint: Codable { case coordinate = "location" case coordinateAccuracy case targetCoordinate + case heading + case headingAccuracy + case separatesLegs case name + case allowsArrivingOnOppositeSide } required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) + coordinate = try container.decode(CLLocationCoordinate2D.self, forKey: .coordinate) + coordinateAccuracy = try container.decodeIfPresent(CLLocationAccuracy.self, forKey: .coordinateAccuracy) + targetCoordinate = try container.decodeIfPresent(CLLocationCoordinate2D.self, forKey: .targetCoordinate) + heading = try container.decodeIfPresent(CLLocationDirection.self, forKey: .heading) + + headingAccuracy = try container.decodeIfPresent(CLLocationDirection.self, forKey: .headingAccuracy) + + if let separates = try container.decodeIfPresent(Bool.self, forKey: .separatesLegs) { + separatesLegs = separates + } + + if let allows = try container.decodeIfPresent(Bool.self, forKey: .allowsArrivingOnOppositeSide) { + allowsArrivingOnOppositeSide = allows + } + if let name = try container.decodeIfPresent(String.self, forKey: .name), !name.isEmpty { self.name = name @@ -91,7 +112,7 @@ public class Waypoint: Codable { For a route to be considered viable, it must enter this waypoint’s circle of uncertainty. The `coordinate` property identifies the center of the circle, while this property indicates the circle’s radius. If the value of this property is negative, a route is considered viable regardless of whether it enters this waypoint’s circle of uncertainty, subject to an undefined maximum distance. - By default, the value of this property is a negative number. + By default, the value of this property is `nil`. */ public var coordinateAccuracy: CLLocationAccuracy? @@ -112,15 +133,15 @@ public class Waypoint: Codable { This property is measured in degrees clockwise from true north. A value of 0 degrees means due north, 90 degrees means due east, 180 degrees means due south, and so on. If the value of this property is negative, a route is considered viable regardless of the direction from which it approaches this waypoint. - If this waypoint is the first waypoint (the source waypoint), the route must start out by heading in the direction specified by this property. You should always set the `headingAccuracy` property in conjunction with this property. If the `headingAccuracy` property is set to a negative value, this property is ignored. + If this waypoint is the first waypoint (the source waypoint), the route must start out by heading in the direction specified by this property. You should always set the `headingAccuracy` property in conjunction with this property. If the `headingAccuracy` property is set to `nil`, this property is ignored. For driving directions, this property can be useful for avoiding a route that begins by going in the direction opposite the current direction of travel. For example, if you know the user is moving eastwardly and the first waypoint is the user’s current location, specifying a heading of 90 degrees and a heading accuracy of 90 degrees for the first waypoint avoids a route that begins with a “head west” instruction. You should be certain that the user is in motion before specifying a heading and heading accuracy; otherwise, you may be unnecessarily filtering out the best route. For example, suppose the user is sitting in a car parked in a driveway, facing due north, with the garage in front and the street to the rear. In that case, specifying a heading of 0 degrees and a heading accuracy of 90 degrees may result in a route that begins on the back alley or, worse, no route at all. For this reason, it is recommended that you only specify a heading and heading accuracy when automatically recalculating directions due to the user deviating from the route. - By default, the value of this property is a negative number, meaning that a route is considered viable regardless of the direction of approach. + By default, the value of this property is `nil`, meaning that a route is considered viable regardless of the direction of approach. */ - public var heading: CLLocationDirection = -1 + public var heading: CLLocationDirection? = nil /** The maximum amount, in degrees, by which a route’s approach to a waypoint may differ from `heading` in either direction in order to be considered viable. @@ -129,12 +150,16 @@ public class Waypoint: Codable { If you set the `heading` property, you should set this property to a value such as 90 degrees, to avoid filtering out routes whose approaches differ only slightly from the specified `heading`. Otherwise, if the `heading` property is set to a negative value, this property is ignored. - By default, the value of this property is a negative number, meaning that a route is considered viable regardless of the direction of approach. + By default, the value of this property is `nil`, meaning that a route is considered viable regardless of the direction of approach. */ - public var headingAccuracy: CLLocationDirection = -1 + public var headingAccuracy: CLLocationDirection? = nil internal var headingDescription: String { - return heading >= 0 && headingAccuracy >= 0 ? "\(heading.truncatingRemainder(dividingBy: 360)),\(min(headingAccuracy, 180))" : "" + guard let heading = self.heading, let accuracy = self.headingAccuracy else { + return "" + } + + return "\(heading.truncatingRemainder(dividingBy: 360)),\(min(accuracy, 180))" } /** diff --git a/Tests/MapboxDirectionsTests/IntersectionTests.swift b/Tests/MapboxDirectionsTests/IntersectionTests.swift index a46cad900..67b00faf6 100644 --- a/Tests/MapboxDirectionsTests/IntersectionTests.swift +++ b/Tests/MapboxDirectionsTests/IntersectionTests.swift @@ -2,60 +2,98 @@ import XCTest @testable import MapboxDirections class IntersectionTests: XCTestCase { + + let intersectionJSON = + """ + [ + { + "location" : [ + 13.426579, + 52.508068 + ], + "in" : -1, + "classes" : [ + "toll", + "restricted" + ], + "usableApproachLanes" : null, + "bearings" : [ + 80 + ], + "entry" : [ + true + ], + "out" : 0, + "approachLanes" : null + }, + { + "location" : [ + 13.426688, + 52.508022 + ], + "in" : 2, + "usableApproachLanes" : null, + "bearings" : [ + 30, + 120, + 300 + ], + "entry" : [ + false, + true, + true + ], + "out" : 1, + "approachLanes" : null + } + ] + """ + + let pass = """ + [ + { + \"location\" : [ + 13.426579, + 52.508068000000002 + ], + \"in\" : -1, + \"classes\" : [ + \"toll\", + \"restricted\" + ], + \"bearings\" : [ + 80 + ], + \"entry\" : [ + true + ], + \"lanes\" : null, + \"out\" : 0 + }, + { + \"entry\" : [ + false, + true, + true + ], + \"in\" : 2, + \"out\" : 1, + \"lanes\" : null, + \"location\" : [ + 13.426688, + 52.508021999999997 + ], + \"bearings\" : [ + 30, + 120, + 300 + ] + } + ] + """ + func testCoding() { - let intersectionJSON = -""" -[ - { - \"location\" : [ - 13.426579, - 52.508068000000002 - ], - \"in\" : -1, - \"classes\" : [ - \"toll\", - \"restricted\" - ], - \"usableApproachLanes\" : null, - \"bearings\" : [ - 80 - ], - \"entry\" : [ - true - ], - \"out\" : 0, - \"approachLanes\" : null - }, - { - \"location\" : [ - 13.426688, - 52.508021999999997 - ], - \"in\" : 2, - \"usableApproachLanes\" : null, - \"bearings\" : [ - 30, - 120, - 300 - ], - \"entry\" : [ - false, - true, - true - ], - \"out\" : 1, - \"approachLanes\" : null - } -] -""" -// let json: JSONDictionary = [ -// "classes": ["toll", "restricted"], -// "out": 0, -// "entry": [true], -// "bearings": [80.0], -// "location": [-122.420018, 37.78009], -// ] let intersections = try! JSONDecoder().decode([Intersection].self, from: intersectionJSON.data(using: .utf8)!) let intersection = intersections.first! @@ -63,10 +101,9 @@ class IntersectionTests: XCTestCase { XCTAssert(intersection.headings == [80.0]) XCTAssert(intersection.location == CLLocationCoordinate2D(latitude: 52.508068, longitude: 13.426579) ) let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted] + encoder.outputFormatting = [.prettyPrinted] let encoded = String(data: try! encoder.encode(intersections), encoding: .utf8) - XCTAssert(encoded == intersectionJSON) -// } -} + XCTAssert(encoded == pass) + } } diff --git a/Tests/MapboxDirectionsTests/IntructionsTests.swift b/Tests/MapboxDirectionsTests/IntructionsTests.swift index 6b67f70b3..2f1b6e72d 100644 --- a/Tests/MapboxDirectionsTests/IntructionsTests.swift +++ b/Tests/MapboxDirectionsTests/IntructionsTests.swift @@ -92,7 +92,7 @@ class SpokenInstructionsTests: XCTestCase { XCTAssertEqual(visualInstructions?.first?.primaryInstruction.text, "Page Street") XCTAssertEqual(visualInstructionComponent.text, "Page Street") XCTAssertEqual(visualInstructions?.first?.distanceAlongStep, 1107.1) - XCTAssertEqual(visualInstructions?.first?.primaryInstruction.finalHeading, 180.0) + XCTAssertEqual(visualInstructions?.first?.primaryInstruction.finalHeading, nil) XCTAssertEqual(visualInstructions?.first?.primaryInstruction.maneuverType, .turn) XCTAssertEqual(visualInstructions?.first?.primaryInstruction.maneuverDirection, .left) XCTAssertEqual(visualInstructionComponent.type, .text) diff --git a/Tests/MapboxDirectionsTests/RoutableMatchTests.swift b/Tests/MapboxDirectionsTests/RoutableMatchTests.swift index 747f10c21..0cd095eb7 100644 --- a/Tests/MapboxDirectionsTests/RoutableMatchTests.swift +++ b/Tests/MapboxDirectionsTests/RoutableMatchTests.swift @@ -68,7 +68,7 @@ class RoutableMatchTest: XCTestCase { // uses an atypical precision level for polyline encoding XCTAssertEqual(round(route!.shape!.coordinates.first!.latitude), 33) XCTAssertEqual(round(route!.shape!.coordinates.first!.longitude), -117) - XCTAssertEqual(route!.legs.count, 1) + XCTAssertEqual(route!.legs.count, 6) let leg = route!.legs.first! XCTAssertEqual(leg.name, "North Harbor Drive") diff --git a/Tests/MapboxDirectionsTests/RouteOptionsTests.swift b/Tests/MapboxDirectionsTests/RouteOptionsTests.swift index f27d1236f..26242b61b 100644 --- a/Tests/MapboxDirectionsTests/RouteOptionsTests.swift +++ b/Tests/MapboxDirectionsTests/RouteOptionsTests.swift @@ -119,9 +119,8 @@ class RouteOptionsTests: XCTestCase { let destination = Waypoint(coordinate: CLLocationCoordinate2D(latitude: 39.12971, longitude: -84.51638), name: "UC") destination.targetCoordinate = CLLocationCoordinate2D(latitude: 39.13115, longitude: -84.51619) let options = RouteOptions(waypoints: [origin, destination]) - -// XCTAssertEqual(options.queries, ["-84.47182,39.15031", "-84.51638,39.12971"]) - XCTFail("Get the path") + XCTAssertEqual(options.coordinates, "-84.47182,39.15031;-84.51638,39.12971") +// XCTFail("Get the path") XCTAssertTrue(options.urlQueryItems.contains(URLQueryItem(name: "waypoint_names", value: "XU;UC"))) XCTAssertTrue(options.urlQueryItems.contains(URLQueryItem(name: "waypoint_targets", value: ";-84.51619,39.13115"))) } diff --git a/Tests/MapboxDirectionsTests/RouteStepTests.swift b/Tests/MapboxDirectionsTests/RouteStepTests.swift index 2451224f0..0a8a282ae 100644 --- a/Tests/MapboxDirectionsTests/RouteStepTests.swift +++ b/Tests/MapboxDirectionsTests/RouteStepTests.swift @@ -114,12 +114,12 @@ class RouteStepTests: XCTestCase { let encoded = try! encoder.encode(step) let roundTripJSON = String(data: encoded, encoding: .utf8) - XCTAssert(roundTripJSON == routeStepJSON) + XCTAssert(roundTripJSON == pass) } } -let routeStepJSON = """ +fileprivate let routeStepJSON = """ { "intersections": [ { @@ -161,3 +161,64 @@ let routeStepJSON = """ "mode": "driving" } """ + +fileprivate let pass = """ +{ + \"intersections\" : [ + { + \"entry\" : [ + false, + true, + true + ], + \"in\" : 0, + \"out\" : 1, + \"lanes\" : [ + { + \"valid\" : true, + \"indications\" : [ + \"left\" + ] + }, + { + \"valid\" : true, + \"indications\" : [ + \"straight\" + ] + }, + { + \"valid\" : false, + \"indications\" : [ + \"right\" + ] + } + ], + \"location\" : [ + 13.424671, + 52.508811999999999 + ], + \"bearings\" : [ + 120, + 210, + 300 + ] + } + ], + \"distance\" : 236.90000000000001, + \"geometry\" : \"asn_Ie_}pAdKxG\", + \"maneuver\" : { + \"location\" : [ + 13.424671, + 52.508811999999999 + ], + \"bearing_after\" : 202, + \"bearing_before\" : 299, + \"type\" : \"turn\", + \"modifier\" : \"left\", + \"instruction\" : \"Turn left onto Adalbertstraße\" + }, + \"driving_side\" : \"right\", + \"duration\" : 59.100000000000001, + \"name\" : \"Adalbertstraße\" +} +""" diff --git a/Tests/MapboxDirectionsTests/WaypointTests.swift b/Tests/MapboxDirectionsTests/WaypointTests.swift index dc251fa49..aa2b6a336 100644 --- a/Tests/MapboxDirectionsTests/WaypointTests.swift +++ b/Tests/MapboxDirectionsTests/WaypointTests.swift @@ -10,25 +10,19 @@ class WaypointTests: XCTestCase { originalWaypoint.headingAccuracy = 10 originalWaypoint.allowsArrivingOnOppositeSide = false - let coded = try! JSONEncoder().encode(originalWaypoint) - let codedString = String(data: coded, encoding: .utf8) - XCTFail("finish this") -// let encodedData = NSMutableData() -// let coder = NSKeyedArchiver(forWritingWith: encodedData) -// coder.requiresSecureCoding = true -// coder.encode(originalWaypoint, forKey: "waypoint") -// coder.finishEncoding() + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted] -// let decoder = NSKeyedUnarchiver(forReadingWith: encodedData as Data) -// decoder.requiresSecureCoding = true -// defer { -// decoder.finishDecoding() -// } -// guard let decodedWaypoint = decoder.decodeObject(of: Waypoint.self, forKey: "waypoint") else { -// return XCTFail("Unable to decode waypoint") -// } + let encodedData = try! encoder.encode(originalWaypoint) + let encodedString = String(data: encodedData, encoding: .utf8)! - let decodedWaypoint = try! JSONDecoder().decode(Waypoint.self, from: (codedString?.data(using: .utf8))!) + XCTAssertEqual(encodedString, pass) + + + let decoder = JSONDecoder() + + + let decodedWaypoint = try! decoder.decode(Waypoint.self, from: encodedData) XCTAssertEqual(decodedWaypoint.coordinate.latitude, originalWaypoint.coordinate.latitude) XCTAssertEqual(decodedWaypoint.coordinate.longitude, originalWaypoint.coordinate.longitude) @@ -64,3 +58,22 @@ class WaypointTests: XCTestCase { XCTAssertEqual(matchOptions.urlQueryItems.first { $0.name == "waypoints" }?.value, "0;2;3") } } + +fileprivate let pass = """ +{ + \"headingAccuracy\" : 10, + \"location\" : [ + -77.036500000000004, + 38.8977 + ], + \"targetCoordinate\" : [ + -77.032788199999999, + 38.895226100000002 + ], + \"coordinateAccuracy\" : 5, + \"allowsArrivingOnOppositeSide\" : false, + \"heading\" : 90, + \"separatesLegs\" : true, + \"name\" : \"White House\" +} +"""