Files
services/geocoding/handler/handler_test.go
2021-05-05 10:37:23 +01:00

275 lines
6.4 KiB
Go

package handler_test
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"googlemaps.github.io/maps"
"github.com/micro/services/geocoding/handler"
pb "github.com/micro/services/geocoding/proto"
)
const (
validReponse = `{
"results":[
{
"address_components":[
{
"long_name":"160",
"types":[
"street_number"
]
},
{
"long_name":"Grays Inn Road",
"types":[
"route"
]
},
{
"long_name":"Holborn",
"types":[
"neighborhood"
]
},
{
"long_name":"Santa Clara County",
"types":[
"administrative_area_level_2",
"political"
]
},
{
"long_name":"London",
"types":[
"political_town"
]
},
{
"long_name":"United Kingdom",
"types":[
"country",
"political"
]
},
{
"long_name":"WC1X 8ED",
"types":[
"postal_code"
]
}
],
"geometry":{
"location":{
"lat":51.522214,
"lng":-0.113565
}
},
"partial_math":false,
"place_id":"ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"types":[
"street_address"
]
}
],
"status":"OK"
}`
noResultsReponse = `{
"results": [],
"status": "OK"
}`
)
func TestGeocoding(t *testing.T) {
tt := []struct {
Name string
ResponseBody string
ResponseCode int
MapQuery string
Error error
Address *pb.Address
Result *pb.Address
}{
{
Name: "Invalid address",
ResponseBody: noResultsReponse,
ResponseCode: http.StatusOK,
Address: &pb.Address{
LineOne: "Foobar Street",
},
Error: handler.ErrNoResults,
MapQuery: "Foobar Street",
},
{
Name: "Valid address",
ResponseBody: validReponse,
ResponseCode: http.StatusOK,
Address: &pb.Address{
LineOne: "160 Grays Inn Road",
LineTwo: "Holborn",
Postcode: "wc1x8ed",
Country: "United Kingdom",
},
MapQuery: "160 Grays Inn Road, Holborn, wc1x8ed, United Kingdom",
},
{
Name: "Maps error",
ResponseCode: http.StatusInternalServerError,
Address: &pb.Address{
LineOne: "Foobar Street",
},
Error: handler.ErrDownstream,
ResponseBody: "{}",
MapQuery: "Foobar Street",
},
}
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
var query string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
query = r.URL.Query().Get("address")
w.WriteHeader(tc.ResponseCode)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
fmt.Fprintln(w, tc.ResponseBody)
}))
defer server.Close()
m, err := maps.NewClient(maps.WithBaseURL(server.URL), maps.WithAPIKey("shh"))
if err != nil {
t.Fatal(err)
}
h := &handler.Geocoding{Maps: m}
var rsp pb.LookupResponse
address := tc.Address.LineOne
if len(tc.Address.LineTwo) > 0 {
address = fmt.Sprintf("%s, %s", address, tc.Address.LineTwo)
}
if len(tc.Address.Postcode) > 0 {
address = fmt.Sprintf("%s, %s", address, tc.Address.Postcode)
}
if len(tc.Address.Country) > 0 {
address = fmt.Sprintf("%s, %s", address, tc.Address.Country)
}
err = h.Lookup(context.TODO(), &pb.LookupRequest{
Address: address,
Postcode: tc.Address.Postcode,
Country: tc.Address.Country,
}, &rsp)
assert.Equal(t, tc.MapQuery, query)
assert.Equal(t, tc.Error, err)
if tc.Result != nil {
assert.Equal(t, tc.Result.LineOne, rsp.Address.LineOne)
assert.Equal(t, tc.Result.LineTwo, rsp.Address.LineTwo)
assert.Equal(t, tc.Result.City, rsp.Address.City)
assert.Equal(t, tc.Result.Country, rsp.Address.Country)
assert.Equal(t, tc.Result.Postcode, rsp.Address.Postcode)
}
})
}
}
func TestReverseGeocoding(t *testing.T) {
tt := []struct {
Name string
ResponseBody string
ResponseCode int
Error error
Latitude float64
Longitude float64
Result *pb.Address
}{
{
Name: "Missing longitude",
Latitude: 51.522214,
Error: handler.ErrMissingLongitude,
},
{
Name: "Missing latitude",
Longitude: -0.113565,
Error: handler.ErrMissingLatitude,
},
{
Name: "Invalid address",
ResponseBody: noResultsReponse,
ResponseCode: http.StatusOK,
Latitude: 999.999999,
Longitude: 999.999999,
Error: handler.ErrNoResults,
},
{
Name: "Valid address",
ResponseBody: validReponse,
ResponseCode: http.StatusOK,
Latitude: 51.522214,
Longitude: -0.113565,
Result: &pb.Address{
LineOne: "160 Grays Inn Road",
LineTwo: "Holborn",
Postcode: "WC1X 8ED",
Country: "United Kingdom",
},
},
{
Name: "Maps error",
Latitude: 51.522214,
Longitude: -0.113565,
ResponseCode: http.StatusInternalServerError,
Error: handler.ErrDownstream,
ResponseBody: "{}",
},
}
for _, tc := range tt {
t.Run(tc.Name, func(t *testing.T) {
var lat, lng string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if coords := strings.Split(string(r.URL.Query().Get("latlng")), ","); len(coords) == 2 {
lat = coords[0]
lng = coords[1]
}
w.WriteHeader(tc.ResponseCode)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
fmt.Fprintln(w, tc.ResponseBody)
}))
defer server.Close()
m, err := maps.NewClient(maps.WithBaseURL(server.URL), maps.WithAPIKey("shh"))
if err != nil {
t.Fatal(err)
}
h := &handler.Geocoding{Maps: m}
var rsp pb.ReverseResponse
err = h.Reverse(context.TODO(), &pb.ReverseRequest{
Latitude: tc.Latitude, Longitude: tc.Longitude,
}, &rsp)
assert.Equal(t, tc.Error, err)
if tc.Latitude != 0.0 && tc.Longitude != 0.0 {
assert.Equal(t, fmt.Sprintf("%f", tc.Latitude), lat)
assert.Equal(t, fmt.Sprintf("%f", tc.Longitude), lng)
}
if tc.Result != nil {
assert.Equal(t, tc.Result.LineOne, rsp.Address.LineOne)
assert.Equal(t, tc.Result.LineTwo, rsp.Address.LineTwo)
assert.Equal(t, tc.Result.City, rsp.Address.City)
assert.Equal(t, tc.Result.Country, rsp.Address.Country)
assert.Equal(t, tc.Result.Postcode, rsp.Address.Postcode)
}
})
}
}