diff --git a/Makefile b/Makefile index 89c01f6..93d41db 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ sanity: .PHONY: sanity # Creates release binaries for each supported platform/architecture. -release: +release: | sanity @gox -osarch="darwin/386 darwin/amd64 linux/386 linux/amd64 linux/arm windows/386 windows/amd64" \ -output "bin/{{.Dir}}_{{.OS}}_{{.Arch}}" . .PHONY: release \ No newline at end of file diff --git a/README.md b/README.md index b19a4ab..edeb32f 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,30 @@ $ commuter -from gym -to-current 12 Minutes ``` +### Travel Modes + +By default, `commuter` assumes you are driving between locations. However, you can specify one or more commute methods using the `-drive`, `-walk`, `-bike` and `-transit` flags, like so: + +```sh +# Single mode: +$ commuter -walk -to work +7 Hours 50 Minutes + +# Multiple modes: +$ commuter -walk -transit -drive -bike -to work +Drive: 30 Minutes +Walk: 7 Hours 50 Minutes +Bike: 2 Hours 45 Minutes +Transit: 1 Hour 17 Minutes +``` + +And of course the different travel modes can be combined with your current location: + +```sh +$ commuter -bike -from-current -to gym +2 Hours 18 Minutes +``` + ## License ``` diff --git a/cli/cli.go b/cli/cli.go index e75ba49..83eae44 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -10,21 +10,29 @@ import ( ) const ( - cmdDefault = "commuter" - defaultFromParam = "from" - defaultFromUsage = "The starting point of your commute, either a named location [ex. 'work'] or an address [ex. '123 Main St. Toronto, Canada']." - defaultToParam = "to" - defaultToUsage = "The destination of your commute, either a named location [ex. 'work'] or an address [ex. '123 Main St. Toronto, Canada']." - defaultFromCurrentParam = "from-current" - defaultFromCurrentUsage = "Sets your current location as the starting point of your commute. This uses Geolocation to attempt to determine your Latitude/Longitude based on IP Address. [Accuracy may vary]" - defaultToCurrentParam = "to-current" - defaultToCurrentUsage = "Sets your current location as the destination of your commute. This uses Geolocation to attempt to determine your Latitude/Longitude based on IP Address. [Accuracy may vary]" + cmdCommute = "commuter" + commuteFromParam = "from" + commuteFromUsage = "The starting point of your commute, either a named location [ex. 'work'] or an address [ex. '123 Main St. Toronto, Canada']." + commuteToParam = "to" + commuteToUsage = "The destination of your commute, either a named location [ex. 'work'] or an address [ex. '123 Main St. Toronto, Canada']." + commuteFromCurrentParam = "from-current" + commuteFromCurrentUsage = "Sets your current location as the starting point of your commute. This uses Geolocation to attempt to determine your Latitude/Longitude based on IP Address. [Accuracy may vary]" + commuteToCurrentParam = "to-current" + commuteToCurrentUsage = "Sets your current location as the destination of your commute. This uses Geolocation to attempt to determine your Latitude/Longitude based on IP Address. [Accuracy may vary]" + commuteDriveParam = "drive" + commuteDriveUsage = "Adds 'driving' as a transit type [default]" + commuteWalkParam = "walk" + commuteWalkUsage = "Adds 'walking' as a transit type" + commuteBikeParam = "bike" + commuteBikeUsage = "Adds 'biking' as a transit type" + commuteTransitParam = "transit" + commuteTransitUsage = "Adds 'transit' as a transit type" cmdAdd = "add" addNameParam = "name" - addNameUsage = `The name of the location you'd like to add [ex. "work"]. (required)\n` + addNameUsage = "The name of the location you'd like to add [ex. 'work']. (required)\n" addLocationParam = "location" - addLocationUsage = `The location to be added [ex. "123 Main St. Toronto, Canada"]. (required)\n` + addLocationUsage = "The location to be added [ex. '123 Main St. Toronto, Canada']. (required)\n" cmdList = "list" ) diff --git a/cli/parser.go b/cli/parser.go index 461daae..b035480 100644 --- a/cli/parser.go +++ b/cli/parser.go @@ -53,13 +53,23 @@ func (a *ArgParser) parseCommuteCmd(conf *cmd.Configuration, args []string) (*cm c := cmd.CommuteCmd{Durationer: r, Locator: r} - f := flag.NewFlagSet(cmdDefault, flag.ExitOnError) - f.StringVar(&c.From, defaultFromParam, cmd.DefaultLocationAlias, defaultFromUsage) - f.BoolVar(&c.FromCurrent, defaultFromCurrentParam, false, defaultFromCurrentUsage) - f.StringVar(&c.To, defaultToParam, cmd.DefaultLocationAlias, defaultToUsage) - f.BoolVar(&c.ToCurrent, defaultToCurrentParam, false, defaultToCurrentUsage) + f := flag.NewFlagSet(cmdCommute, flag.ExitOnError) + f.StringVar(&c.From, commuteFromParam, cmd.DefaultLocationAlias, commuteFromUsage) + f.BoolVar(&c.FromCurrent, commuteFromCurrentParam, false, commuteFromCurrentUsage) + f.StringVar(&c.To, commuteToParam, cmd.DefaultLocationAlias, commuteToUsage) + f.BoolVar(&c.ToCurrent, commuteToCurrentParam, false, commuteToCurrentUsage) + + f.BoolVar(&c.Drive, commuteDriveParam, false, commuteDriveUsage) + f.BoolVar(&c.Walk, commuteWalkParam, false, commuteWalkUsage) + f.BoolVar(&c.Bike, commuteBikeParam, false, commuteBikeUsage) + f.BoolVar(&c.Transit, commuteTransitParam, false, commuteTransitUsage) f.Parse(args) + // Only default drive to true when no other methods of transport are selected. + if !c.Walk && !c.Bike && !c.Transit { + c.Drive = true + } + return &c, nil } diff --git a/cli/parser_test.go b/cli/parser_test.go index ba05925..7209c3c 100644 --- a/cli/parser_test.go +++ b/cli/parser_test.go @@ -118,6 +118,8 @@ func TestArgParser_parseCommuteCmd(t *testing.T) { } conf.APIKey = "example" + + // To/From and ToCurrent/FromCurrent tests := []struct { args []string expected cmd.CommuteCmd @@ -151,6 +153,41 @@ func TestArgParser_parseCommuteCmd(t *testing.T) { t.Fatalf("[%v] Unexpected nil Durationer", idx) } else if r.Locator == nil { t.Fatalf("[%v] Unexpected nil Locator", idx) + } else if r.Drive == false { + t.Fatalf("[%v] Unexpected Drive, expected=true, got=false", idx) + } else if r.Bike == true || r.Walk == true || r.Transit == true { + t.Fatalf("[%v] Unexpected Bike/Walk/Transit, expected=false, got=[%v, %v, %v]", idx, r.Bike, r.Walk, r.Transit) + } + } + + // Modes + mTests := []struct { + args []string + expected cmd.CommuteCmd + }{ + {[]string{""}, cmd.CommuteCmd{Drive: true}}, + {[]string{"-drive"}, cmd.CommuteCmd{Drive: true}}, + {[]string{"-walk"}, cmd.CommuteCmd{Walk: true}}, + {[]string{"-bike"}, cmd.CommuteCmd{Bike: true}}, + {[]string{"-transit"}, cmd.CommuteCmd{Transit: true}}, + {[]string{"-drive", "-walk"}, cmd.CommuteCmd{Drive: true, Walk: true}}, + {[]string{"-drive", "-walk", "-bike", "-transit"}, cmd.CommuteCmd{Drive: true, Walk: true, Bike: true, Transit: true}}, + } + + for idx, tt := range mTests { + r, err := a.parseCommuteCmd(&conf, tt.args) + if err != nil { + t.Fatal(err) + } + + if tt.expected.Drive != r.Drive { + t.Fatalf("[%v] Unexpected 'Drive' parsed, expected=%v, got=%v", idx, tt.expected.Drive, r.Drive) + } else if tt.expected.Walk != r.Walk { + t.Fatalf("[%v] Unexpected 'Walk' parsed, expected=%v, got=%v", idx, tt.expected.Walk, r.Walk) + } else if tt.expected.Bike != r.Bike { + t.Fatalf("[%v] Unexpected 'Bike' parsed, expected=%v, got=%v", idx, tt.expected.Bike, r.Bike) + } else if tt.expected.Transit != r.Transit { + t.Fatalf("[%v] Unexpected 'Transit' parsed, expected=%v, got=%v", idx, tt.expected.Transit, r.Transit) } } } diff --git a/cmd/cmd.go b/cmd/cmd.go index 89558ec..b400d93 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -3,6 +3,8 @@ package cmd import ( "time" + + "github.com/KyleBanks/commuter/pkg/geo" ) // Configuration represents a Commuter configuration, including @@ -64,7 +66,7 @@ type StorageProvider interface { // Durationer provides the ability to retrieve the duration between // two locations. type Durationer interface { - Duration(string, string) (*time.Duration, error) + Duration(string, string, geo.TravelMode) (*time.Duration, error) } // Locator provides the ability to retrieve the current location as diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index c014cf1..2b23dab 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -3,6 +3,8 @@ package cmd import ( "fmt" "time" + + "github.com/KyleBanks/commuter/pkg/geo" ) // mock Indicator @@ -18,11 +20,11 @@ func (m *mockIndicator) Indicate(msg string, args ...interface{}) { // mock Durationer type mockDurationer struct { - durationFn func(string, string) (*time.Duration, error) + durationFn func(string, string, geo.TravelMode) (*time.Duration, error) } -func (m *mockDurationer) Duration(from, to string) (*time.Duration, error) { - return m.durationFn(from, to) +func (m *mockDurationer) Duration(from, to string, tm geo.TravelMode) (*time.Duration, error) { + return m.durationFn(from, to, tm) } // mock StorageProvider diff --git a/cmd/commute.go b/cmd/commute.go index 02ce81f..afa0fde 100644 --- a/cmd/commute.go +++ b/cmd/commute.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" "time" + + "github.com/KyleBanks/commuter/pkg/geo" ) const ( @@ -18,6 +20,8 @@ var ( ErrDefaultFromMissing = errors.New("missing -from or -from-current parameter") // ErrDefaultToMissing is returned when running the default command and the -to argument is missing. ErrDefaultToMissing = errors.New("missing -to or -to-current parameter") + // ErrNoCommuteMethod is returned when no commute method is selected. + ErrNoCommuteMethod = errors.New("at least one commute method must be specified") // ErrFromAndFromCurrentProvided is returned when the -from and -from-current arguments are both supplied. ErrFromAndFromCurrentProvided = errors.New("cannot use -from and -from-current arguments") @@ -34,6 +38,11 @@ type CommuteCmd struct { To string ToCurrent bool + Drive bool + Walk bool + Bike bool + Transit bool + Durationer Durationer Locator Locator } @@ -41,85 +50,127 @@ type CommuteCmd struct { // Run calculates the distance between the From and To locations, // and outputs the result. func (c *CommuteCmd) Run(conf *Configuration, i Indicator) error { - d, err := c.Durationer.Duration(c.From, c.To) - if err != nil { - return err + modes := c.modes() + multiMode := len(modes) > 1 + + for _, m := range modes { + d, err := c.Durationer.Duration(c.From, c.To, m) + if err != nil { + return err + } + + var method string + if multiMode { + method = fmt.Sprintf("%v: ", m) + } + i.Indicate("%v%v", method, c.format(*d)) } - i.Indicate(c.format(*d)) return nil } // format takes a duration and returns a formatter representation. func (c *CommuteCmd) format(d time.Duration) string { + pluralize := func(s string, i int) string { + if i != 1 { + s += "s" + } + return s + } + var out []string hours := int(d.Hours()) minutes := int(d.Minutes()) if hours > 0 { minutes -= (hours * 60) + out = append(out, fmt.Sprintf("%v %v", hours, pluralize("Hour", hours))) + } - var suffix string - if hours != 1 { - suffix = "s" - } + out = append(out, fmt.Sprintf("%v %v", minutes, pluralize("Minute", minutes))) - out = append(out, fmt.Sprintf("%v Hour%v", hours, suffix)) - } + return strings.Join(out, " ") +} - var suffix string - if minutes != 1 { - suffix = "s" +// modes returns a slice of TravelModes based on the commands Drive, Walk, Bike and Transit properties. +func (c *CommuteCmd) modes() []geo.TravelMode { + var modes []geo.TravelMode + if c.Drive { + modes = append(modes, geo.Drive) + } + if c.Walk { + modes = append(modes, geo.Walk) + } + if c.Bike { + modes = append(modes, geo.Bike) + } + if c.Transit { + modes = append(modes, geo.Transit) } - out = append(out, fmt.Sprintf("%v Minute%v", minutes, suffix)) - return strings.Join(out, " ") + return modes } // Validate validates the CommuteCmd is properly initialized and ready to be Run. -// -// TODO: This is an ugly function, thing of a way of cleaning it up. -func (c *CommuteCmd) Validate(conf *Configuration) error { - if c.FromCurrent && len(c.From) > 0 && c.From != DefaultLocationAlias { - return ErrFromAndFromCurrentProvided +func (c *CommuteCmd) Validate(conf *Configuration) (err error) { + // Must provide at least one method of transport + if !c.Drive && !c.Walk && !c.Bike && !c.Transit { + return ErrNoCommuteMethod } - if c.ToCurrent && len(c.To) > 0 && c.To != DefaultLocationAlias { - return ErrToAndToCurrentProvided + + c.From, err = c.setLocation(conf, c.From, c.FromCurrent, ErrFromAndFromCurrentProvided, ErrDefaultFromMissing) + if err != nil { + return } - var err error - c.From, err = c.getLoc(c.FromCurrent, c.From, conf) + c.To, err = c.setLocation(conf, c.To, c.ToCurrent, ErrToAndToCurrentProvided, ErrDefaultToMissing) if err != nil { - return err + return + } + + return +} + +// setLocation validates and determines a location based on the provided value and the `useCurrent` flag. +// +// If the useCurrent flag is true, setLocation will attempt to use geolocation to determine the current location. Otherwise, +// it will check if the value is an alias, or use the actual value provided. +func (c *CommuteCmd) setLocation(conf *Configuration, value string, useCurrent bool, bothProvided error, missing error) (string, error) { + if useCurrent && len(value) > 0 && value != DefaultLocationAlias { + return "", bothProvided } - c.To, err = c.getLoc(c.ToCurrent, c.To, conf) + + var err error + if useCurrent { + value, err = c.locate(conf) + } else { + value = c.alias(conf, value) + } + if err != nil { - return err + return "", err } - if len(c.From) == 0 { - return ErrDefaultFromMissing - } else if len(c.To) == 0 { - return ErrDefaultToMissing + if len(value) == 0 { + return "", missing } - return nil + return value, nil } -// getLoc uses geolocation to populate a location if the current flag is true, otherwise -// it checks for a named location matching the input string. -// -// TODO: This is an ugly function, thing of a way of cleaning it up. -func (c *CommuteCmd) getLoc(current bool, input string, conf *Configuration) (string, error) { - if !current { - val, ok := conf.Locations[input] - if ok { - return val, nil - } - - return input, nil +// alias checks if the provided value is an alias to a location in the Configuration. +// If it is, the value of the alias is returned, otherwise the value provided is returned. +func (c *CommuteCmd) alias(conf *Configuration, value string) string { + val, ok := conf.Locations[value] + if !ok { + return value } + return val +} + +// locate attempts to return a latitude/longitude string for the user's current location. +func (c *CommuteCmd) locate(conf *Configuration) (string, error) { lat, long, err := c.Locator.CurrentLocation() if err != nil { return "", err diff --git a/cmd/commute_test.go b/cmd/commute_test.go index 4f54bed..2e66253 100644 --- a/cmd/commute_test.go +++ b/cmd/commute_test.go @@ -5,10 +5,12 @@ import ( "fmt" "testing" "time" + + "github.com/KyleBanks/commuter/pkg/geo" ) func TestCommuteCmd_Run(t *testing.T) { - // Positive + // Positive, To/From tests := []struct { from string to string @@ -22,7 +24,7 @@ func TestCommuteCmd_Run(t *testing.T) { for idx, tt := range tests { d := time.Minute * 3 m := mockDurationer{ - durationFn: func(from, to string) (*time.Duration, error) { + durationFn: func(from, to string, tm geo.TravelMode) (*time.Duration, error) { if from != tt.from { t.Fatalf("[#%v] Unexpected From, expected=%v, got=%v", idx, tt.from, from) } else if to != tt.to { @@ -33,7 +35,7 @@ func TestCommuteCmd_Run(t *testing.T) { }, } - c := CommuteCmd{From: tt.from, To: tt.to, Durationer: &m} + c := CommuteCmd{From: tt.from, To: tt.to, Drive: true, Durationer: &m} var conf Configuration var i mockIndicator if err := c.Run(&conf, &i); err != nil { @@ -47,16 +49,77 @@ func TestCommuteCmd_Run(t *testing.T) { } } + // Positive, Modes + mTests := []struct { + drive bool + walk bool + bike bool + transit bool + }{ + {true, false, false, false}, + {true, true, false, false}, + {false, true, false, false}, + {false, true, true, false}, + {false, false, true, false}, + {false, false, true, true}, + {false, true, true, true}, + {true, true, true, true}, + } + + for idx, tt := range mTests { + var expectCount int + if tt.drive { + expectCount++ + } + if tt.walk { + expectCount++ + } + if tt.bike { + expectCount++ + } + if tt.transit { + expectCount++ + } + + m := mockDurationer{ + durationFn: func(from, to string, tm geo.TravelMode) (*time.Duration, error) { + if tm == geo.Drive && !tt.drive { + t.Fatalf("[#%v] Unexpected Mode, Drive", idx) + } else if tm == geo.Walk && !tt.walk { + t.Fatalf("[#%v] Unexpected Mode, Walk", idx) + } else if tm == geo.Bike && !tt.bike { + t.Fatalf("[#%v] Unexpected Mode, Bike", idx) + } else if tm == geo.Transit && !tt.transit { + t.Fatalf("[#%v] Unexpected Mode, Transit", idx) + } + + d := time.Minute * 3 + return &d, nil + }, + } + + c := CommuteCmd{From: "default", To: "default", Drive: tt.drive, Walk: tt.walk, Bike: tt.bike, Transit: tt.transit, Durationer: &m} + var conf Configuration + var i mockIndicator + if err := c.Run(&conf, &i); err != nil { + t.Fatal(err) + } + + if len(i.out) != expectCount { + t.Fatalf("[#%v] Unexpected number of output lines, expected=%v, got=%v", idx, expectCount, i.out) + } + } + // Negative { testErr := errors.New("mock error") m := mockDurationer{ - durationFn: func(from, to string) (*time.Duration, error) { + durationFn: func(from, to string, tm geo.TravelMode) (*time.Duration, error) { return nil, testErr }, } - c := CommuteCmd{From: "from", To: "to", Durationer: &m} + c := CommuteCmd{From: "from", To: "to", Drive: true, Durationer: &m} var conf Configuration var i mockIndicator if err := c.Run(&conf, &i); err != testErr { @@ -90,6 +153,7 @@ func TestCommuteCmd_format(t *testing.T) { } func TestCommuteCmd_Validate(t *testing.T) { + // From/To tests := []struct { locs map[string]string from string @@ -114,7 +178,7 @@ func TestCommuteCmd_Validate(t *testing.T) { {map[string]string{}, "", false, "to", false, ErrDefaultFromMissing, "", ""}, {map[string]string{}, "from", false, "", false, ErrDefaultToMissing, "", ""}, {map[string]string{}, "from", true, "", false, ErrFromAndFromCurrentProvided, "", ""}, - {map[string]string{}, "", false, "to", true, ErrToAndToCurrentProvided, "", ""}, + {map[string]string{}, "from", false, "to", true, ErrToAndToCurrentProvided, "", ""}, {map[string]string{"from": ""}, "from", false, "to", false, ErrDefaultFromMissing, "", ""}, {map[string]string{"to": ""}, "from", false, "to", false, ErrDefaultToMissing, "", ""}, } @@ -137,7 +201,7 @@ func TestCommuteCmd_Validate(t *testing.T) { return float64(idx), float64(idx), nil }, } - c := CommuteCmd{From: tt.from, FromCurrent: tt.fromCurrent, To: tt.to, ToCurrent: tt.toCurrent, Locator: &m} + c := CommuteCmd{From: tt.from, FromCurrent: tt.fromCurrent, To: tt.to, ToCurrent: tt.toCurrent, Locator: &m, Drive: true} if err := c.Validate(&conf); err != tt.err { t.Fatalf("[#%v] Unexpected error, expected=%v, got=%v", idx, tt.err, err) @@ -153,4 +217,32 @@ func TestCommuteCmd_Validate(t *testing.T) { t.Fatalf("[#%v] Unexpected To, expected=%v, got=%v", idx, tt.expectTo, c.To) } } + + // Modes + cTests := []struct { + drive bool + walk bool + bike bool + transit bool + + err error + }{ + {true, false, false, false, nil}, + {true, true, false, false, nil}, + {true, true, true, false, nil}, + {true, true, true, true, nil}, + {false, true, true, true, nil}, + {false, false, true, true, nil}, + {false, false, false, true, nil}, + {false, false, false, false, ErrNoCommuteMethod}, + } + + for idx, tt := range cTests { + conf := Configuration{Locations: make(map[string]string)} + + c := CommuteCmd{From: "default", To: "default", Drive: tt.drive, Walk: tt.walk, Bike: tt.bike, Transit: tt.transit} + if err := c.Validate(&conf); err != tt.err { + t.Fatalf("[#%v] Unexpected error, expected=%v, got=%v", idx, tt.err, err) + } + } } diff --git a/main.go b/main.go index b914641..c8190c9 100644 --- a/main.go +++ b/main.go @@ -27,7 +27,7 @@ func main() { exec(out, conf, r) } -// exec validates executes a Runner with the Indicator and Configuration provided. +// exec validates and executes a Runner with the Indicator and Configuration provided. func exec(i cmd.Indicator, c *cmd.Configuration, r cmd.RunnerValidator) { if err := r.Validate(c); err != nil { i.Indicate("Invalid command: %v", r) diff --git a/pkg/geo/geo.go b/pkg/geo/geo.go index e77f434..eb276db 100644 --- a/pkg/geo/geo.go +++ b/pkg/geo/geo.go @@ -16,8 +16,7 @@ const ( statusOk = "OK" statusNotFound = "NOT_FOUND" - geolocationURL = "https://www.googleapis.com/geolocation/v1/geolocate?key=" - geolocationBody = `{"considerIp": "true"}` + geolocationURL = "https://www.googleapis.com/geolocation/v1/geolocate?key=" ) var ( @@ -28,8 +27,38 @@ var ( // ErrBadLocation is returned in cases where either the 'from' or 'to' address // could not be found. ErrBadLocation = errors.New("failed to find one of the provided locations") + + geolocationBody = bytes.NewBuffer([]byte(`{"considerIp": "true"}`)) + + defaultAvoid = maps.AvoidTolls ) +// TravelMode dictates the type of travel when determining the duration. +type TravelMode maps.Mode + +var ( + // Drive indicates a driving TravelMode. + Drive = TravelMode(maps.TravelModeDriving) + // Walk indicates a walking TravelMode. + Walk = TravelMode(maps.TravelModeWalking) + // Bike indicates a Biking TravelMode. + Bike = TravelMode(maps.TravelModeBicycling) + // Transit indicates public transit as a TravelMode. + Transit = TravelMode(maps.TravelModeTransit) + + travelModeStrings = map[TravelMode]string{ + Drive: "Drive", + Walk: "Walk", + Bike: "Bike", + Transit: "Transit", + } +) + +// String returns a user friendly string representation of a TravelMode. +func (t TravelMode) String() string { + return travelModeStrings[t] +} + // Router provides the ability to calculate travel duration between Routes. type Router struct { apiKey string @@ -52,10 +81,12 @@ func NewRouter(apiKey string) (*Router, error) { // Duration returns the time it will take to travel between // the From and To address. -func (r Router) Duration(from, to string) (*time.Duration, error) { +func (r Router) Duration(from, to string, tm TravelMode) (*time.Duration, error) { req := maps.DistanceMatrixRequest{ Origins: []string{from}, Destinations: []string{to}, + Mode: maps.Mode(tm), + Avoid: defaultAvoid, } res, err := r.client.DistanceMatrix(context.Background(), &req) @@ -80,7 +111,7 @@ func (r Router) Duration(from, to string) (*time.Duration, error) { // CurrentLocation attempts to use Geolocation to return the Lat/Long of the system device // based on it's IP Address. func (r Router) CurrentLocation() (float64, float64, error) { - resp, err := http.Post(geolocationURL+r.apiKey, "application/json", bytes.NewBuffer([]byte(geolocationBody))) + resp, err := http.Post(geolocationURL+r.apiKey, "application/json", geolocationBody) if err != nil { return 0, 0, err } diff --git a/pkg/geo/geo_test.go b/pkg/geo/geo_test.go index 7d36ac3..c4742e4 100644 --- a/pkg/geo/geo_test.go +++ b/pkg/geo/geo_test.go @@ -43,6 +43,7 @@ func TestRouter_Duration(t *testing.T) { from := "321 Main St" to := "123 Maple St" duration := time.Minute * 5 + mode := Drive mc.distanceFn = func(c context.Context, r *maps.DistanceMatrixRequest) (*maps.DistanceMatrixResponse, error) { if c == nil { t.Fatal("Unexpected nil Context") @@ -54,6 +55,12 @@ func TestRouter_Duration(t *testing.T) { if len(r.Destinations) != 1 || r.Destinations[0] != to { t.Fatalf("Unexpected Destinations, expected=%v, got=%v", to, r.Destinations) } + if r.Mode != maps.Mode(mode) { + t.Fatalf("Unexpected Mode, expected=%v, got=%v", mode, r.Mode) + } + if r.Avoid != defaultAvoid { + t.Fatalf("Unexpected Avoid, expected=%v, got=%v", defaultAvoid, r.Avoid) + } return &maps.DistanceMatrixResponse{ Rows: []maps.DistanceMatrixElementsRow{ @@ -69,7 +76,7 @@ func TestRouter_Duration(t *testing.T) { }, nil } - d, err := r.Duration(from, to) + d, err := r.Duration(from, to, mode) if err != nil { t.Fatal(err) } @@ -86,7 +93,7 @@ func TestRouter_Duration(t *testing.T) { return nil, e } - _, err := r.Duration("", "") + _, err := r.Duration("", "", Drive) if err != e { t.Fatalf("Unexpected error returned, expected=%v, got=%v", e, err) } @@ -108,7 +115,7 @@ func TestRouter_Duration(t *testing.T) { }, nil } - _, err := r.Duration("", "") + _, err := r.Duration("", "", Drive) if err != ErrBadLocation { t.Fatalf("Unexpected error returned, expected=%v, got=%v", ErrBadLocation, err) } @@ -120,7 +127,7 @@ func TestRouter_Duration(t *testing.T) { return &maps.DistanceMatrixResponse{}, nil } - _, err := r.Duration("", "") + _, err := r.Duration("", "", Drive) if err != ErrUnavailable { t.Fatalf("Unexpected error returned, expected=%v, got=%v", ErrUnavailable, err) } diff --git a/test.json b/test.json deleted file mode 100644 index e6d2756..0000000 --- a/test.json +++ /dev/null @@ -1 +0,0 @@ -{"considerIp": "true"}