Files
backend_fiesta/utils/geo_test.go
2026-09-16 12:17:39 +05:30

131 lines
3.8 KiB
Go

package utils
import (
"testing"
"time"
)
func TestParseLatLng(t *testing.T) {
if _, _, ok := ParseLatLng("", ""); ok {
t.Error("blank must not parse")
}
if _, _, ok := ParseLatLng("0", "0"); ok {
t.Error("0,0 is an empty map picker, not a place")
}
if _, _, ok := ParseLatLng("91", "10"); ok {
t.Error("out of range")
}
lat, lng, ok := ParseLatLng(" 11.0168 ", "76.9558")
if !ok || lat != 11.0168 || lng != 76.9558 {
t.Errorf("got %v %v %v", lat, lng, ok)
}
}
func TestHaversineKm(t *testing.T) {
// Coimbatore railway station to Peelamedu, roughly 8 km.
d := HaversineKm(11.0018, 76.9660, 11.0290, 77.0290)
if d < 7 || d > 9 {
t.Errorf("got %.2f km", d)
}
if HaversineKm(1, 1, 1, 1) != 0 {
t.Error("same point")
}
}
func TestOpenNow(t *testing.T) {
at := func(h, m int) time.Time { return time.Date(2026, 9, 15, h, m, 0, 0, time.UTC) }
if !OpenNow("09:00", "21:00", at(12, 0)) || OpenNow("09:00", "21:00", at(22, 0)) {
t.Error("plain hours")
}
if !OpenNow("20:00", "02:00", at(1, 0)) || OpenNow("20:00", "02:00", at(12, 0)) {
t.Error("past midnight")
}
if !OpenNow("9:00 AM", "9:30 PM", at(21, 0)) || OpenNow("9:00 AM", "9:30 PM", at(21, 45)) {
t.Error("12-hour clock")
}
if !OpenNow("", "", at(3, 0)) || !OpenNow("always", "", at(3, 0)) {
t.Error("unknown hours mean open")
}
}
func TestSearchTokens(t *testing.T) {
got := SearchTokens("Milk Bikis 100g, Britannia (2 x 50gm)")
want := []string{"milk", "bikis", "britannia"}
if len(got) != len(want) {
t.Fatalf("got %v want %v", got, want)
}
for i := range want {
if got[i] != want[i] {
t.Fatalf("got %v want %v", got, want)
}
}
if len(SearchTokens("500ml 1kg 2")) != 0 {
t.Error("pack sizes alone are not searchable")
}
}
// A single letter is often the whole product name in this catalogue, so it
// survives when it follows a word — but not when it stands alone, and not
// when it is the multiplier in a pack size.
func TestSearchTokensKeepsALetterThatFollowsAWord(t *testing.T) {
for _, tc := range []struct {
label string
want []string
}{
{"Parle G", []string{"parle", "g"}},
{"Parle-G", []string{"parle", "g"}},
{"Special K Original", []string{"special", "k", "original"}},
{"G", nil}, // a letter alone is not a search
{"2 x 50gm", nil}, // multiplier and pack size, no words
{"Milk Bikis 100g, Britannia (2 x 50gm)", []string{"milk", "bikis", "britannia"}},
} {
got := SearchTokens(tc.label)
if len(got) != len(tc.want) {
t.Fatalf("%q: got %v want %v", tc.label, got, tc.want)
}
for i := range tc.want {
if got[i] != tc.want[i] {
t.Fatalf("%q: got %v want %v", tc.label, got, tc.want)
}
}
}
}
func TestFoldAndTightenSeparators(t *testing.T) {
if got := FoldSeparators("Parle-G Original"); got != "parle g original" {
t.Fatalf("fold: got %q", got)
}
if FoldSeparators("Parle-G") != FoldSeparators("Parle G") {
t.Error("a hyphen and a space are the same separator to us")
}
if got := TightenLabel("Parle-G"); got != "parleg" {
t.Fatalf("tighten: got %q", got)
}
}
// Lens reads the wrapper as well as the product. No catalogue name carries
// "bottle" or "pack", so requiring them found no Dettol at all.
func TestSearchTokensDropsPackagingWords(t *testing.T) {
for _, tc := range []struct {
label string
want []string
}{
{"Dettol bottle pack", []string{"dettol"}},
{"Parle G biscuit pack", []string{"parle", "g", "biscuit"}},
{"Milk Bikis pack", []string{"milk", "bikis"}},
{"Nescafe jar 50g", []string{"nescafe"}},
{"pack", []string{"pack"}}, // nothing else: the wrapper is the search
{"combo pack", []string{"combo", "pack"}}, // ditto, both kept
} {
got := SearchTokens(tc.label)
if len(got) != len(tc.want) {
t.Fatalf("%q: got %v want %v", tc.label, got, tc.want)
}
for i := range tc.want {
if got[i] != tc.want[i] {
t.Fatalf("%q: got %v want %v", tc.label, got, tc.want)
}
}
}
}