Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support intl autocomplete v2 #34

Merged
merged 1 commit into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion examples/international-autocomplete-api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ func main() {
log.Fatal("Error sending batch:", err)
}

fmt.Printf("Results for input: [%s]\n", lookup.Search)
if len(lookup.Search) > 0 {
fmt.Printf("Results for input: [%s]\n", lookup.Search)
} else {
fmt.Printf("Results for input: [%s]\n", lookup.AddressID)
}
for s, candidate := range lookup.Result.Candidates {
fmt.Printf("#%d: %#v\n", s, candidate)
}
Expand Down
16 changes: 9 additions & 7 deletions international-autocomplete-api/candidate.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package international_autocomplete_api

type Candidate struct {
Street string `json:"street"`
Locality string `json:"locality"`
AdministrativeArea string `json:"administrative_area"`
SuperAdministrativeArea string `json:"super_administrative_area"`
SubAdministrativeArea string `json:"sub_administrative_area"`
PostalCode string `json:"postal_code"`
CountryIso3 string `json:"country_iso3"`
Street string `json:"street"`
Locality string `json:"locality"`
AdministrativeArea string `json:"administrative_area"`
PostalCode string `json:"postal_code"`
CountryIso3 string `json:"country_iso3"`

Entries int `json:"entries"`
AddressText string `json:"address_text"`
AddressID string `json:"address_id"`
}
9 changes: 7 additions & 2 deletions international-autocomplete-api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (c *Client) SendLookup(lookup *Lookup) error {
}

func (c *Client) SendLookupWithContext(ctx context.Context, lookup *Lookup) error {
if lookup == nil || len(lookup.Search) == 0 {
if lookup == nil || len(lookup.Country) == 0 || (len(lookup.Search) == 0 && len(lookup.AddressID) == 0) {
return nil
}

Expand All @@ -45,11 +45,16 @@ func deserializeResponse(response []byte, lookup *Lookup) error {
}

func buildRequest(lookup *Lookup) *http.Request {
request, _ := http.NewRequest("GET", suggestURL, nil) // We control the method and the URL. This is safe.
var addressID = ""
if len(lookup.AddressID) > 0 {
addressID = "/" + lookup.AddressID
}
request, _ := http.NewRequest("GET", suggestURL+addressID, nil) // We control the method and the URL. This is safe.
query := request.URL.Query()
lookup.populate(query)
request.URL.RawQuery = query.Encode()
return request
}

// TODO support /lookup and /v2/lookup
const suggestURL = "/lookup" // Remaining parts will be completed later by the sdk.BaseURLClient.
61 changes: 35 additions & 26 deletions international-autocomplete-api/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,20 @@ func (f *ClientFixture) TestAddressLookupSerializedAndSentWithContext__ResponseS
"street": "1",
"locality": "2",
"administrative_area": "3",
"super_administrative_area": "4",
"sub_administrative_area": "5",
"postal_code": "6",
"country_iso3": "7"
"postal_code": "4",
"country_iso3": "5"
},
{
"street": "8",
"locality": "9",
"administrative_area": "10",
"super_administrative_area": "11",
"sub_administrative_area": "12",
"postal_code": "13",
"country_iso3": "14"
"street": "6",
"locality": "7",
"administrative_area": "8",
"postal_code": "9",
"country_iso3": "10"
}
]
}`
f.input.Search = "42"
f.input.Country = "FRA"

ctx := context.WithValue(context.Background(), "key", "value")
err := f.client.SendLookupWithContext(ctx, f.input)
Expand All @@ -62,27 +59,23 @@ func (f *ClientFixture) TestAddressLookupSerializedAndSentWithContext__ResponseS
f.So(f.sender.request.Method, should.Equal, "GET")
f.So(f.sender.request.URL.Path, should.Equal, suggestURL)
f.So(f.sender.request.URL.Query().Get("search"), should.Equal, "42")
f.So(f.sender.request.URL.String(), should.Equal, suggestURL+"?distance=5&max_results=5&search=42")
f.So(f.sender.request.URL.String(), should.Equal, suggestURL+"?country=FRA&max_results=5&search=42")
f.So(f.sender.request.Context(), should.Resemble, ctx)

f.So(f.input.Result, should.Resemble, &Result{Candidates: []*Candidate{
{
Street: "1",
Locality: "2",
AdministrativeArea: "3",
SuperAdministrativeArea: "4",
SubAdministrativeArea: "5",
PostalCode: "6",
CountryIso3: "7",
Street: "1",
Locality: "2",
AdministrativeArea: "3",
PostalCode: "4",
CountryIso3: "5",
},
{
Street: "8",
Locality: "9",
AdministrativeArea: "10",
SuperAdministrativeArea: "11",
SubAdministrativeArea: "12",
PostalCode: "13",
CountryIso3: "14",
Street: "6",
Locality: "7",
AdministrativeArea: "8",
PostalCode: "9",
CountryIso3: "10",
},
}})
}
Expand All @@ -106,6 +99,7 @@ func (f *ClientFixture) TestSenderErrorPreventsDeserialization() {
{"text": "3"}
]}` // would be deserialized if not for the err (above)
f.input.Search = "HI"
f.input.Country = "FRA"

err := f.client.SendLookup(f.input)

Expand All @@ -116,13 +110,28 @@ func (f *ClientFixture) TestSenderErrorPreventsDeserialization() {
func (f *ClientFixture) TestDeserializationErrorPreventsDeserialization() {
f.sender.response = `I can't haz JSON`
f.input.Search = "HI"
f.input.Country = "FRA"

err := f.client.SendLookup(f.input)

f.So(err, should.NotBeNil)
f.So(f.input.Result, should.BeNil)
}

func (f *ClientFixture) TestAddressIDAppendsToURL() {
f.input.Country = "FRA"
f.input.AddressID = "thisisid"

err := f.client.SendLookup(f.input)

f.So(err, should.NotBeNil)

f.So(f.sender.request, should.NotBeNil)
f.So(f.sender.request.Method, should.Equal, "GET")
f.So(f.sender.request.URL.Path, should.Equal, suggestURL+"/thisisid")
f.So(f.sender.request.URL.String(), should.Equal, suggestURL+"/thisisid?country=FRA&max_results=5")
}

//////////////////////////////////////////////////////////////////

type FakeSender struct {
Expand Down
63 changes: 7 additions & 56 deletions international-autocomplete-api/lookup.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package international_autocomplete_api

import (
"math"
"net/url"
"strconv"
)
Expand All @@ -12,30 +11,21 @@ const (
)

type Lookup struct {
Country string
Search string
MaxResults int
Distance int
Geolocation InternationalGeolocateType
AdministrativeArea string
Locality string
PostalCode string
Latitude float64
Longitude float64
Result *Result
Country string
Search string
AddressID string
MaxResults int
Locality string
PostalCode string
Result *Result
}

func (l Lookup) populate(query url.Values) {
l.populateCountry(query)
l.populateSearch(query)
l.populateMaxResults(query)
l.populateDistance(query)
l.populateGeolocation(query)
l.populateAdministrativeArea(query)
l.populateLocality(query)
l.populatePostalCode(query)
l.populateLatitude(query)
l.populateLongitude(query)
}
func (l Lookup) populateCountry(query url.Values) {
if len(l.Country) > 0 {
Expand All @@ -54,25 +44,6 @@ func (l Lookup) populateMaxResults(query url.Values) {
}
query.Set("max_results", strconv.Itoa(maxResults))
}
func (l Lookup) populateDistance(query url.Values) {
distance := l.Distance
if distance < 1 {
distance = distanceDefault
}
query.Set("distance", strconv.Itoa(distance))
}
func (l Lookup) populateGeolocation(query url.Values) {
if l.Geolocation != None {
query.Set("geolocation", string(l.Geolocation))
} else {
query.Del("geolocation")
}
}
func (l Lookup) populateAdministrativeArea(query url.Values) {
if len(l.AdministrativeArea) > 0 {
query.Set("include_only_administrative_area", l.AdministrativeArea)
}
}
func (l Lookup) populateLocality(query url.Values) {
if len(l.Locality) > 0 {
query.Set("include_only_locality", l.Locality)
Expand All @@ -83,23 +54,3 @@ func (l Lookup) populatePostalCode(query url.Values) {
query.Set("include_only_postal_code", l.PostalCode)
}
}
func (l Lookup) populateLatitude(query url.Values) {
if math.Floor(l.Latitude) != 0 {
query.Set("latitude", strconv.FormatFloat(l.Latitude, 'f', 8, 64))
}
}
func (l Lookup) populateLongitude(query url.Values) {
if math.Floor(l.Longitude) != 0 {
query.Set("longitude", strconv.FormatFloat(l.Longitude, 'f', 8, 64))
}
}

type InternationalGeolocateType string

const (
AdminArea = InternationalGeolocateType("adminarea")
Locality = InternationalGeolocateType("locality")
PostalCode = InternationalGeolocateType("postalcode")
Geocodes = InternationalGeolocateType("geocodes")
None = InternationalGeolocateType("")
)
47 changes: 5 additions & 42 deletions international-autocomplete-api/lookup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,23 @@ func (f *LookupFixture) populate() {
func (f *LookupFixture) TestDefaults() {
f.populate()

f.So(f.query, should.HaveLength, 2)
f.So(f.query, should.HaveLength, 1)
f.So(f.query.Get("max_results"), should.Equal, "5")
f.So(f.query.Get("distance"), should.Equal, "5")
}
func (f *LookupFixture) TestCountry() {
f.lookup.Country = "Hello, World!"

f.populate()

f.So(f.query, should.HaveLength, 3)
f.So(f.query, should.HaveLength, 2)
f.So(f.query.Get("country"), should.Equal, "Hello, World!")
}
func (f *LookupFixture) TestSearch() {
f.lookup.Search = "Hello, World!"

f.populate()

f.So(f.query, should.HaveLength, 3)
f.So(f.query, should.HaveLength, 2)
f.So(f.query.Get("search"), should.Equal, "Hello, World!")
}
func (f *LookupFixture) TestMaxResults() {
Expand All @@ -56,55 +55,19 @@ func (f *LookupFixture) TestMaxResults() {

f.So(f.query.Get("max_results"), should.Equal, "7")
}
func (f *LookupFixture) TestDistance() {
f.lookup.Distance = 3
f.populate()

f.So(f.query.Get("distance"), should.Equal, "3")
}
func (f *LookupFixture) TestGeolocation() {
typeList := []InternationalGeolocateType{AdminArea, Locality, PostalCode, Geocodes, None}
for _, geoLocateType := range typeList {
f.lookup.Geolocation = geoLocateType
f.populate()
f.So(f.query.Get("geolocation"), should.Equal, string(geoLocateType))
}
}
func (f *LookupFixture) TestAdministrativeArea() {
f.lookup.AdministrativeArea = "Hello, World!"

f.populate()

f.So(f.query, should.HaveLength, 3)
f.So(f.query.Get("include_only_administrative_area"), should.Equal, "Hello, World!")
}
func (f *LookupFixture) TestLocality() {
f.lookup.Locality = "Hello, World!"

f.populate()

f.So(f.query, should.HaveLength, 3)
f.So(f.query, should.HaveLength, 2)
f.So(f.query.Get("include_only_locality"), should.Equal, "Hello, World!")
}
func (f *LookupFixture) TestPostalCode() {
f.lookup.PostalCode = "Hello, World!"

f.populate()

f.So(f.query, should.HaveLength, 3)
f.So(f.query, should.HaveLength, 2)
f.So(f.query.Get("include_only_postal_code"), should.Equal, "Hello, World!")
}
func (f *LookupFixture) TestLatitude() {
f.lookup.Latitude = 123.458757987986

f.populate()

f.So(f.query.Get("latitude"), should.Equal, "123.45875799") // Here we only care about 8 digits of accuracy
}
func (f *LookupFixture) TestLongitude() {
f.lookup.Longitude = -134.877532234

f.populate()

f.So(f.query.Get("longitude"), should.Equal, "-134.87753223") // Here we only care about 8 digits of accuracy
}
2 changes: 1 addition & 1 deletion wireup/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func (b *clientBuilder) buildTransport() *http.Transport {

var (
defaultBaseURL_InternationalStreetAPI = &url.URL{Scheme: "https", Host: "international-street.api.smarty.com"}
defaultBaseURL_InternationalAutocompleteAPI = &url.URL{Scheme: "https", Host: "international-autocomplete.api.smarty.com"}
defaultBaseURL_InternationalAutocompleteAPI = &url.URL{Scheme: "https", Host: "international-autocomplete.api.smarty.com/v2"}
defaultBaseURL_USStreetAPI = &url.URL{Scheme: "https", Host: "us-street.api.smarty.com"}
defaultBaseURL_USZIPCodeAPI = &url.URL{Scheme: "https", Host: "us-zipcode.api.smarty.com"}
defaultBaseURL_USAutocompleteAPI = &url.URL{Scheme: "https", Host: "us-autocomplete.api.smarty.com"}
Expand Down
Loading