updates on the api endpoints on the customer page and more
This commit is contained in:
117
internal/legs/legs_test.go
Normal file
117
internal/legs/legs_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package legs
|
||||
|
||||
import "testing"
|
||||
|
||||
// The one definition of "does this parcel go via a base?".
|
||||
//
|
||||
// It lives in its own package because two callers need it and neither can
|
||||
// import the other: controllers decides it at pickup-complete, internal/routing
|
||||
// needs it to know where a rider's leg ends. A second copy in routing was the
|
||||
// alternative, and this codebase has been bitten by that shape before — a rival
|
||||
// status table that drifted until the map and the list showed the same parcel
|
||||
// two different colours.
|
||||
//
|
||||
// So the rule is tested here, once, and both callers inherit it.
|
||||
|
||||
func TestSamePostalArea(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
pickup string
|
||||
delivery string
|
||||
want bool
|
||||
}{
|
||||
{"same 3-digit area is one zone", "641012", "641004", true},
|
||||
{"an identical pincode is trivially one zone", "641012", "641012", true},
|
||||
{"Coimbatore to Chennai is not", "641012", "600001", false},
|
||||
{"Coimbatore to Pollachi is not, though it is close", "641012", "642001", false},
|
||||
{"a short pincode proves nothing", "64", "641004", false},
|
||||
{"an empty pincode proves nothing", "", "641004", false},
|
||||
{"two empty pincodes do not match each other", "", "", false},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if got := SamePostalArea(tc.pickup, tc.delivery); got != tc.want {
|
||||
t.Errorf("SamePostalArea(%q, %q) = %v, want %v", tc.pickup, tc.delivery, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsHyperlocalPrefersThePincodeRule(t *testing.T) {
|
||||
// Coimbatore pickup, Pollachi delivery: ~40 km apart, which is inside the
|
||||
// distance fallback — but they are different postal areas, and when both
|
||||
// pincodes are present the prefix rule decides outright. Distance does not
|
||||
// get a vote, or a parcel would be routed one way on Tuesday and another on
|
||||
// Wednesday because a geocoder moved a pin.
|
||||
if IsHyperlocal("641025", "642001", 11.0168, 76.9558, 10.658, 77.008) {
|
||||
t.Error("a different postal area must route via a base even when it is close")
|
||||
}
|
||||
|
||||
// The mirror: same area, far apart. A 3-digit area can be large, and the
|
||||
// prefix still decides.
|
||||
if !IsHyperlocal("641025", "641999", 11.0168, 76.9558, 11.6, 77.5) {
|
||||
t.Error("the same postal area must stay hyperlocal even when it is a long way across")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsHyperlocalFallsBackToDistance(t *testing.T) {
|
||||
// Console-created bookings frequently carry accurate coordinates and no
|
||||
// delivery pincode. Routing those through a base because of a missing field
|
||||
// would send a kitchen-to-doorstep lunch order on a tour of the network.
|
||||
if !IsHyperlocal("641025", "", 11.0168, 76.9558, 11.05, 77.01) {
|
||||
t.Error("a short hop with no pincode should stay hyperlocal on the distance fallback")
|
||||
}
|
||||
if IsHyperlocal("641025", "", 11.0168, 76.9558, 13.0827, 80.2707) {
|
||||
t.Error("a 430km haul with no pincode is not hyperlocal whatever the fallback")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsHyperlocalIsFalseWhenNothingCanBeProven(t *testing.T) {
|
||||
// No usable pincodes and no usable coordinates. False routes via a base,
|
||||
// which is the safe direction to be wrong in: a parcel that reaches a base
|
||||
// can still be forwarded, while one handed to a rider who cannot reach the
|
||||
// receiver is simply stuck.
|
||||
if IsHyperlocal("", "", 0, 0, 0, 0) {
|
||||
t.Error("with nothing to decide on, the answer must be the safe one")
|
||||
}
|
||||
if IsHyperlocal("64", "60", 0, 0, 0, 0) {
|
||||
t.Error("unusable pincodes and no coordinates must not resolve to hyperlocal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsHyperlocalTreatsAMissingCoordinateAsMissing(t *testing.T) {
|
||||
// 0,0 is in the Gulf of Guinea. Treating it as a real position would make
|
||||
// every un-geocoded booking look like a 7,000 km haul — or, worse, let two
|
||||
// of them look like neighbours.
|
||||
if IsHyperlocal("641025", "", 11.0168, 76.9558, 0, 0) {
|
||||
t.Error("a 0,0 delivery point is an unset value, not a location near anything")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHaversineKM(t *testing.T) {
|
||||
// A known pair: Coimbatore to Chennai is roughly 430 km great-circle.
|
||||
km := HaversineKM(11.0168, 76.9558, 13.0827, 80.2707)
|
||||
if km < 400 || km > 460 {
|
||||
t.Errorf("Coimbatore→Chennai = %.0f km, expected roughly 430", km)
|
||||
}
|
||||
|
||||
if d := HaversineKM(11.0168, 76.9558, 11.0168, 76.9558); d != 0 {
|
||||
t.Errorf("a point is %v km from itself, want 0", d)
|
||||
}
|
||||
|
||||
// Symmetric, or distance-based decisions would depend on argument order.
|
||||
a := HaversineKM(11.0168, 76.9558, 12.9716, 77.5946)
|
||||
b := HaversineKM(12.9716, 77.5946, 11.0168, 76.9558)
|
||||
if a != b {
|
||||
t.Errorf("distance is not symmetric: %v vs %v", a, b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxHyperlocalKMBoundary(t *testing.T) {
|
||||
// The fallback threshold is a real operational number, not a magic
|
||||
// constant — a rider is expected to carry a parcel this far, and not
|
||||
// further. Guarding it stops a silent widening.
|
||||
if MaxHyperlocalKM != 30.0 {
|
||||
t.Errorf("MaxHyperlocalKM = %v; changing it changes which parcels riders carry end to end", MaxHyperlocalKM)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user