package models import ( "strings" "testing" "time" ) func at(day string) time.Time { parsed, err := time.Parse("2006-01-02", day) if err != nil { panic(err) } return parsed } func TestOpenByDefault(t *testing.T) { // Every branch trading today has isopen true and no date. None of them may // go dark the moment this ships. if !StoreIsOpen("Active", true, "", at("2026-10-09")) { t.Error("a normal trading branch was reported closed") } } func TestClosedWithNoDateStaysClosed(t *testing.T) { // A power cut nobody can put an end to. It stays shut until a person says // otherwise — the safe way round, because a shop wrongly shown open takes // orders it cannot fill. if StoreIsOpen("Active", false, "", at("2026-10-09")) { t.Error("a branch closed with no reopen date was reported open") } } func TestReopensOnTheDateItNamed(t *testing.T) { // "Closed until the 12th" means open ON the 12th. cases := []struct { today string want bool }{ {"2026-10-10", false}, // still closed {"2026-10-11", false}, // last closed day {"2026-10-12", true}, // back {"2026-10-13", true}, // and stays back } for _, tc := range cases { got := StoreIsOpen("Active", false, "2026-10-12", at(tc.today)) if got != tc.want { t.Errorf("on %s: open=%v, want %v", tc.today, got, tc.want) } } } func TestReopeningNeedsNobodyToRemember(t *testing.T) { // The whole reason this is computed and not scheduled: no job ran, nothing // flipped the flag, and the shop is open anyway. if !StoreIsOpen("Active", false, "2026-10-01", at("2026-12-25")) { t.Error("a branch whose reopen date passed months ago is still shut") } } func TestDecommissionedBeatsEverything(t *testing.T) { // Status is Nearle's word for whether the branch exists. A date passing // must not bring back a branch that was switched off. if StoreIsOpen("Inactive", true, "", at("2026-10-09")) { t.Error("an inactive branch was reported open") } if StoreIsOpen("Inactive", false, "2026-10-01", at("2026-12-25")) { t.Error("an inactive branch came back because a date passed") } } func TestUnreadableDateIsNotTreatedAsToday(t *testing.T) { // A zero time would be before today and quietly reopen the shop. if StoreIsOpen("Active", false, "not a date", at("2026-10-09")) { t.Error("an unreadable reopen date reopened the branch") } } func TestAcceptsATimestampAsWellAsADate(t *testing.T) { // The column is a DATE, but GORM and the console have both been known to // hand over a full timestamp. if !StoreIsOpen("Active", false, "2026-10-12T00:00:00Z", at("2026-10-12")) { t.Error("a timestamp form of the reopen date was not understood") } } func TestReasonIsWrittenForAShopper(t *testing.T) { if msg := StoreClosedReason("Active", true, "", at("2026-10-09")); msg != "" { t.Errorf("an open store gave a reason: %q", msg) } msg := StoreClosedReason("Active", false, "2026-10-12", at("2026-10-09")) if !strings.Contains(msg, "12 Oct") { t.Errorf("the reason does not say when it reopens: %q", msg) } // No date: say it is closed, and do not invent a return. plain := StoreClosedReason("Active", false, "", at("2026-10-09")) if plain == "" || strings.Contains(plain, "reopens") { t.Errorf("a close with no date promised a return: %q", plain) } } func TestStatusIsNotCaseSensitive(t *testing.T) { // The column holds "Active" today, but nothing enforces the capital. for _, s := range []string{"Active", "active", "ACTIVE", " Active "} { if !StoreIsOpen(s, true, "", at("2026-10-09")) { t.Errorf("status %q read as not active", s) } } }