package products import ( "encoding/json" "fmt" "testing" "time" "git.t5de.dev/t5de/t5de-proxy/internal/hub" ) func TestRecentlyAdded(t *testing.T) { h, _ := newHarness(t) hubDir := t.TempDir() for _, id := range []string{"coatcoat22", "sofasofa22", "oldoldold2", "hairhair22"} { writePack(t, hubDir, id, 1) } h.p.dirs = append(h.p.dirs, hubDir) h.p.HubDir = hubDir h.p.Owned = func(string) bool { return true } h.p.refresh(true) now := time.Now() clothes := []hub.Category{{ID: 106}, {ID: 40}, {ID: 716}} h.p.Library = func() []hub.LibraryEntry { return []hub.LibraryEntry{ {Product: hub.Product{ID: "coatcoat22", Categories: clothes}, AddedAt: now.Add(-2 * time.Hour)}, {Product: hub.Product{ID: "sofasofa22", Categories: []hub.Category{{ID: 1027}, {ID: 1056}}}, AddedAt: now.Add(-time.Hour)}, {Product: hub.Product{ID: "oldoldold2", Categories: clothes}, AddedAt: now.Add(-40 * 24 * time.Hour)}, {Product: hub.Product{ID: "hairhair22"}, AddedAt: now.Add(-time.Hour)}, // no categories known: worn } } local := func(id string) int64 { return h.p.byProductID(id).local } get := func(kind string) []int64 { _, b := h.do("GET", "http://client-dynamic.imvu.com/api/recently_added_inventory.php?type="+kind, nil, false, false) var ids []int64 if json.Unmarshal(b, &ids) != nil { t.Fatalf("%s: %s", kind, b) } return ids } if got, want := fmt.Sprint(get("clothing")), fmt.Sprint([]int64{local("hairhair22"), local("coatcoat22"), 31162856, 108363}); got != want { t.Errorf("clothing %s, want %s", got, want) } if got, want := fmt.Sprint(get("furni")), fmt.Sprint([]int64{local("sofasofa22"), 31162856, 108363}); got != want { t.Errorf("furni %s, want %s", got, want) } if got, want := fmt.Sprint(get("scenes")), fmt.Sprint([]int64{31162856, 108363}); got != want { t.Errorf("scenes %s, want %s", got, want) } } func TestShopSorting(t *testing.T) { day := func(n int) time.Time { return time.Date(2026, 10, n, 0, 0, 0, 0, time.UTC) } list := func() []hub.Product { return []hub.Product{ {ID: "a", Name: "Long Red Coat", CreatedAt: day(5)}, {ID: "b", Name: "Coat", CreatedAt: day(1)}, {ID: "c", Name: "Coats & Jackets Pack", CreatedAt: day(2)}, {ID: "d", Name: "Raincoat", CreatedAt: day(4)}, {ID: "e", Name: "Hat", Creator: "coat_maker", CreatedAt: day(3)}, } } order := func(l []hub.Product) string { s := "" for _, p := range l { s += p.ID } return s } for _, c := range []struct{ query, field, dir, want string }{ {"coat", "conversion_score_b", "desc", "bcade"}, // same name, starts with, word, inside a word, creator {"", "conversion_score_b", "desc", "adecb"}, // no search: newest {"coat", "id", "desc", "adecb"}, // Newest Products {"coat", "id", "asc", "bceda"}, {"coat", "price", "asc", "adecb"}, // all free: newest {"coat", "user_rating", "desc", "adecb"}, } { l := list() sortShop(l, c.query, c.field, c.dir) if got := order(l); got != c.want { t.Errorf("%q %s %s: %s, want %s", c.query, c.field, c.dir, got, c.want) } } }