-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
558 additions
and
142 deletions.
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
examples/international-autocomplete-api-deprecated/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
international_autocomplete_deprecated "github.com/smartystreets/smartystreets-go-sdk/international-autocomplete-api-deprecated" | ||
"github.com/smartystreets/smartystreets-go-sdk/wireup" | ||
"log" | ||
"os" | ||
) | ||
|
||
func main() { | ||
log.SetFlags(log.Ltime | log.Llongfile) | ||
|
||
client := wireup.BuildInternationalAutocompleteAPIDeprecatedClient( | ||
wireup.WebsiteKeyCredential(os.Getenv("SMARTY_AUTH_WEB"), os.Getenv("SMARTY_AUTH_REFERER")), | ||
//wireup.SecretKeyCredential(os.Getenv("SMARTY_AUTH_ID"), os.Getenv("SMARTY_AUTH_TOKEN")), | ||
// The appropriate license values to be used for your subscriptions | ||
// can be found on the Subscriptions page the account dashboard. | ||
// https://www.smartystreets.com/docs/cloud/licensing | ||
wireup.WithLicenses("international-autocomplete-cloud"), | ||
) | ||
|
||
// Documentation for input fields can be found at: | ||
// https://smartystreets.com/docs/cloud/us-autocomplete-api#http-request-input-fields | ||
|
||
lookup := &international_autocomplete_deprecated.Lookup{ | ||
Country: "FRA", | ||
Search: "Louis", | ||
Locality: "Paris", | ||
} | ||
|
||
if err := client.SendLookupWithContext(context.Background(), lookup); err != nil { | ||
log.Fatal("Error sending batch:", err) | ||
} | ||
|
||
fmt.Printf("Results for input: [%s]\n", lookup.Search) | ||
for s, candidate := range lookup.Result.Candidates { | ||
fmt.Printf("#%d: %#v\n", s, candidate) | ||
} | ||
|
||
log.Println("OK") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
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"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package international_autocomplete_api | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
|
||
sdk "github.com/smartystreets/smartystreets-go-sdk" | ||
) | ||
|
||
type Client struct { | ||
sender sdk.RequestSender | ||
} | ||
|
||
// NewClient creates a client with the provided sender. | ||
func NewClient(sender sdk.RequestSender) *Client { | ||
return &Client{sender: sender} | ||
} | ||
|
||
func (c *Client) SendLookup(lookup *Lookup) error { | ||
return c.SendLookupWithContext(context.Background(), lookup) | ||
} | ||
|
||
func (c *Client) SendLookupWithContext(ctx context.Context, lookup *Lookup) error { | ||
if lookup == nil || len(lookup.Search) == 0 { | ||
return nil | ||
} | ||
|
||
request := buildRequest(lookup) | ||
request = request.WithContext(ctx) | ||
response, err := c.sender.Send(request) | ||
if err != nil { | ||
return err | ||
} else { | ||
return deserializeResponse(response, lookup) | ||
} | ||
} | ||
|
||
func deserializeResponse(response []byte, lookup *Lookup) error { | ||
err := json.Unmarshal(response, &lookup.Result) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func buildRequest(lookup *Lookup) *http.Request { | ||
request, _ := http.NewRequest("GET", suggestURL, 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 | ||
} | ||
|
||
const suggestURL = "/lookup" // Remaining parts will be completed later by the sdk.BaseURLClient. |
140 changes: 140 additions & 0 deletions
140
international-autocomplete-api-deprecated/client_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package international_autocomplete_api | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/smarty/assertions/should" | ||
"github.com/smarty/gunit" | ||
) | ||
|
||
func TestClientFixture(t *testing.T) { | ||
gunit.Run(new(ClientFixture), t) | ||
} | ||
|
||
type ClientFixture struct { | ||
*gunit.Fixture | ||
|
||
sender *FakeSender | ||
client *Client | ||
|
||
input *Lookup | ||
} | ||
|
||
func (f *ClientFixture) Setup() { | ||
f.sender = &FakeSender{} | ||
f.client = NewClient(f.sender) | ||
f.input = new(Lookup) | ||
} | ||
|
||
func (f *ClientFixture) TestAddressLookupSerializedAndSentWithContext__ResponseSuggestionsIncorporatedIntoLookup() { | ||
f.sender.response = `{ | ||
"candidates": [ | ||
{ | ||
"street": "1", | ||
"locality": "2", | ||
"administrative_area": "3", | ||
"super_administrative_area": "4", | ||
"sub_administrative_area": "5", | ||
"postal_code": "6", | ||
"country_iso3": "7" | ||
}, | ||
{ | ||
"street": "8", | ||
"locality": "9", | ||
"administrative_area": "10", | ||
"super_administrative_area": "11", | ||
"sub_administrative_area": "12", | ||
"postal_code": "13", | ||
"country_iso3": "14" | ||
} | ||
] | ||
}` | ||
f.input.Search = "42" | ||
|
||
ctx := context.WithValue(context.Background(), "key", "value") | ||
err := f.client.SendLookupWithContext(ctx, f.input) | ||
|
||
f.So(err, should.BeNil) | ||
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) | ||
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.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: "8", | ||
Locality: "9", | ||
AdministrativeArea: "10", | ||
SuperAdministrativeArea: "11", | ||
SubAdministrativeArea: "12", | ||
PostalCode: "13", | ||
CountryIso3: "14", | ||
}, | ||
}}) | ||
} | ||
func (f *ClientFixture) TestNilLookupNOP() { | ||
err := f.client.SendLookup(nil) | ||
f.So(err, should.BeNil) | ||
f.So(f.sender.request, should.BeNil) | ||
} | ||
|
||
func (f *ClientFixture) TestEmptyLookup_NOP() { | ||
err := f.client.SendLookup(new(Lookup)) | ||
f.So(err, should.BeNil) | ||
f.So(f.sender.request, should.BeNil) | ||
} | ||
|
||
func (f *ClientFixture) TestSenderErrorPreventsDeserialization() { | ||
f.sender.err = errors.New("GOPHERS!") | ||
f.sender.response = `{"candidates":[ | ||
{"text": "1"}, | ||
{"text": "2"}, | ||
{"text": "3"} | ||
]}` // would be deserialized if not for the err (above) | ||
f.input.Search = "HI" | ||
|
||
err := f.client.SendLookup(f.input) | ||
|
||
f.So(err, should.NotBeNil) | ||
f.So(f.input.Result, should.BeNil) | ||
} | ||
|
||
func (f *ClientFixture) TestDeserializationErrorPreventsDeserialization() { | ||
f.sender.response = `I can't haz JSON` | ||
f.input.Search = "HI" | ||
|
||
err := f.client.SendLookup(f.input) | ||
|
||
f.So(err, should.NotBeNil) | ||
f.So(f.input.Result, should.BeNil) | ||
} | ||
|
||
////////////////////////////////////////////////////////////////// | ||
|
||
type FakeSender struct { | ||
callCount int | ||
request *http.Request | ||
|
||
response string | ||
err error | ||
} | ||
|
||
func (f *FakeSender) Send(request *http.Request) ([]byte, error) { | ||
f.callCount++ | ||
f.request = request | ||
return []byte(f.response), f.err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package international_autocomplete_api | ||
|
||
import ( | ||
"math" | ||
"net/url" | ||
"strconv" | ||
) | ||
|
||
const ( | ||
maxResultsDefault = 5 | ||
distanceDefault = 5 | ||
) | ||
|
||
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 | ||
} | ||
|
||
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 { | ||
query.Set("country", l.Country) | ||
} | ||
} | ||
func (l Lookup) populateSearch(query url.Values) { | ||
if len(l.Search) > 0 { | ||
query.Set("search", l.Search) | ||
} | ||
} | ||
func (l Lookup) populateMaxResults(query url.Values) { | ||
maxResults := l.MaxResults | ||
if maxResults < 1 { | ||
maxResults = maxResultsDefault | ||
} | ||
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) | ||
} | ||
} | ||
func (l Lookup) populatePostalCode(query url.Values) { | ||
if len(l.PostalCode) > 0 { | ||
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("") | ||
) |
Oops, something went wrong.