diff --git a/Sources/SmartyStreets/ClientBuilder.swift b/Sources/SmartyStreets/ClientBuilder.swift index c5310e8..1e5812d 100644 --- a/Sources/SmartyStreets/ClientBuilder.swift +++ b/Sources/SmartyStreets/ClientBuilder.swift @@ -15,7 +15,7 @@ import Foundation var proxy:NSDictionary! var licenses:[String] = [] var internationalStreetApiURL:String = "https://international-street.api.smarty.com/verify" - var internationalAutocompleteApiURL:String = "https://international-autocomplete.api.smarty.com/lookup" + var internationalAutocompleteApiURL:String = "https://international-autocomplete.api.smarty.com/v2/lookup" var usAutocompleteApiURL:String = "https://us-autocomplete.api.smarty.com/suggest" var usAutocompleteProApiURL:String = "https://us-autocomplete-pro.api.smarty.com/lookup" var usExtractApiURL:String = "https://us-extract.api.smarty.com" @@ -133,13 +133,13 @@ import Foundation let serializer = InternationalStreetSerializer() return InternationalStreetClient(sender:buildSender(), serializer: serializer) } - + public func buildInternationalAutocompleteApiClient() -> InternationalAutocompleteClient { ensureURLPrefixNotNil(url: self.internationalAutocompleteApiURL) let serializer = InternationalAutocompleteSerializer() return InternationalAutocompleteClient(sender:buildSender(), serializer:serializer) } - + public func buildUSAutocompleteApiClient() -> USAutocompleteClient { // Deprecated ensureURLPrefixNotNil(url: self.usAutocompleteApiURL) let serializer = USAutocompleteSerializer() diff --git a/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteCandidate.swift b/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteCandidate.swift index 692ad89..80cad65 100644 --- a/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteCandidate.swift +++ b/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteCandidate.swift @@ -8,28 +8,31 @@ import Foundation public var street:String? public var locality:String? public var administrativeArea:String? - public var superAdministrativeArea:String?; - public var subAdministrativeArea:String?; public var postalCode:String? public var countryISO3:String? + public var entries:Int? + public var addressText:String? + public var addressID:String? enum CodingKeys:String, CodingKey { case street = "street" case locality = "locality" case administrativeArea = "administrative_area" - case superAdministrativeArea = "super_administrative_area" - case subAdministrativeArea = "sub_administrative_area" case postalCode = "postal_code" case countryISO3 = "country_iso3" + case entries = "entries" + case addressText = "address_text" + case addressID = "address_id" } init(dictionary:NSDictionary) { self.street = dictionary["street"] as? String self.locality = dictionary["locality"] as? String self.administrativeArea = dictionary["administrative_area"] as? String - self.superAdministrativeArea = dictionary["super_administrative_area"] as? String - self.subAdministrativeArea = dictionary["sub_administrative_area"] as? String self.postalCode = dictionary["postal_code"] as? String self.countryISO3 = dictionary["country_iso3"] as? String + self.entries = dictionary["entries"] as? Int + self.addressText = dictionary["address_text"] as? String + self.addressID = dictionary["address_id"] as? String } } diff --git a/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteClient.swift b/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteClient.swift index 6d2e81c..c9d4e7f 100644 --- a/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteClient.swift +++ b/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteClient.swift @@ -14,50 +14,43 @@ public class InternationalAutocompleteClient: NSObject { @objc public func sendLookup(lookup: UnsafeMutablePointer, error: UnsafeMutablePointer) -> Bool { // Sends a Lookup object to the International Autocomplete API and stores the result in the Lookup's result field. - if let prefix = lookup.pointee.search { - if prefix.count == 0 { - let details = [NSLocalizedDescriptionKey:"sendLookup must be passed a Lookup with the prefix field set."] - error.pointee = NSError(domain: SmartyErrors().SSErrorDomain, code: SmartyErrors.SSErrors.FieldNotSetError.rawValue, userInfo: details) - return false - } - - let request = buildRequest(lookup:lookup.pointee) - let response = self.sender.sendRequest(request: request, error: &error.pointee) - if error.pointee != nil { return false } - - var result:InternationalAutocompleteResult - - if let payload = response?.payload { - result = self.serializer.Deserialize(payload: payload, error: &error.pointee) as? InternationalAutocompleteResult ?? InternationalAutocompleteResult(dictionary: NSDictionary()) - } else { - result = InternationalAutocompleteResult(dictionary: NSDictionary()) - } - - // Naming of parameters to allow JSON deserialization - if error.pointee != nil { return false } - - lookup.pointee.result = result - return true - } else { + if lookup.pointee.country == nil || (lookup.pointee.search == nil && lookup.pointee.addressID == nil) { + let details = [NSLocalizedDescriptionKey:"sendLookup must be passed a Lookup with the country field set, and either search or addressID set."] + error.pointee = NSError(domain: SmartyErrors().SSErrorDomain, code: SmartyErrors.SSErrors.FieldNotSetError.rawValue, userInfo: details) return false } + + let request = buildRequest(lookup:lookup.pointee) + let response = self.sender.sendRequest(request: request, error: &error.pointee) + if error.pointee != nil { return false } + + var result:InternationalAutocompleteResult + + if let payload = response?.payload { + result = self.serializer.Deserialize(payload: payload, error: &error.pointee) as? InternationalAutocompleteResult ?? InternationalAutocompleteResult(dictionary: NSDictionary()) + } else { + result = InternationalAutocompleteResult(dictionary: NSDictionary()) + } + + // Naming of parameters to allow JSON deserialization + if error.pointee != nil { return false } + + lookup.pointee.result = result + return true } func buildRequest(lookup:InternationalAutocompleteLookup) -> SmartyRequest { let request = SmartyRequest() + + if let unwrappedPrefix = lookup.addressID { + request.urlPrefix = "/" + unwrappedPrefix + } request.setValue(value: lookup.search ?? "", HTTPParameterField: "search") request.setValue(value: lookup.country ?? "", HTTPParameterField: "country") request.setValue(value: lookup.maxResults.flatMap { String($0) } ?? "10", HTTPParameterField: "max_results") - request.setValue(value: lookup.distance.flatMap { String($0) } ?? "5", HTTPParameterField: "distance") - if lookup.geolocation != InternationalAutocompleteLookup.InternationalGeolocateType.none { - request.setValue(value: lookup.geolocation?.rawValue ?? "", HTTPParameterField: "geolocation") - } - request.setValue(value: lookup.administrativeArea ?? "", HTTPParameterField: "include_only_administrative_area") request.setValue(value: lookup.locality ?? "", HTTPParameterField: "include_only_locality") request.setValue(value: lookup.postalCode ?? "", HTTPParameterField: "include_only_postal_code") - request.setValue(value: lookup.longitude.flatMap { String($0) } ?? "", HTTPParameterField: "longitude") - request.setValue(value: lookup.latitude.flatMap { String($0) } ?? "", HTTPParameterField: "latitude") return request } diff --git a/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteLookup.swift b/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteLookup.swift index 7866fe0..14d2869 100644 --- a/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteLookup.swift +++ b/Sources/SmartyStreets/InternationalAutocomplete/InternationalAutocompleteLookup.swift @@ -7,44 +7,26 @@ import Foundation // See "https://smartystreets.com/docs/cloud/international-address-autocomplete-api#pro-http-request-input-fields" static let SSMaxResults = 10 - static let SSDistance = 5 public var result:InternationalAutocompleteResult? public var country:String? public var search:String? + public var addressID:String? public var maxResults:Int? - public var distance:Int? - public var geolocation:InternationalGeolocateType? - public var administrativeArea:String? public var locality:String? public var postalCode:String? - public var latitude:Double? - public var longitude:Double? - - public enum InternationalGeolocateType: String, Codable { - case adminarea - case locality - case postalcode - case geocodes - case none - } enum CodingKeys: String, CodingKey { case country = "country" case search = "search" + case addressID = "address_id" case maxResults = "max_results" - case distance = "distance" - case geolocation = "geolocation" - case administrativeArea = "include_only_administrative_area" case locality = "include_only_locality" case postalCode = "include_only_postal_code" - case latitude = "latitude" - case longitude = "longitude" } override public init() { self.maxResults = InternationalAutocompleteLookup.SSMaxResults - self.distance = InternationalAutocompleteLookup.SSDistance } public func withSearch(search:String) -> InternationalAutocompleteLookup { diff --git a/Sources/SmartyStreets/URLPrefixSender.swift b/Sources/SmartyStreets/URLPrefixSender.swift index 396ec47..f91207c 100644 --- a/Sources/SmartyStreets/URLPrefixSender.swift +++ b/Sources/SmartyStreets/URLPrefixSender.swift @@ -11,7 +11,12 @@ public class URLPrefixSender: SmartySender { } override func sendRequest(request: SmartyRequest, error: inout NSError!) -> SmartyResponse! { - request.urlPrefix = self.urlPrefix + if !request.urlPrefix.isEmpty { + request.urlPrefix = self.urlPrefix + request.urlPrefix + } else { + request.urlPrefix = self.urlPrefix + } + return self.inner.sendRequest(request: request, error: &error) } } diff --git a/Tests/SmartyStreetsTests/ClientBuilderTests.swift b/Tests/SmartyStreetsTests/ClientBuilderTests.swift index a0809be..0807ee9 100644 --- a/Tests/SmartyStreetsTests/ClientBuilderTests.swift +++ b/Tests/SmartyStreetsTests/ClientBuilderTests.swift @@ -22,6 +22,7 @@ class ClientBuilderTests: XCTestCase { XCTAssertEqual(client.maxTimeout, 10000) XCTAssertEqual(client.debug, false) XCTAssertEqual(client.internationalStreetApiURL, "https://international-street.api.smarty.com/verify") + XCTAssertEqual(client.internationalAutocompleteApiURL, "https://international-autocomplete.api.smarty.com/v2/lookup") XCTAssertEqual(client.usAutocompleteApiURL, "https://us-autocomplete.api.smarty.com/suggest") XCTAssertEqual(client.usExtractApiURL, "https://us-extract.api.smarty.com") XCTAssertEqual(client.usStreetApiURL, "https://us-street.api.smarty.com/street-address") diff --git a/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift b/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift index 076c85d..ee1d6c1 100644 --- a/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift +++ b/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift @@ -19,36 +19,28 @@ class InternationalAutocompleteClientTests: XCTestCase { } func testSendingSinglePrefixOnlyLookup() { - let sender = URLPrefixSender(urlPrefix: "http://localhost/", inner: self.capturingSender as Any) + let sender = URLPrefixSender(urlPrefix: "http://localhost", inner: self.capturingSender as Any) let serializer = MockSerializer(result: InternationalAutocompleteResult(dictionary: NSDictionary())) let client = InternationalAutocompleteClient(sender:sender, serializer:serializer) var lookup = InternationalAutocompleteLookup() lookup.search = "1" lookup.country = "2" lookup.locality = "3" - lookup.administrativeArea = "4" - lookup.maxResults = 5 - lookup.distance = 7 - lookup.geolocation = InternationalAutocompleteLookup.InternationalGeolocateType.geocodes - lookup.postalCode = "6" - lookup.longitude = 112.1 - lookup.latitude = -23.4 + lookup.maxResults = 4 + lookup.postalCode = "5" + lookup.addressID = "6" _ = client.sendLookup(lookup:&lookup, error:&error) XCTAssertEqual("1", capturingSender.request.parameters["search"]) XCTAssertEqual("2", capturingSender.request.parameters["country"]) XCTAssertEqual("3", capturingSender.request.parameters["include_only_locality"]) - XCTAssertEqual("4", capturingSender.request.parameters["include_only_administrative_area"]) - XCTAssertEqual("5", capturingSender.request.parameters["max_results"]) - XCTAssertEqual("7", capturingSender.request.parameters["distance"]) - XCTAssertEqual("geocodes", capturingSender.request.parameters["geolocation"]) - XCTAssertEqual("6", capturingSender.request.parameters["include_only_postal_code"]) - XCTAssertEqual("112.1", capturingSender.request.parameters["longitude"]) - XCTAssertEqual("-23.4", capturingSender.request.parameters["latitude"]) + XCTAssertEqual("4", capturingSender.request.parameters["max_results"]) + XCTAssertEqual("5", capturingSender.request.parameters["include_only_postal_code"]) + XCTAssertEqual("http://localhost/6", capturingSender.request.urlPrefix) XCTAssertNil(self.error) } - + func testSendingSingleMinimumParams() { let sender = URLPrefixSender(urlPrefix: "http://localhost/", inner: self.capturingSender as Any) let serializer = MockSerializer(result: InternationalAutocompleteResult(dictionary: NSDictionary())) @@ -62,13 +54,8 @@ class InternationalAutocompleteClientTests: XCTestCase { XCTAssertEqual("1", capturingSender.request.parameters["search"]) XCTAssertEqual("2", capturingSender.request.parameters["country"]) XCTAssertEqual(nil, capturingSender.request.parameters["include_only_locality"]) - XCTAssertEqual(nil, capturingSender.request.parameters["include_only_administrative_area"]) XCTAssertEqual("10", capturingSender.request.parameters["max_results"]) - XCTAssertEqual("5", capturingSender.request.parameters["distance"]) - XCTAssertEqual(nil, capturingSender.request.parameters["geolocation"]) XCTAssertEqual(nil, capturingSender.request.parameters["include_only_postal_code"]) - XCTAssertEqual(nil, capturingSender.request.parameters["longitude"]) - XCTAssertEqual(nil, capturingSender.request.parameters["latitude"]) XCTAssertNil(self.error) } } diff --git a/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteResultTests.swift b/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteResultTests.swift index e8185b8..c908184 100644 --- a/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteResultTests.swift +++ b/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteResultTests.swift @@ -13,19 +13,13 @@ class InternationalAutocompleteResultTests: XCTestCase { "street":"0", "locality":"1", "administrative_area":"2", - "super_administrative_area":"3", - "sub_administrative_area":"4", - "postal_code":"5", - "country_iso3":"6" + "postal_code":"3", + "country_iso3":"4" ], [ - "street":"7", - "locality":"8", - "administrative_area":"9", - "super_administrative_area":"super", - "sub_administrative_area":"sub", - "postal_code":"10", - "country_iso3":"11" + "entries": 5, + "address_text": "6", + "address_id": "7" ] ] ] @@ -41,17 +35,11 @@ class InternationalAutocompleteResultTests: XCTestCase { XCTAssertEqual("0", result.getCandidateAtIndex(index: 0).street) XCTAssertEqual("1", result.getCandidateAtIndex(index: 0).locality) XCTAssertEqual("2", result.getCandidateAtIndex(index: 0).administrativeArea) - XCTAssertEqual("3", result.getCandidateAtIndex(index: 0).superAdministrativeArea) - XCTAssertEqual("4", result.getCandidateAtIndex(index: 0).subAdministrativeArea) - XCTAssertEqual("5", result.getCandidateAtIndex(index: 0).postalCode) - XCTAssertEqual("6", result.getCandidateAtIndex(index: 0).countryISO3) + XCTAssertEqual("3", result.getCandidateAtIndex(index: 0).postalCode) + XCTAssertEqual("4", result.getCandidateAtIndex(index: 0).countryISO3) - XCTAssertEqual("7", result.getCandidateAtIndex(index: 1).street) - XCTAssertEqual("8", result.getCandidateAtIndex(index: 1).locality) - XCTAssertEqual("9", result.getCandidateAtIndex(index: 1).administrativeArea) - XCTAssertEqual("super", result.getCandidateAtIndex(index: 1).superAdministrativeArea) - XCTAssertEqual("sub", result.getCandidateAtIndex(index: 1).subAdministrativeArea) - XCTAssertEqual("10", result.getCandidateAtIndex(index: 1).postalCode) - XCTAssertEqual("11", result.getCandidateAtIndex(index: 1).countryISO3) + XCTAssertEqual("5", String(result.getCandidateAtIndex(index: 1).entries ?? 0)) + XCTAssertEqual("6", result.getCandidateAtIndex(index: 1).addressText) + XCTAssertEqual("7", result.getCandidateAtIndex(index: 1).addressID) } } diff --git a/Tests/SmartyStreetsTests/Mocks/RequestCapturingSender.swift b/Tests/SmartyStreetsTests/Mocks/RequestCapturingSender.swift index 1c63cf1..cf98579 100644 --- a/Tests/SmartyStreetsTests/Mocks/RequestCapturingSender.swift +++ b/Tests/SmartyStreetsTests/Mocks/RequestCapturingSender.swift @@ -7,7 +7,6 @@ class RequestCapturingSender:SmartySender { override func sendRequest(request: SmartyRequest, error: inout NSError!) -> SmartyResponse! { self.request = request - self.request.urlPrefix = "http://localhost/?" let emptyString = "[]" let data = emptyString.data(using: String.Encoding.utf8) diff --git a/Tests/SmartyStreetsTests/URLPrefixSenderTests.swift b/Tests/SmartyStreetsTests/URLPrefixSenderTests.swift new file mode 100644 index 0000000..c95bf75 --- /dev/null +++ b/Tests/SmartyStreetsTests/URLPrefixSenderTests.swift @@ -0,0 +1,42 @@ +import XCTest +@testable import SmartyStreets + +class URLPrefixSenderTests: XCTestCase { + + var urlPrefixSender:URLPrefixSender! + var inner:MockSender! + var error:NSError! + + override func setUp() { + super.setUp() + self.inner = MockSender(response: nil) + self.urlPrefixSender = URLPrefixSender(urlPrefix: "http://mysite.com/lookup", inner: self.inner as Any) + } + + override func tearDown() { + super.tearDown() + self.urlPrefixSender = nil + self.error = nil + self.inner = nil + } + + func testRequestURLPresent() { + let request:SmartyRequest = SmartyRequest() + request.urlPrefix = "/jimbo" + + _ = self.urlPrefixSender.sendRequest(request: request, error: &self.error) + + XCTAssertEqual(request.urlPrefix, "http://mysite.com/lookup/jimbo") + + } + + func testRequestURLNotPresent() { + let request:SmartyRequest = SmartyRequest() + + _ = self.urlPrefixSender.sendRequest(request: request, error: &self.error) + + XCTAssertEqual(request.urlPrefix, "http://mysite.com/lookup") + } + + +} \ No newline at end of file diff --git a/Tests/SmartyStreetsTests/USStreetTests/USStreetClientTests.swift b/Tests/SmartyStreetsTests/USStreetTests/USStreetClientTests.swift index c81c180..5e83075 100644 --- a/Tests/SmartyStreetsTests/USStreetTests/USStreetClientTests.swift +++ b/Tests/SmartyStreetsTests/USStreetTests/USStreetClientTests.swift @@ -21,13 +21,14 @@ class USStreetClientTests: XCTestCase { func testSendingSingleFreeformLookup() { let expectedUrl = "http://localhost/?candidates=1" - let sender = RequestCapturingSender() + let capturingSender = RequestCapturingSender() + let sender = URLPrefixSender(urlPrefix: "http://localhost/", inner: capturingSender as Any) let client = USStreetClient(sender: sender, serializer: serializer) var lookup = USStreetLookup() _ = client.sendLookup(lookup: &lookup, error: &self.error) - let actualUrl = sender.request.getUrl() + let actualUrl = capturingSender.request.getUrl() XCTAssertEqual(actualUrl, expectedUrl) } diff --git a/samples/Sources/swiftExamples/InternationalAutocompleteExample.swift b/samples/Sources/swiftExamples/InternationalAutocompleteExample.swift index 9fbe764..b8c44de 100644 --- a/samples/Sources/swiftExamples/InternationalAutocompleteExample.swift +++ b/samples/Sources/swiftExamples/InternationalAutocompleteExample.swift @@ -47,7 +47,11 @@ class InternationalAutocompleteExample { } for candidate in candidates { - output.append("\(candidate.street ?? "") \(candidate.locality ?? "") \(candidate.administrativeArea ?? ""), \(candidate.countryISO3 ?? "")") + if candidate.street != nil { + output.append("\(candidate.street ?? "") \(candidate.locality ?? "") \(candidate.administrativeArea ?? ""), \(candidate.countryISO3 ?? "")") + } else { + output.append("\(candidate.entries ?? 0) \(candidate.addressText ?? "") \(candidate.addressID ?? "")") + } } return output diff --git a/samples/Sources/swiftExamples/USReverseGeoExample.swift b/samples/Sources/swiftExamples/USReverseGeoExample.swift index 8a8b6c8..2fadd8f 100644 --- a/samples/Sources/swiftExamples/USReverseGeoExample.swift +++ b/samples/Sources/swiftExamples/USReverseGeoExample.swift @@ -20,7 +20,7 @@ class USReverseGeoExample { // Documentation for input fields can be found at: // https://smartystreets.com/docs/cloud/us-reverse-geo-api#http-input-fields - var lookup = USReverseGeoLookup(latitude: 40.27644, longitude: -111.65747) + var lookup = USReverseGeoLookup(latitude: 40.27644, longitude: -111.65747, source: "postal") var error: NSError! = nil