package calls import ( "strings" "testing" "time" ) // TestCallTitle is the review follow-up for "Start a call": // callstest's black-box test only ever checked the title for a // "Call, " prefix, so this pins the exact format over a fixed time // and a few zones, including one that rolls the date over. func TestCallTitle(t *testing.T) { dublin, err := time.LoadLocation("Europe/Dublin") if err != nil { t.Fatal(err) } tokyo, err := time.LoadLocation("Asia/Tokyo") if err != nil { t.Fatal(err) } cases := []struct { name string now time.Time zone *time.Location want string wantZone string }{ { // Not "Call, 30 Sep 20:47 UTC" (f86d4da until 2026-10-02): // the zone is data, not words. name: "no browser zone: the instance zone, kept but not in the title", now: time.Date(2026, 9, 30, 20, 47, 0, 0, time.UTC), zone: nil, want: "Call, 30 Sep 20:47", wantZone: "UTC", }, { name: "UTC", now: time.Date(2026, 9, 10, 9, 5, 0, 0, time.UTC), zone: time.UTC, want: "Call, 10 Sep 09:05", }, { name: "single-digit day is not zero-padded", now: time.Date(2026, 9, 3, 9, 5, 0, 0, time.UTC), zone: time.UTC, want: "Call, 3 Sep 09:05", }, { name: "a zone ahead of UTC, same day", now: time.Date(2026, 9, 10, 9, 15, 0, 0, time.UTC), zone: dublin, // Irish summer time is UTC+1 in September want: "Call, 10 Sep 10:15", wantZone: "Europe/Dublin", }, { name: "a zone far enough ahead to roll the date over", now: time.Date(2026, 9, 10, 23, 30, 0, 0, time.UTC), zone: tokyo, // UTC+9, no DST want: "Call, 11 Sep 08:30", }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { got := callTitle(c.now, c.zone, time.UTC) if got.Text != c.want { t.Errorf("callTitle(%s, %s) = %q, want %q", c.now, c.zone, got.Text, c.want) } if c.wantZone != "" && got.Zone != c.wantZone { t.Errorf("callTitle(%s, %s) zone = %q, want %q", c.now, c.zone, got.Zone, c.wantZone) } }) } } // TestCallZone: the browser's zone is used only when it is a real IANA // zone; anything else falls back to the instance zone (and its name). func TestCallZone(t *testing.T) { if callZone("Europe/Dublin") == nil { t.Error("a real zone was refused") } for _, bad := range []string{"", "Local", "Mars/Olympus", "../../etc/passwd", "Europe/Dublin\n"} { if callZone(bad) != nil { t.Errorf("callZone(%q) accepted", bad) } } } // TestCallTitleNeverNamesItsZone: whatever zone the title is written in, // the title is the day and time and nothing after them — the reported // "Call, 2 Oct 15:40 Europe/Dublin" — and the zone is returned beside it. func TestCallTitleNeverNamesItsZone(t *testing.T) { dublin, _ := time.LoadLocation("Europe/Dublin") now := time.Date(2026, 10, 2, 14, 40, 0, 0, time.UTC) for _, local := range []*time.Location{nil, dublin, time.UTC} { got := callTitle(now, local, dublin) if got.Text != "Call, 2 Oct 15:40" && local != time.UTC { t.Errorf("callTitle in %v = %q", local, got.Text) } if strings.Contains(got.Text, "/") || strings.HasSuffix(got.Text, "UTC") { t.Errorf("callTitle in %v names its zone: %q", local, got.Text) } if got.Zone == "" { t.Errorf("callTitle in %v kept no zone", local) } } } // TestAutoTitleIsAFlagNotAReading: a meeting started with no title is // marked when it is made, and a meeting someone titled is not — even // one whose title reads exactly like an automatic one, which is why // this is a flag and not a pattern match on the words. func TestAutoTitleIsAFlagNotAReading(t *testing.T) { s, _ := testStore(t) ctx := t.Context() auto, _, err := s.createCall(ctx, autoTitle{Text: "Call, 2 Oct 15:40", Zone: "Europe/Dublin"}, "person:1") if err != nil { t.Fatal(err) } named, _, err := s.createMeeting(ctx, "Call, 2 Oct 15:40", nil, "person:1") if err != nil { t.Fatal(err) } for _, c := range []struct { m Meeting auto bool zone string }{{auto, true, "Europe/Dublin"}, {named, false, ""}} { got, ok, err := s.meetingBySqid(ctx, c.m.Sqid) if err != nil || !ok { t.Fatalf("read back %s: %v %v", c.m.Sqid, ok, err) } if got.AutoTitle != c.auto || got.TitleZone != c.zone { t.Errorf("meeting %s: auto %v zone %q, want %v %q", c.m.Sqid, got.AutoTitle, got.TitleZone, c.auto, c.zone) } if s.title(got) != "Call, 2 Oct 15:40" { t.Errorf("title read back as %q", s.title(got)) } } }