diff --git a/MapboxGeocoder.xcodeproj/project.pbxproj b/MapboxGeocoder.xcodeproj/project.pbxproj index 6ca6f86..2532d97 100644 --- a/MapboxGeocoder.xcodeproj/project.pbxproj +++ b/MapboxGeocoder.xcodeproj/project.pbxproj @@ -7,6 +7,42 @@ objects = { /* Begin PBXBuildFile section */ + 079F41E820E42EEF007EEB5E /* BatchGeocodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 079F41E720E42EEF007EEB5E /* BatchGeocodingTests.swift */; }; + 079F41E920E42EEF007EEB5E /* BatchGeocodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 079F41E720E42EEF007EEB5E /* BatchGeocodingTests.swift */; }; + 079F41EA20E42EEF007EEB5E /* BatchGeocodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 079F41E720E42EEF007EEB5E /* BatchGeocodingTests.swift */; }; + 07CF859F20F6DE61007B26B6 /* permanent_invalid_token.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF859E20F6DE61007B26B6 /* permanent_invalid_token.json */; }; + 07CF85A020F6DE61007B26B6 /* permanent_invalid_token.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF859E20F6DE61007B26B6 /* permanent_invalid_token.json */; }; + 07CF85A120F6DE61007B26B6 /* permanent_invalid_token.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF859E20F6DE61007B26B6 /* permanent_invalid_token.json */; }; + 07CF85A320F6DED8007B26B6 /* permanent_invalid_token_scope.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85A220F6DED8007B26B6 /* permanent_invalid_token_scope.json */; }; + 07CF85A420F6DED8007B26B6 /* permanent_invalid_token_scope.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85A220F6DED8007B26B6 /* permanent_invalid_token_scope.json */; }; + 07CF85A520F6DED8007B26B6 /* permanent_invalid_token_scope.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85A220F6DED8007B26B6 /* permanent_invalid_token_scope.json */; }; + 07CF85A720F6DF0F007B26B6 /* permanent_invalid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85A620F6DF0E007B26B6 /* permanent_invalid.json */; }; + 07CF85A820F6DF0F007B26B6 /* permanent_invalid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85A620F6DF0E007B26B6 /* permanent_invalid.json */; }; + 07CF85A920F6DF0F007B26B6 /* permanent_invalid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85A620F6DF0E007B26B6 /* permanent_invalid.json */; }; + 07CF85AB20F6DF1E007B26B6 /* permanent_forward_single_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85AA20F6DF1D007B26B6 /* permanent_forward_single_no_results.json */; }; + 07CF85AC20F6DF1E007B26B6 /* permanent_forward_single_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85AA20F6DF1D007B26B6 /* permanent_forward_single_no_results.json */; }; + 07CF85AD20F6DF1E007B26B6 /* permanent_forward_single_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85AA20F6DF1D007B26B6 /* permanent_forward_single_no_results.json */; }; + 07CF85AF20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85AE20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json */; }; + 07CF85B020F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85AE20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json */; }; + 07CF85B120F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85AE20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json */; }; + 07CF85B320F6DF3C007B26B6 /* permanent_forward_multiple_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85B220F6DF3C007B26B6 /* permanent_forward_multiple_valid.json */; }; + 07CF85B420F6DF3C007B26B6 /* permanent_forward_multiple_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85B220F6DF3C007B26B6 /* permanent_forward_multiple_valid.json */; }; + 07CF85B520F6DF3C007B26B6 /* permanent_forward_multiple_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85B220F6DF3C007B26B6 /* permanent_forward_multiple_valid.json */; }; + 07CF85B720F6DF55007B26B6 /* permanent_forward_single_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85B620F6DF55007B26B6 /* permanent_forward_single_valid.json */; }; + 07CF85B820F6DF55007B26B6 /* permanent_forward_single_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85B620F6DF55007B26B6 /* permanent_forward_single_valid.json */; }; + 07CF85B920F6DF55007B26B6 /* permanent_forward_single_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85B620F6DF55007B26B6 /* permanent_forward_single_valid.json */; }; + 07CF85BB20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85BA20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json */; }; + 07CF85BC20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85BA20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json */; }; + 07CF85BD20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85BA20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json */; }; + 07CF85BF20F6DF86007B26B6 /* permanent_reverse_single_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85BE20F6DF86007B26B6 /* permanent_reverse_single_no_results.json */; }; + 07CF85C020F6DF86007B26B6 /* permanent_reverse_single_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85BE20F6DF86007B26B6 /* permanent_reverse_single_no_results.json */; }; + 07CF85C120F6DF86007B26B6 /* permanent_reverse_single_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85BE20F6DF86007B26B6 /* permanent_reverse_single_no_results.json */; }; + 07CF85C320F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85C220F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json */; }; + 07CF85C420F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85C220F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json */; }; + 07CF85C520F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85C220F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json */; }; + 07CF85C720F6DFEB007B26B6 /* permanent_reverse_single_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85C620F6DFEB007B26B6 /* permanent_reverse_single_valid.json */; }; + 07CF85C820F6DFEB007B26B6 /* permanent_reverse_single_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85C620F6DFEB007B26B6 /* permanent_reverse_single_valid.json */; }; + 07CF85C920F6DFEB007B26B6 /* permanent_reverse_single_valid.json in Resources */ = {isa = PBXBuildFile; fileRef = 07CF85C620F6DFEB007B26B6 /* permanent_reverse_single_valid.json */; }; 35506B8B200F856400629509 /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35506B8A200F856400629509 /* BridgingTests.m */; }; 35506B8C200F856400629509 /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35506B8A200F856400629509 /* BridgingTests.m */; }; 35506B8D200F856400629509 /* BridgingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35506B8A200F856400629509 /* BridgingTests.m */; }; @@ -170,6 +206,18 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 079F41E720E42EEF007EEB5E /* BatchGeocodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BatchGeocodingTests.swift; sourceTree = ""; }; + 07CF859E20F6DE61007B26B6 /* permanent_invalid_token.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_invalid_token.json; sourceTree = ""; }; + 07CF85A220F6DED8007B26B6 /* permanent_invalid_token_scope.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_invalid_token_scope.json; sourceTree = ""; }; + 07CF85A620F6DF0E007B26B6 /* permanent_invalid.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_invalid.json; sourceTree = ""; }; + 07CF85AA20F6DF1D007B26B6 /* permanent_forward_single_no_results.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_forward_single_no_results.json; sourceTree = ""; }; + 07CF85AE20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_forward_multiple_no_results.json; sourceTree = ""; }; + 07CF85B220F6DF3C007B26B6 /* permanent_forward_multiple_valid.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_forward_multiple_valid.json; sourceTree = ""; }; + 07CF85B620F6DF55007B26B6 /* permanent_forward_single_valid.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_forward_single_valid.json; sourceTree = ""; }; + 07CF85BA20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_reverse_multiple_valid.json; sourceTree = ""; }; + 07CF85BE20F6DF86007B26B6 /* permanent_reverse_single_no_results.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_reverse_single_no_results.json; sourceTree = ""; }; + 07CF85C220F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_reverse_multiple_no_results.json; sourceTree = ""; }; + 07CF85C620F6DFEB007B26B6 /* permanent_reverse_single_valid.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = permanent_reverse_single_valid.json; sourceTree = ""; }; 35506B8A200F856400629509 /* BridgingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BridgingTests.m; sourceTree = ""; }; 357B4357202CC90A00735521 /* reverse_address.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = reverse_address.json; sourceTree = ""; }; DA1AC0211E5C23B8006DF1D6 /* Contacts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Contacts.framework; path = System/Library/Frameworks/Contacts.framework; sourceTree = SDKROOT; }; @@ -402,6 +450,7 @@ DDF1E84B1BD6F7BA00C40C78 /* MapboxGeocoderTests */ = { isa = PBXGroup; children = ( + 079F41E720E42EEF007EEB5E /* BatchGeocodingTests.swift */, DA701C001CB1292C00B0E520 /* GeocoderTests.swift */, DA210BAA1CB4BE73008088FD /* ForwardGeocodingTests.swift */, DDF1E84C1BD6F7BA00C40C78 /* ReverseGeocodingTests.swift */, @@ -416,6 +465,17 @@ DDF1E8571BD700EB00C40C78 /* Fixtures */ = { isa = PBXGroup; children = ( + 07CF85A220F6DED8007B26B6 /* permanent_invalid_token_scope.json */, + 07CF859E20F6DE61007B26B6 /* permanent_invalid_token.json */, + 07CF85A620F6DF0E007B26B6 /* permanent_invalid.json */, + 07CF85AA20F6DF1D007B26B6 /* permanent_forward_single_no_results.json */, + 07CF85AE20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json */, + 07CF85B220F6DF3C007B26B6 /* permanent_forward_multiple_valid.json */, + 07CF85B620F6DF55007B26B6 /* permanent_forward_single_valid.json */, + 07CF85C620F6DFEB007B26B6 /* permanent_reverse_single_valid.json */, + 07CF85BA20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json */, + 07CF85BE20F6DF86007B26B6 /* permanent_reverse_single_no_results.json */, + 07CF85C220F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json */, DA210BAC1CB4BFF7008088FD /* forward_valid.json */, DA58D8A01DB2ADDD00530CBB /* forward_valid_zh.json */, DA210BAE1CB4C5A7008088FD /* forward_invalid.json */, @@ -726,12 +786,23 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 07CF85B020F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json in Resources */, + 07CF85A820F6DF0F007B26B6 /* permanent_invalid.json in Resources */, + 07CF85C020F6DF86007B26B6 /* permanent_reverse_single_no_results.json in Resources */, DA5170B81CF1B1F900CD6DCF /* forward_valid.json in Resources */, + 07CF85B420F6DF3C007B26B6 /* permanent_forward_multiple_valid.json in Resources */, + 07CF85AC20F6DF1E007B26B6 /* permanent_forward_single_no_results.json in Resources */, 357B4359202CC90A00735521 /* reverse_address.json in Resources */, + 07CF85C820F6DFEB007B26B6 /* permanent_reverse_single_valid.json in Resources */, + 07CF85A020F6DE61007B26B6 /* permanent_invalid_token.json in Resources */, DA5170B91CF1B1F900CD6DCF /* forward_invalid.json in Resources */, DA5170BB1CF1B1F900CD6DCF /* reverse_invalid.json in Resources */, DA5170BA1CF1B1F900CD6DCF /* reverse_valid.json in Resources */, + 07CF85BC20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json in Resources */, + 07CF85A420F6DED8007B26B6 /* permanent_invalid_token_scope.json in Resources */, + 07CF85B820F6DF55007B26B6 /* permanent_forward_single_valid.json in Resources */, DA58D8A21DB2ADDD00530CBB /* forward_valid_zh.json in Resources */, + 07CF85C420F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -746,12 +817,23 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 07CF85B120F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json in Resources */, + 07CF85A920F6DF0F007B26B6 /* permanent_invalid.json in Resources */, + 07CF85C120F6DF86007B26B6 /* permanent_reverse_single_no_results.json in Resources */, DA5170E21CF2542B00CD6DCF /* forward_valid.json in Resources */, + 07CF85B520F6DF3C007B26B6 /* permanent_forward_multiple_valid.json in Resources */, + 07CF85AD20F6DF1E007B26B6 /* permanent_forward_single_no_results.json in Resources */, 357B435A202CC90A00735521 /* reverse_address.json in Resources */, + 07CF85C920F6DFEB007B26B6 /* permanent_reverse_single_valid.json in Resources */, + 07CF85A120F6DE61007B26B6 /* permanent_invalid_token.json in Resources */, DA5170E31CF2542B00CD6DCF /* forward_invalid.json in Resources */, DA5170E51CF2542B00CD6DCF /* reverse_invalid.json in Resources */, DA5170E41CF2542B00CD6DCF /* reverse_valid.json in Resources */, + 07CF85BD20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json in Resources */, + 07CF85A520F6DED8007B26B6 /* permanent_invalid_token_scope.json in Resources */, + 07CF85B920F6DF55007B26B6 /* permanent_forward_single_valid.json in Resources */, DA58D8A31DB2ADDD00530CBB /* forward_valid_zh.json in Resources */, + 07CF85C520F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -789,12 +871,23 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 07CF85AF20F6DF2F007B26B6 /* permanent_forward_multiple_no_results.json in Resources */, + 07CF85A720F6DF0F007B26B6 /* permanent_invalid.json in Resources */, + 07CF85BF20F6DF86007B26B6 /* permanent_reverse_single_no_results.json in Resources */, DA210BAD1CB4BFF7008088FD /* forward_valid.json in Resources */, + 07CF85B320F6DF3C007B26B6 /* permanent_forward_multiple_valid.json in Resources */, + 07CF85AB20F6DF1E007B26B6 /* permanent_forward_single_no_results.json in Resources */, 357B4358202CC90A00735521 /* reverse_address.json in Resources */, + 07CF85C720F6DFEB007B26B6 /* permanent_reverse_single_valid.json in Resources */, + 07CF859F20F6DE61007B26B6 /* permanent_invalid_token.json in Resources */, DDF1E85C1BD70E4C00C40C78 /* reverse_invalid.json in Resources */, DDF1E85D1BD70E4C00C40C78 /* reverse_valid.json in Resources */, DA210BAF1CB4C5A7008088FD /* forward_invalid.json in Resources */, + 07CF85BB20F6DF76007B26B6 /* permanent_reverse_multiple_valid.json in Resources */, + 07CF85A320F6DED8007B26B6 /* permanent_invalid_token_scope.json in Resources */, + 07CF85B720F6DF55007B26B6 /* permanent_forward_single_valid.json in Resources */, DA58D8A11DB2ADDD00530CBB /* forward_valid_zh.json in Resources */, + 07CF85C320F6DF93007B26B6 /* permanent_reverse_multiple_no_results.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -885,6 +978,7 @@ DA5170B61CF1B1EF00CD6DCF /* ReverseGeocodingTests.swift in Sources */, DA4D90081DD63AEC006EC71A /* PlacemarkScopeTests.swift in Sources */, DA5170B41CF1B1EF00CD6DCF /* GeocoderTests.swift in Sources */, + 079F41E920E42EEF007EEB5E /* BatchGeocodingTests.swift in Sources */, DA5170B51CF1B1EF00CD6DCF /* ForwardGeocodingTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -909,6 +1003,7 @@ DA5170E11CF2542800CD6DCF /* ReverseGeocodingTests.swift in Sources */, DA4D90091DD63AEC006EC71A /* PlacemarkScopeTests.swift in Sources */, DA5170DF1CF2542800CD6DCF /* GeocoderTests.swift in Sources */, + 079F41EA20E42EEF007EEB5E /* BatchGeocodingTests.swift in Sources */, DA5170E01CF2542800CD6DCF /* ForwardGeocodingTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -964,6 +1059,7 @@ DDF1E84D1BD6F7BA00C40C78 /* ReverseGeocodingTests.swift in Sources */, DA4D90071DD63AEC006EC71A /* PlacemarkScopeTests.swift in Sources */, DA210BAB1CB4BE73008088FD /* ForwardGeocodingTests.swift in Sources */, + 079F41E820E42EEF007EEB5E /* BatchGeocodingTests.swift in Sources */, DA701C011CB1292C00B0E520 /* GeocoderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/MapboxGeocoder/MBGeocodeOptions.swift b/MapboxGeocoder/MBGeocodeOptions.swift index 4281f7d..0652ad9 100644 --- a/MapboxGeocoder/MBGeocodeOptions.swift +++ b/MapboxGeocoder/MBGeocodeOptions.swift @@ -80,6 +80,11 @@ open class GeocodeOptions: NSObject { */ internal var queries: [String] = [] + /** + The query mode of the forward or reverse geocoding request. + */ + internal var mode = "mapbox.places" + /** An array of URL parameters to include in the request URL. */ @@ -221,6 +226,7 @@ open class ForwardBatchGeocodeOptions: ForwardGeocodeOptions, BatchGeocodeOption */ @objc public override init(queries: [String]) { super.init(queries: queries) + mode = "mapbox.places-permanent" } } @@ -236,6 +242,7 @@ open class ReverseBatchGeocodeOptions: ReverseGeocodeOptions, BatchGeocodeOption */ @objc public override init(coordinates: [CLLocationCoordinate2D]) { super.init(coordinates: coordinates) + mode = "mapbox.places-permanent" } /** @@ -245,5 +252,6 @@ open class ReverseBatchGeocodeOptions: ReverseGeocodeOptions, BatchGeocodeOption */ @objc public convenience init(locations: [CLLocation]) { self.init(coordinates: locations.map { $0.coordinate }) + mode = "mapbox.places-permanent" } } diff --git a/MapboxGeocoder/MBGeocoder.swift b/MapboxGeocoder/MBGeocoder.swift index 4dd9b65..a08f311 100644 --- a/MapboxGeocoder/MBGeocoder.swift +++ b/MapboxGeocoder/MBGeocoder.swift @@ -223,7 +223,17 @@ open class Geocoder: NSObject { let decoder = JSONDecoder() do { - let result = try decoder.decode([GeocodeResult].self, from: data) + + let result: [GeocodeResult] + + do { + // Decode multiple batch geocoding queries + result = try decoder.decode([GeocodeResult].self, from: data) + } catch { + // Decode single batch geocding queries + result = [try decoder.decode(GeocodeResult.self, from: data)] + } + let placemarks = result.map { $0.placemarks } let attributionsByQuery = result.map { $0.attribution } completionHandler(placemarks, attributionsByQuery, nil) @@ -250,6 +260,7 @@ open class Geocoder: NSObject { */ fileprivate func dataTaskWithURL(_ url: URL, completionHandler: @escaping (_ data: Data?) -> Void, errorHandler: @escaping (_ error: NSError) -> Void) -> URLSessionDataTask { var request = URLRequest(url: url) + request.setValue(userAgent, forHTTPHeaderField: "User-Agent") return URLSession.shared.dataTask(with: request) { (data, response, error) in @@ -257,9 +268,12 @@ open class Geocoder: NSObject { let decoder = JSONDecoder() do { - let result = try decoder.decode(GeocodeAPIResult.self, from: data) - guard result.message == nil else { - let apiError = Geocoder.descriptiveError(["message": result.message!], response: response, underlyingError: error as NSError?) + // Handle multiple batch geocoding queries + let result = try decoder.decode([GeocodeAPIResult].self, from: data) + + // Check if any of the batch geocoding queries failed + if let failedResult = result.first(where: { $0.message != nil }) { + let apiError = Geocoder.descriptiveError(["message": failedResult.message!], response: response, underlyingError: error as NSError?) DispatchQueue.main.async { errorHandler(apiError) } @@ -269,8 +283,26 @@ open class Geocoder: NSObject { completionHandler(data) } } catch { - DispatchQueue.main.async { - errorHandler(error as NSError) + // Handle single & single batch geocoding queries + do { + let result = try decoder.decode(GeocodeAPIResult.self, from: data) + // Check if geocoding query failed + if let message = result.message { + let apiError = Geocoder.descriptiveError(["message": message], response: response, underlyingError: error as NSError?) + DispatchQueue.main.async { + errorHandler(apiError) + } + return + + } + DispatchQueue.main.async { + completionHandler(data) + } + } catch { + // Handle errors that don't return a message (such as a server/network error) + DispatchQueue.main.async { + errorHandler(error as NSError) + } } } } @@ -290,13 +322,7 @@ open class Geocoder: NSObject { assert(!options.queries.isEmpty, "No query") - let mode: String - if options.queries.count > 1 { - mode = "mapbox.places-permanent" - assert(options.queries.count <= 50, "Too many queries in a single request.") - } else { - mode = "mapbox.places" - } + let mode = options.mode let queryComponent = options.queries.map { $0.replacingOccurrences(of: " ", with: "+") diff --git a/MapboxGeocoderTests/BatchGeocodingTests.swift b/MapboxGeocoderTests/BatchGeocodingTests.swift new file mode 100644 index 0000000..9f39323 --- /dev/null +++ b/MapboxGeocoderTests/BatchGeocodingTests.swift @@ -0,0 +1,384 @@ +import XCTest +import OHHTTPStubs +import CoreLocation +@testable import MapboxGeocoder + +class BatchGeocodingTests: XCTestCase { + override func tearDown() { + OHHTTPStubs.removeAllStubs() + super.tearDown() + } + + /** + Forward batch geocoding tests + */ + + func testValidForwardSingleBatchGeocode() { + let expectation = self.expectation(description: "forward batch geocode with single query should return results") + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/85+2nd+st+san+francisco.json") + && containsQueryParams(["country": "ca", "access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_forward_single_valid", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let geocoder = Geocoder(accessToken: BogusToken) + + let options = ForwardBatchGeocodeOptions(query: "85 2nd st san francisco") + options.allowedISOCountryCodes = ["CA"] + + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + let results = placemarks![0] + let attribution = attribution![0] + + XCTAssertEqual(results.count, 5, "single forward batch geocode should have 5 results") + + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testValidForwardMultipleBatchGeocode() { + let expectation = self.expectation(description: "forward batch geocode with multiple queries should return results") + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/20001;20001;20001.json") + && containsQueryParams(["country": "us", "access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_forward_multiple_valid", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let geocoder = Geocoder(accessToken: BogusToken) + + let options = ForwardBatchGeocodeOptions(queries: ["20001", "20001", "20001"]) + options.allowedISOCountryCodes = ["US"] + + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + let queries = placemarks! + let attribution = attribution![0] + + XCTAssertEqual(queries.count, 3, "forward batch geocode should have 3 queries") + + for result in queries { + XCTAssertEqual(result.count, 5, "each forward batch geocode query should have 5 found results") + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + } + + let sampleResult = queries[0][0] + + XCTAssertEqual(sampleResult.qualifiedName, "Washington, District of Columbia 20001, United States") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testNoResultsForwardSingleBatchGeocode() { + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/#M@Pb0X.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_forward_single_no_results", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let expectation = self.expectation(description: "single forward batch geocode should not return results for an invalid location") + let geocoder = Geocoder(accessToken: BogusToken) + let options = ForwardBatchGeocodeOptions(query: "#M@Pb0X") + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + let results = placemarks![0] + let attribution = attribution![0] + + XCTAssertEqual(results.count, 0, "single forward batch geocode should not return results for an invalid location") + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testNoResultsForwardMultipleBatchGeocode() { + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/#M@Pb0X;$C00L!.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_forward_multiple_no_results", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let expectation = self.expectation(description: "multiple forward batch geocode should not return results for an invalid locations") + let geocoder = Geocoder(accessToken: BogusToken) + let options = ForwardBatchGeocodeOptions(queries: ["#M@Pb0X", "$C00L!"]) + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + for result in placemarks! { + XCTAssertTrue(result.isEmpty, "each individual geocode request should not return results") + } + + XCTAssertEqual(attribution![0], "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + /** + Reverse batch geocoding tests + */ + + func testValidReverseSingleBatchGeocode() { + let expectation = self.expectation(description: "reverse batch geocode with single query should return results") + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/-77.01073,38.88887.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_reverse_single_valid", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let geocoder = Geocoder(accessToken: BogusToken) + + let options = ReverseBatchGeocodeOptions(coordinate: CLLocationCoordinate2DMake(38.88887, -77.01073)) + + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + let results = placemarks![0] + let attribution = attribution![0] + + XCTAssertEqual(results.count, 6, "single forward batch geocode should have 6 results") + + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testValidReverseMultipleBatchGeocode() { + let expectation = self.expectation(description: "forward batch geocode with multiple queries should return results") + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/-77.01073,38.88887;-77.01073,38.88887;-77.01073,38.88887.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_reverse_multiple_valid", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let geocoder = Geocoder(accessToken: BogusToken) + + let queries = [ + CLLocationCoordinate2DMake(38.88887, -77.01073), + CLLocationCoordinate2DMake(38.88887, -77.01073), + CLLocationCoordinate2DMake(38.88887, -77.01073) + ] + + let options = ReverseBatchGeocodeOptions(coordinates: queries) + + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + let queries = placemarks! + let attribution = attribution![0] + + XCTAssertEqual(queries.count, 3, "forward batch geocode should have 3 queries") + + for result in queries { + XCTAssertEqual(result.count, 6, "each forward batch geocode query should have 6 found results") + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + } + + let sampleResult = queries[0][0] + + XCTAssertEqual(sampleResult.qualifiedName, "South Capitol Circle Southwest, Washington, District of Columbia 20002, United States") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testNoResultsReverseSingleBatchGeocode() { + _ = stub(condition: isHost("api.mapbox.com") + + && isPath("/geocoding/v5/mapbox.places-permanent/100.00000,100.00000.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_reverse_single_no_results", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let expectation = self.expectation(description: "single reverse batch geocode should not return results for an invalid location") + let geocoder = Geocoder(accessToken: BogusToken) + let options = ReverseBatchGeocodeOptions(coordinate: CLLocationCoordinate2DMake(100, 100)) + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + let results = placemarks![0] + let attribution = attribution![0] + + XCTAssertEqual(results.count, 0, "single reverse batch geocode should not return results for an invalid location") + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testNoResultsReverseMultipleBatchGeocode() { + let expectation = self.expectation(description: "multiple reverse batch geocodes should not return results for invalid locations") + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/100.00000,100.00000;100.00000,100.00000;100.00000,100.00000.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_reverse_multiple_no_results", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let geocoder = Geocoder(accessToken: BogusToken) + + let queries = [ + CLLocationCoordinate2DMake(100, 100), + CLLocationCoordinate2DMake(100, 100), + CLLocationCoordinate2DMake(100, 100) + ] + + let options = ReverseBatchGeocodeOptions(coordinates: queries) + + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + let queries = placemarks! + let attribution = attribution![0] + + XCTAssertEqual(queries.count, 3, "reverse batch geocode should have 3 queries") + + for result in queries { + XCTAssertEqual(result.count, 0, "each reverse batch geocode query should have 0 found results") + XCTAssertEqual(attribution, "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)") + } + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + /** + General batch geocoding tests - invalid queries, invalid tokens, token scope checking, etc. + */ + + func testInvalidBatchGeocode() { + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent////.json") + && containsQueryParams(["access_token": BogusToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_invalid", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let expectation = self.expectation(description: "invalid batch geocoding query should not return results") + let geocoder = Geocoder(accessToken: BogusToken) + let options = ForwardBatchGeocodeOptions(query: "///") + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + XCTAssertEqual(error!.localizedFailureReason, "Not Found") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testInvalidTokenForBatchGeocode() { + let invalidToken = "xyz" + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/85+2nd+st+san+francisco.json") + && containsQueryParams(["access_token": invalidToken])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_invalid_token", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let expectation = self.expectation(description: "invalid token use in batch geocoding query should return an error") + let geocoder = Geocoder(accessToken: invalidToken) + let options = ForwardBatchGeocodeOptions(query: "85 2nd st san francisco") + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + XCTAssertEqual(error!.localizedFailureReason, "Not Authorized - Invalid Token") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } + + func testInvalidTokenScopeForBatchGeocoding() { + let incorrectTokenScope = "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4M29iazA2Z2gycXA4N2pmbDZmangifQ.-g_vE53SD2WrJ6tFX7QHmA" + + _ = stub(condition: isHost("api.mapbox.com") + && isPath("/geocoding/v5/mapbox.places-permanent/85+2nd+st+san+francisco.json") + && containsQueryParams(["access_token": incorrectTokenScope])) { _ in + let path = Bundle(for: type(of: self)).path(forResource: "permanent_invalid_token_scope", ofType: "json") + return OHHTTPStubsResponse(fileAtPath: path!, statusCode: 200, headers: ["Content-Type": "application/vnd.geo+json"]) + } + + let expectation = self.expectation(description: "invalid token use in batch geocoding query should return an error") + let geocoder = Geocoder(accessToken: incorrectTokenScope) + let options = ForwardBatchGeocodeOptions(query: "85 2nd st san francisco") + let task = geocoder.batchGeocode(options) { (placemarks, attribution, error) in + + XCTAssertEqual(error!.localizedFailureReason, "Permanent geocodes are not enabled for this account. Contact support@mapbox.com to enable this feature.") + + expectation.fulfill() + } + XCTAssertNotNil(task) + + waitForExpectations(timeout: 1) { (error) in + XCTAssertNil(error, "Error: \(error!)") + XCTAssertEqual(task.state, URLSessionTask.State.completed) + } + } +} diff --git a/MapboxGeocoderTests/fixtures/permanent_forward_multiple_no_results.json b/MapboxGeocoderTests/fixtures/permanent_forward_multiple_no_results.json new file mode 100644 index 0000000..78bdf2a --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_forward_multiple_no_results.json @@ -0,0 +1,23 @@ +[ + { + "type": "FeatureCollection", + "query": [ + "m", + "pb0x" + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + "c00l" + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + } +] \ No newline at end of file diff --git a/MapboxGeocoderTests/fixtures/permanent_forward_multiple_valid.json b/MapboxGeocoderTests/fixtures/permanent_forward_multiple_valid.json new file mode 100644 index 0000000..d0f764c --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_forward_multiple_valid.json @@ -0,0 +1,716 @@ +[ + { + "type": "FeatureCollection", + "query": [ + "20001" + ], + "features": [ + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "Washington, District of Columbia 20001, United States", + "bbox": [ + -77, + 38, + -77, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "20001, Donostia, Gipuzkoa, Spain", + "bbox": [ + -1, + 43, + -1, + 43 + ], + "center": [ + -1, + 43 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -1, + 43 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q10313", + "text": "Donostia" + }, + { + "id": "region.123", + "short_code": "ES-SS", + "wikidata": "Q95010", + "text": "Gipuzkoa" + }, + { + "id": "country.123", + "short_code": "es", + "wikidata": "Q29", + "text": "Spain" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001 Westside Dr", + "place_name": "20001 Westside Dr, Frankford, Missouri 63441, United States", + "center": [ + -91, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -91, + 39 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "63441" + }, + { + "id": "place.123", + "wikidata": "Q960791", + "text": "Frankford" + }, + { + "id": "region.123", + "short_code": "US-MO", + "wikidata": "Q1581", + "text": "Missouri" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001 Painted Cup Dr", + "place_name": "20001 Painted Cup Dr, Unionville, Missouri 63565, United States", + "center": [ + -93, + 40 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -93, + 40 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "63565" + }, + { + "id": "place.123", + "wikidata": "Q598853", + "text": "Unionville" + }, + { + "id": "region.123", + "short_code": "US-MO", + "wikidata": "Q1581", + "text": "Missouri" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.1", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "20001, Mc Alpin, Florida 32062, United States", + "center": [ + -82, + 30 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -82, + 30 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "32062" + }, + { + "id": "place.123", + "wikidata": null, + "text": "Mc Alpin" + }, + { + "id": "region.123", + "short_code": "US-FL", + "wikidata": "Q812", + "text": "Florida" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + "20001" + ], + "features": [ + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "Washington, District of Columbia 20001, United States", + "bbox": [ + -77, + 38, + -77, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "20001, Donostia, Gipuzkoa, Spain", + "bbox": [ + -1, + 43, + -1, + 43 + ], + "center": [ + -1.972363, + 43.323461 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -1, + 43 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q10313", + "text": "Donostia" + }, + { + "id": "region.123", + "short_code": "ES-SS", + "wikidata": "Q95010", + "text": "Gipuzkoa" + }, + { + "id": "country.123", + "short_code": "es", + "wikidata": "Q29", + "text": "Spain" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001 Westside Dr", + "place_name": "20001 Westside Dr, Frankford, Missouri 63441, United States", + "center": [ + -91, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -91, + 39 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "63441" + }, + { + "id": "place.123", + "wikidata": "Q960791", + "text": "Frankford" + }, + { + "id": "region.123", + "short_code": "US-MO", + "wikidata": "Q1581", + "text": "Missouri" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001 Painted Cup Dr", + "place_name": "20001 Painted Cup Dr, Unionville, Missouri 63565, United States", + "center": [ + -93, + 40 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -93, + 40 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "63565" + }, + { + "id": "place.123", + "wikidata": "Q598853", + "text": "Unionville" + }, + { + "id": "region.123", + "short_code": "US-MO", + "wikidata": "Q1581", + "text": "Missouri" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "20001, Mc Alpin, Florida 32062, United States", + "center": [ + -82, + 30 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -82, + 30 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "32062" + }, + { + "id": "place.123", + "wikidata": null, + "text": "Mc Alpin" + }, + { + "id": "region.123", + "short_code": "US-FL", + "wikidata": "Q812", + "text": "Florida" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + "20001" + ], + "features": [ + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "Washington, District of Columbia 20001, United States", + "bbox": [ + -77, + 38, + -77, + 38 + ], + "center": [ + -77, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "20001, Donostia, Gipuzkoa, Spain", + "bbox": [ + -1, + 43, + -1, + 43 + ], + "center": [ + -1, + 43 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -1, + 43 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q10313", + "text": "Donostia" + }, + { + "id": "region.123", + "short_code": "ES-SS", + "wikidata": "Q95010", + "text": "Gipuzkoa" + }, + { + "id": "country.123", + "short_code": "es", + "wikidata": "Q29", + "text": "Spain" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001 Westside Dr", + "place_name": "20001 Westside Dr, Frankford, Missouri 63441, United States", + "center": [ + -91, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -91, + 39 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "63441" + }, + { + "id": "place.123", + "wikidata": "Q960791", + "text": "Frankford" + }, + { + "id": "region.123", + "short_code": "US-MO", + "wikidata": "Q1581", + "text": "Missouri" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001 Painted Cup Dr", + "place_name": "20001 Painted Cup Dr, Unionville, Missouri 63565, United States", + "center": [ + -93, + 40 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -93, + 40 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "63565" + }, + { + "id": "place.123", + "wikidata": "Q598853", + "text": "Unionville" + }, + { + "id": "region.123", + "short_code": "US-MO", + "wikidata": "Q1581", + "text": "Missouri" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.1", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": {}, + "text": "20001", + "place_name": "20001, Mc Alpin, Florida 32062, United States", + "center": [ + -82, + 30 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -82, + 30 + ] + }, + "context": [ + { + "id": "postcode.6857120106983010", + "text": "32062" + }, + { + "id": "place.4536624049214180", + "wikidata": null, + "text": "Mc Alpin" + }, + { + "id": "region.3865", + "short_code": "US-FL", + "wikidata": "Q812", + "text": "Florida" + }, + { + "id": "country.3145", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + } +] \ No newline at end of file diff --git a/MapboxGeocoderTests/fixtures/permanent_forward_single_no_results.json b/MapboxGeocoderTests/fixtures/permanent_forward_single_no_results.json new file mode 100644 index 0000000..8d12884 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_forward_single_no_results.json @@ -0,0 +1,11 @@ +{ + "type": "FeatureCollection", + "query": [ + "m", + "pb0x" + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" +} diff --git a/MapboxGeocoderTests/fixtures/permanent_forward_single_valid.json b/MapboxGeocoderTests/fixtures/permanent_forward_single_valid.json new file mode 100644 index 0000000..534e280 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_forward_single_valid.json @@ -0,0 +1,265 @@ +{ + "type": "FeatureCollection", + "query": [ + "85", + "2nd", + "st", + "san", + "francisco" + ], + "features": [ + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + + }, + "text": "2nd Street", + "place_name": "85 2nd Street, San Francisco, California 94105, United States", + "center": [ + -122, + 37 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -122123, + 37 + ] + }, + "address": "85", + "context": [ + { + "id": "neighborhood.123", + "text": "South Beach" + }, + { + "id": "postcode.123", + "text": "94105" + }, + { + "id": "place.123", + "wikidata": "Q62", + "text": "San Francisco" + }, + { + "id": "region.123", + "short_code": "US-CA", + "wikidata": "Q99", + "text": "California" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + + }, + "text": "2nd Street", + "place_name": "85 2nd Street, San Francisco Plaza, New Mexico 87830, United States", + "center": [ + -108, + 33 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -108, + 33 + ], + "interpolated": true, + "omitted": true + }, + "address": "85", + "context": [ + { + "id": "postcode.123", + "text": "87830" + }, + { + "id": "place.123", + "wikidata": null, + "text": "San Francisco Plaza" + }, + { + "id": "region.123", + "short_code": "US-NM", + "wikidata": "Q1522", + "text": "New Mexico" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 0.9, + "properties": { + + }, + "text": "2nd Street", + "place_name": "85 2nd Street, South San Francisco, California 94080, United States", + "center": [ + -122, + 37 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -122, + 37 + ], + "interpolated": true + }, + "address": "85", + "context": [ + { + "id": "neighborhood.123", + "text": "El Camino" + }, + { + "id": "postcode.123", + "text": "94080" + }, + { + "id": "place.123", + "wikidata": "Q927122", + "text": "South San Francisco" + }, + { + "id": "region.123", + "short_code": "US-CA", + "wikidata": "Q99", + "text": "California" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "place.123", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 0.5, + "properties": { + "wikidata": "Q62" + }, + "text": "San Francisco", + "place_name": "San Francisco, California, United States", + "bbox": [ + -122, + 37, + -122, + 37 + ], + "center": [ + -122, + 37 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -122, + 37 + ] + }, + "context": [ + { + "id": "region.123", + "short_code": "US-CA", + "wikidata": "Q99", + "text": "California" + }, + { + "id": "country.123", + "short_code": "us", + "wikidata": "Q30", + "text": "United States" + } + ] + }, + { + "id": "locality.123", + "type": "Feature", + "place_type": [ + "locality" + ], + "relevance": 0.5, + "properties": { + + }, + "text": "San Francisco", + "place_name": "San Francisco, 4024, Biñan, Laguna, Philippines", + "bbox": [ + 121, + 14, + 121, + 14 + ], + "center": [ + 121, + 14 + ], + "geometry": { + "type": "Point", + "coordinates": [ + 121, + 14 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "4024" + }, + { + "id": "place.123", + "wikidata": "Q75961", + "text": "Biñan" + }, + { + "id": "region.123", + "short_code": "PH-LAG", + "wikidata": "Q13840", + "text": "Laguna" + }, + { + "id": "country.123", + "short_code": "ph", + "wikidata": "Q928", + "text": "Philippines" + } + ] + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" +} diff --git a/MapboxGeocoderTests/fixtures/permanent_invalid.json b/MapboxGeocoderTests/fixtures/permanent_invalid.json new file mode 100644 index 0000000..8ac1825 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_invalid.json @@ -0,0 +1,3 @@ +{ + "message": "Not Found" +} \ No newline at end of file diff --git a/MapboxGeocoderTests/fixtures/permanent_invalid_token.json b/MapboxGeocoderTests/fixtures/permanent_invalid_token.json new file mode 100644 index 0000000..2aaeb43 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_invalid_token.json @@ -0,0 +1,3 @@ +{ + "message": "Not Authorized - Invalid Token" +} \ No newline at end of file diff --git a/MapboxGeocoderTests/fixtures/permanent_invalid_token_scope.json b/MapboxGeocoderTests/fixtures/permanent_invalid_token_scope.json new file mode 100644 index 0000000..e258013 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_invalid_token_scope.json @@ -0,0 +1,3 @@ +{ + "message": "Permanent geocodes are not enabled for this account. Contact support@mapbox.com to enable this feature." +} \ No newline at end of file diff --git a/MapboxGeocoderTests/fixtures/permanent_reverse_multiple_no_results.json b/MapboxGeocoderTests/fixtures/permanent_reverse_multiple_no_results.json new file mode 100644 index 0000000..c07c246 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_reverse_multiple_no_results.json @@ -0,0 +1,35 @@ +[ + { + "type": "FeatureCollection", + "query": [ + 100, + 100 + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + 100, + 100 + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + 100, + 100 + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + } + ] diff --git a/MapboxGeocoderTests/fixtures/permanent_reverse_multiple_valid.json b/MapboxGeocoderTests/fixtures/permanent_reverse_multiple_valid.json new file mode 100644 index 0000000..9276ce6 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_reverse_multiple_valid.json @@ -0,0 +1,833 @@ +[ + { + "type": "FeatureCollection", + "query": [ + -77, + 38 + ], + "features": [ + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + + }, + "text": "South Capitol Circle Southwest", + "place_name": "South Capitol Circle Southwest, Washington, District of Columbia 20002, United States", + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "neighborhood.123", + "text": "Capitol Hill" + }, + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "neighborhood.123", + "type": "Feature", + "place_type": [ + "neighborhood" + ], + "relevance": 1, + "properties": { + + }, + "text": "Capitol Hill", + "place_name": "Capitol Hill, Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": { + + }, + "text": "20002", + "place_name": "Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "place.123", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 1, + "properties": { + "wikidata": "Q61" + }, + "text": "Washington", + "place_name": "Washington, District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "region.123", + "type": "Feature", + "place_type": [ + "region" + ], + "relevance": 1, + "properties": { + "short_code": "US-DC", + "wikidata": "Q61" + }, + "text": "District of Columbia", + "place_name": "District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -76, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -76, + 38 + ] + }, + "context": [ + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "country.123", + "type": "Feature", + "place_type": [ + "country" + ], + "relevance": 1, + "properties": { + "wikidata": "Q30", + "short_code": "us" + }, + "text": "United States", + "place_name": "United States", + "bbox": [ + -179, + -14, + -64, + 71 + ], + "center": [ + -97, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -97, + 39 + ] + } + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + -77, + 38 + ], + "features": [ + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + + }, + "text": "South Capitol Circle Southwest", + "place_name": "South Capitol Circle Southwest, Washington, District of Columbia 20002, United States", + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "neighborhood.123", + "text": "Capitol Hill" + }, + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "neighborhood.123", + "type": "Feature", + "place_type": [ + "neighborhood" + ], + "relevance": 1, + "properties": { + + }, + "text": "Capitol Hill", + "place_name": "Capitol Hill, Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": { + + }, + "text": "20002", + "place_name": "Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "place.123", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 1, + "properties": { + "wikidata": "Q61" + }, + "text": "Washington", + "place_name": "Washington, District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "region.123", + "type": "Feature", + "place_type": [ + "region" + ], + "relevance": 1, + "properties": { + "short_code": "US-DC", + "wikidata": "Q61" + }, + "text": "District of Columbia", + "place_name": "District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -76, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -76, + 38 + ] + }, + "context": [ + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "country.123", + "type": "Feature", + "place_type": [ + "country" + ], + "relevance": 1, + "properties": { + "wikidata": "Q30", + "short_code": "us" + }, + "text": "United States", + "place_name": "United States", + "bbox": [ + -179, + -14, + -64, + 71 + ], + "center": [ + -97, + 39.381266 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -97, + 39.381266 + ] + } + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + }, + { + "type": "FeatureCollection", + "query": [ + -77, + 38 + ], + "features": [ + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + + }, + "text": "South Capitol Circle Southwest", + "place_name": "South Capitol Circle Southwest, Washington, District of Columbia 20002, United States", + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "neighborhood.123", + "text": "Capitol Hill" + }, + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "neighborhood.123", + "type": "Feature", + "place_type": [ + "neighborhood" + ], + "relevance": 1, + "properties": { + + }, + "text": "Capitol Hill", + "place_name": "Capitol Hill, Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": { + + }, + "text": "20002", + "place_name": "Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "place.123", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 1, + "properties": { + "wikidata": "Q61" + }, + "text": "Washington", + "place_name": "Washington, District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "region.123", + "type": "Feature", + "place_type": [ + "region" + ], + "relevance": 1, + "properties": { + "short_code": "US-DC", + "wikidata": "Q61" + }, + "text": "District of Columbia", + "place_name": "District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -76, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -76, + 38 + ] + }, + "context": [ + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "country.123", + "type": "Feature", + "place_type": [ + "country" + ], + "relevance": 1, + "properties": { + "wikidata": "Q30", + "short_code": "us" + }, + "text": "United States", + "place_name": "United States", + "bbox": [ + -179, + -14, + -64, + 71 + ], + "center": [ + -97, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -97, + 39 + ] + } + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" + } +] \ No newline at end of file diff --git a/MapboxGeocoderTests/fixtures/permanent_reverse_single_no_results.json b/MapboxGeocoderTests/fixtures/permanent_reverse_single_no_results.json new file mode 100644 index 0000000..14c5d5b --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_reverse_single_no_results.json @@ -0,0 +1,11 @@ +{ + "type": "FeatureCollection", + "query": [ + 100, + 100 + ], + "features": [ + + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" +} diff --git a/MapboxGeocoderTests/fixtures/permanent_reverse_single_valid.json b/MapboxGeocoderTests/fixtures/permanent_reverse_single_valid.json new file mode 100644 index 0000000..cdd4c87 --- /dev/null +++ b/MapboxGeocoderTests/fixtures/permanent_reverse_single_valid.json @@ -0,0 +1,277 @@ +{ + "type": "FeatureCollection", + "query": [ + -77, + 38 + ], + "features": [ + { + "id": "address.123", + "type": "Feature", + "place_type": [ + "address" + ], + "relevance": 1, + "properties": { + + }, + "text": "South Capitol Circle Southwest", + "place_name": "South Capitol Circle Southwest, Washington, District of Columbia 20002, United States", + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "neighborhood.123", + "text": "Capitol Hill" + }, + { + "id": "postcode.123", + "text": "20002" + }, + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "neighborhood.123", + "type": "Feature", + "place_type": [ + "neighborhood" + ], + "relevance": 1, + "properties": { + + }, + "text": "Capitol Hill", + "place_name": "Capitol Hill, Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77.0003, + 38.889 + ] + }, + "context": [ + { + "id": "postcode", + "text": "20002" + }, + { + "id": "place", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "postcode.123", + "type": "Feature", + "place_type": [ + "postcode" + ], + "relevance": 1, + "properties": { + + }, + "text": "20002", + "place_name": "Washington, District of Columbia 20002, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "place.123", + "wikidata": "Q61", + "text": "Washington" + }, + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "place.123", + "type": "Feature", + "place_type": [ + "place" + ], + "relevance": 1, + "properties": { + "wikidata": "Q61" + }, + "text": "Washington", + "place_name": "Washington, District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -77, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -77, + 38 + ] + }, + "context": [ + { + "id": "region.123", + "short_code": "US-DC", + "wikidata": "Q61", + "text": "District of Columbia" + }, + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "region.123", + "type": "Feature", + "place_type": [ + "region" + ], + "relevance": 1, + "properties": { + "short_code": "US-DC", + "wikidata": "Q61" + }, + "text": "District of Columbia", + "place_name": "District of Columbia, United States", + "bbox": [ + -77, + 38, + -76, + 38 + ], + "center": [ + -76, + 38 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -76, + 38 + ] + }, + "context": [ + { + "id": "country.123", + "wikidata": "Q30", + "short_code": "us", + "text": "United States" + } + ] + }, + { + "id": "country.123", + "type": "Feature", + "place_type": [ + "country" + ], + "relevance": 1, + "properties": { + "wikidata": "Q30", + "short_code": "us" + }, + "text": "United States", + "place_name": "United States", + "bbox": [ + -179, + -14, + -64, + 71 + ], + "center": [ + -97, + 39 + ], + "geometry": { + "type": "Point", + "coordinates": [ + -97, + 39 + ] + } + } + ], + "attribution": "© 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service. (https://www.mapbox.com/about/maps/)" +} \ No newline at end of file