diff --git a/Sources/SmartyStreets/ClientBuilder.swift b/Sources/SmartyStreets/ClientBuilder.swift index c5310e8..f55a7ec 100644 --- a/Sources/SmartyStreets/ClientBuilder.swift +++ b/Sources/SmartyStreets/ClientBuilder.swift @@ -15,7 +15,8 @@ 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 internationalAutocompleteApiDeprecatedURL:String = "https://international-autocomplete.api.smarty.com/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,12 +134,18 @@ 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 buildInternationalAutocompleteApiDeprecatedClient() -> InternationalAutocompleteDeprecatedClient { + ensureURLPrefixNotNil(url: self.internationalAutocompleteApiDeprecatedURL) + let serializer = InternationalAutocompleteDeprecatedSerializer() + return InternationalAutocompleteDeprecatedClient(sender:buildSender(), serializer:serializer) + } public func buildUSAutocompleteApiClient() -> USAutocompleteClient { // Deprecated ensureURLPrefixNotNil(url: self.usAutocompleteApiURL) 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/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedCandidate.swift b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedCandidate.swift new file mode 100644 index 0000000..3943ba1 --- /dev/null +++ b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedCandidate.swift @@ -0,0 +1,35 @@ +import Foundation + +@objcMembers public class InternationalAutocompleteDeprecatedCandidate: NSObject, Codable { + // A candidate is a possible match for an address that was submitted. + // + // See "https://smartystreets.com/docs/cloud/international-address-autocomplete-api" + + 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? + + 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" + } + + 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 + } +} diff --git a/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedClient.swift b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedClient.swift new file mode 100644 index 0000000..2684f5c --- /dev/null +++ b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedClient.swift @@ -0,0 +1,64 @@ +import Foundation + +public class InternationalAutocompleteDeprecatedClient: NSObject { + // It is recommended to instantiate this class using SSClientBuilder + + var sender:SmartySender + public var serializer:SmartySerializer + + public init(sender:Any, serializer:SmartySerializer) { + self.sender = sender as! SmartySender + self.serializer = serializer + } + + @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:InternationalAutocompleteDeprecatedResult + + if let payload = response?.payload { + result = self.serializer.Deserialize(payload: payload, error: &error.pointee) as? InternationalAutocompleteDeprecatedResult ?? InternationalAutocompleteDeprecatedResult(dictionary: NSDictionary()) + } else { + result = InternationalAutocompleteDeprecatedResult(dictionary: NSDictionary()) + } + + // Naming of parameters to allow JSON deserialization + if error.pointee != nil { return false } + + lookup.pointee.result = result + return true + } else { + return false + } + } + + func buildRequest(lookup:InternationalAutocompleteDeprecatedLookup) -> SmartyRequest { + let request = SmartyRequest() + + 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 != InternationalAutocompleteDeprecatedLookup.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/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedLookup.swift b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedLookup.swift new file mode 100644 index 0000000..1f2d98b --- /dev/null +++ b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedLookup.swift @@ -0,0 +1,71 @@ +import Foundation + +@objcMembers public class InternationalAutocompleteDeprecatedLookup: NSObject, Codable { + // In addition to holding all of the input data for this lookup, this class also will contain the result + // of the lookup after it comes back from the API. + // + // 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:InternationalAutocompleteDeprecatedResult? + public var country:String? + public var search: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 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 = InternationalAutocompleteDeprecatedLookup.SSMaxResults + self.distance = InternationalAutocompleteDeprecatedLookup.SSDistance + } + + public func withSearch(search:String) -> InternationalAutocompleteDeprecatedLookup { + self.search = search + return self + } + + func getResultAtIndex(index:Int) -> InternationalAutocompleteDeprecatedCandidate{ + if let result = self.result { + return result.candidates![index] + } else { + return InternationalAutocompleteDeprecatedCandidate(dictionary: NSDictionary()) + } + } + + public func setMaxResults(maxResults: Int, error: inout NSError?) { + if maxResults > 0 && maxResults <= 10 { + self.maxResults = maxResults + } else { + let details = [NSLocalizedDescriptionKey:"Max suggestions must be a postive integer no larger than 10."] + error = NSError(domain: SmartyErrors().SSErrorDomain, code: SmartyErrors.SSErrors.NotPositiveIntergerError.rawValue, userInfo: details) + } + } +} diff --git a/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedResult.swift b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedResult.swift new file mode 100644 index 0000000..6dd0a23 --- /dev/null +++ b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedResult.swift @@ -0,0 +1,31 @@ +import Foundation + +@objcMembers public class InternationalAutocompleteDeprecatedResult: NSObject, Codable { + + public var candidates:[InternationalAutocompleteDeprecatedCandidate]? + + public init(dictionary: NSDictionary) { + super.init() + if let candidates = dictionary["candidates"] { + self.candidates = convertToCandidateObjects(candidates as! [[String:Any]]) + } else { + self.candidates = [InternationalAutocompleteDeprecatedCandidate]() + } + } + + func convertToCandidateObjects(_ object:[[String:Any]]) -> [InternationalAutocompleteDeprecatedCandidate] { + var mutable = [InternationalAutocompleteDeprecatedCandidate]() + for suggestion in object { + mutable.append(InternationalAutocompleteDeprecatedCandidate(dictionary: suggestion as NSDictionary)) + } + return mutable + } + + func getCandidateAtIndex(index: Int) -> InternationalAutocompleteDeprecatedCandidate { + if let candidates = self.candidates { + return candidates[index] + } else { + return InternationalAutocompleteDeprecatedCandidate(dictionary: NSDictionary()) + } + } +} diff --git a/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedSerializer.swift b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedSerializer.swift new file mode 100644 index 0000000..6d14196 --- /dev/null +++ b/Sources/SmartyStreets/InternationalAutocompleteDeprecated/InternationalAutocompleteDeprecatedSerializer.swift @@ -0,0 +1,47 @@ +import Foundation + +public class InternationalAutocompleteDeprecatedSerializer: SmartySerializer { + + override public init() {} + + override func Serialize(obj: Any?, error: inout NSError!) -> Data! { + let raw:[InternationalAutocompleteDeprecatedLookup]? = obj as? [InternationalAutocompleteDeprecatedLookup] + let smartyErrors = SmartyErrors() + let jsonEncoder = JSONEncoder() + if raw == nil { + let details = [NSLocalizedDescriptionKey: "The object to be serialized is nil"] + error = NSError(domain: smartyErrors.SSErrorDomain, code: SmartyErrors.SSErrors.ObjectNilError.rawValue, userInfo: details) + return nil + } + + do { + let jsonData = try jsonEncoder.encode(raw) as Data + return jsonData + } catch let jsonError { + let details = [NSLocalizedDescriptionKey: jsonError.localizedDescription] + error = NSError(domain: smartyErrors.SSErrorDomain, code: SmartyErrors.SSErrors.ObjectInvalidTypeError.rawValue, userInfo: details) + } + + + return nil + } + + override public func Deserialize(payload: Data?, error: inout NSError!) -> Any! { + let smartyErrors = SmartyErrors() + let jsonDecoder = JSONDecoder() + if payload == nil { + let details = [NSLocalizedDescriptionKey: "The payload is nil."] + error = NSError(domain: smartyErrors.SSErrorDomain, code: SmartyErrors.SSErrors.ObjectNilError.rawValue, userInfo: details) + return nil + } + + do { + let result:InternationalAutocompleteDeprecatedResult = try jsonDecoder.decode(InternationalAutocompleteDeprecatedResult.self, from: payload!) + return result + } catch let jsonError { + let details = [NSLocalizedDescriptionKey:jsonError.localizedDescription] + error = NSError(domain: smartyErrors.SSErrorDomain, code: SmartyErrors.SSErrors.ObjectInvalidTypeError.rawValue, userInfo: details) + return nil + } + } +} 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..352f7fc 100644 --- a/Tests/SmartyStreetsTests/ClientBuilderTests.swift +++ b/Tests/SmartyStreetsTests/ClientBuilderTests.swift @@ -22,6 +22,8 @@ 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.internationalAutocompleteApiDeprecatedURL, "https://international-autocomplete.api.smarty.com/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/InternationalAutocompleteDeprecatedTests/InternationalAutocompleteDeprecatedClientTests.swift b/Tests/SmartyStreetsTests/InternationalAutocompleteDeprecatedTests/InternationalAutocompleteDeprecatedClientTests.swift new file mode 100644 index 0000000..8d5920e --- /dev/null +++ b/Tests/SmartyStreetsTests/InternationalAutocompleteDeprecatedTests/InternationalAutocompleteDeprecatedClientTests.swift @@ -0,0 +1,74 @@ +import XCTest +import SmartyStreets + +class InternationalAutocompleteDeprecatedClientTests: XCTestCase { + + var capturingSender:RequestCapturingSender! + var error:NSError! + + override func setUp() { + super.setUp() + self.capturingSender = RequestCapturingSender() + self.error = nil + } + + override func tearDown() { + super.tearDown() + self.capturingSender = nil + self.error = nil + } + + func testSendingSinglePrefixOnlyLookup() { + let sender = URLPrefixSender(urlPrefix: "http://localhost/", inner: self.capturingSender as Any) + let serializer = MockSerializer(result: InternationalAutocompleteDeprecatedResult(dictionary: NSDictionary())) + let client = InternationalAutocompleteDeprecatedClient(sender:sender, serializer:serializer) + var lookup = InternationalAutocompleteDeprecatedLookup() + lookup.search = "1" + lookup.country = "2" + lookup.locality = "3" + lookup.administrativeArea = "4" + lookup.maxResults = 5 + lookup.distance = 7 + lookup.geolocation = InternationalAutocompleteDeprecatedLookup.InternationalGeolocateType.geocodes + lookup.postalCode = "6" + lookup.longitude = 112.1 + lookup.latitude = -23.4 + + _ = 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"]) + XCTAssertNil(self.error) + } + + func testSendingSingleMinimumParams() { + let sender = URLPrefixSender(urlPrefix: "http://localhost/", inner: self.capturingSender as Any) + let serializer = MockSerializer(result: InternationalAutocompleteDeprecatedResult(dictionary: NSDictionary())) + let client = InternationalAutocompleteDeprecatedClient(sender:sender, serializer:serializer) + var lookup = InternationalAutocompleteDeprecatedLookup() + lookup.search = "1" + lookup.country = "2" + + _ = client.sendLookup(lookup:&lookup, error:&error) + + 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/InternationalAutocompleteDeprecatedTests/InternationalAutocompleteDeprecatedResultTests.swift b/Tests/SmartyStreetsTests/InternationalAutocompleteDeprecatedTests/InternationalAutocompleteDeprecatedResultTests.swift new file mode 100644 index 0000000..44e7b71 --- /dev/null +++ b/Tests/SmartyStreetsTests/InternationalAutocompleteDeprecatedTests/InternationalAutocompleteDeprecatedResultTests.swift @@ -0,0 +1,57 @@ +import XCTest +@testable import SmartyStreets + +class InternationalAutocompleteDeprecatedResultTests: XCTestCase { + + var obj:NSDictionary! + + override func setUp() { + super.setUp() + self.obj = [ + "candidates": [ + [ + "street":"0", + "locality":"1", + "administrative_area":"2", + "super_administrative_area":"3", + "sub_administrative_area":"4", + "postal_code":"5", + "country_iso3":"6" + ], + [ + "street":"7", + "locality":"8", + "administrative_area":"9", + "super_administrative_area":"super", + "sub_administrative_area":"sub", + "postal_code":"10", + "country_iso3":"11" + ] + ] + ] + } + + override func tearDown() { + super.tearDown() + } + + func testAllFieldsFilledCorrectly() { + let result = InternationalAutocompleteDeprecatedResult(dictionary: obj) + + 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("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) + } +} diff --git a/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift b/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift index 076c85d..959d248 100644 --- a/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift +++ b/Tests/SmartyStreetsTests/InternationalAutocompleteTests/InternationalAutocompleteClientTests.swift @@ -26,26 +26,18 @@ class InternationalAutocompleteClientTests: XCTestCase { 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("/6", capturingSender.request.urlPrefix) XCTAssertNil(self.error) } @@ -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..3470edd 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/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/samples/Sources/swiftExamples/InternationalAutocompleteDeprecatedExample.swift b/samples/Sources/swiftExamples/InternationalAutocompleteDeprecatedExample.swift new file mode 100644 index 0000000..7009262 --- /dev/null +++ b/samples/Sources/swiftExamples/InternationalAutocompleteDeprecatedExample.swift @@ -0,0 +1,55 @@ +import Foundation +import SmartyStreets + +class InternationalAutocompleteDeprecatedExample { + func run() -> String { + // The appropriate license values to be used for your subscriptions + // can be found on the Subscriptions page of the account dashboard. + // https://www.smartystreets.com/docs/cloud/licensing + // We recommend storing your authentication credentials in environment variables. + // for server-to-server requests, use this code: + //let authId = getEnvironmentVar("SMARTY_AUTH_ID") ?? "" + //let authToken = getEnvironmentVar("SMARTY_AUTH_TOKEN") ?? "" + //let client = ClientBuilder(authId:authId, authToken:authToken).withLicenses(licenses: ["international-autocomplete-cloud"]).buildInternationalAutocompleteApiClient() + + // for client-side requests (browser/mobile), use this code: + let id = getEnvironmentVar("SMARTY_AUTH_WEB") ?? "" + let hostname = getEnvironmentVar("SMARTY_AUTH_REFERER") ?? "" + let client = ClientBuilder(id: id, hostname: hostname).withLicenses(licenses: ["international-autocomplete-cloud"]).buildInternationalAutocompleteApiDeprecatedClient() + + // Documentation for input fields can be found at: + // https://smartystreets.com/docs/cloud/international-address-autocomplete-api#http-input-fields + + var lookup = InternationalAutocompleteDeprecatedLookup() + lookup.country = "FRA" + lookup.locality = "Paris" + lookup.search = "Louis" + + var error: NSError! = nil + + _ = client.sendLookup(lookup: &lookup, error:&error) + if let error = error { + let output = """ + Domain: \(error.domain) + Error Code: \(error.code) + Description:\n\(error.userInfo[NSLocalizedDescriptionKey] as! NSString) + """ + NSLog(output) + return output + } + + let results:InternationalAutocompleteDeprecatedResult = lookup.result ?? InternationalAutocompleteDeprecatedResult(dictionary: NSDictionary()) + let candidates:[InternationalAutocompleteDeprecatedCandidate] = results.candidates ?? [] + var output = "Results:\n" + + if candidates.count == 0 { + return "Error. Address is not valid" + } + + for candidate in candidates { + output.append("\(candidate.street ?? "") \(candidate.locality ?? "") \(candidate.administrativeArea ?? ""), \(candidate.countryISO3 ?? "")") + } + + return output + } +} 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 diff --git a/samples/Sources/swiftExamples/main.swift b/samples/Sources/swiftExamples/main.swift index 5abc817..db15068 100644 --- a/samples/Sources/swiftExamples/main.swift +++ b/samples/Sources/swiftExamples/main.swift @@ -10,4 +10,5 @@ print(USAutocompleteProExample().run()) print(USExtractExample().run()) print(InternationalStreetExample().run()) print(InternationalAutocompleteExample().run()) +print(InternationalAutocompleteDeprecatedExample().run()) print(USReverseGeoExample().run())