package server import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "time" "vocat/internal/store" ) func TestSMSThreadAllDevicesUsesIMSIFilter(t *testing.T) { ctx := context.Background() database, err := store.Open(ctx, ":memory:") if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = database.Close() }) for index, imsi := range []string{"imsi-a", "imsi-b"} { if _, err := database.SaveSMSMessage(ctx, store.SMSMessage{ MessageID: "message-" + imsi, DeviceID: "ec20", IMSI: imsi, Peer: "VOXI", Direction: "inbound", Body: imsi, Timestamp: time.Unix(1_700_000_000+int64(index), 0), }); err != nil { t.Fatal(err) } } server := &Server{store: database} request := httptest.NewRequest( http.MethodGet, "/api/sms/thread?device_id=all&imsi=imsi-a&peer=VOXI", nil, ) response := httptest.NewRecorder() server.handleSMSThread(response, request) if response.Code != http.StatusOK { t.Fatalf("status = %d, body = %s", response.Code, response.Body.String()) } var envelope struct { Data []map[string]any `json:"data"` } if err := json.Unmarshal(response.Body.Bytes(), &envelope); err != nil { t.Fatal(err) } if len(envelope.Data) != 1 || envelope.Data[0]["imsi"] != "imsi-a" { t.Fatalf("thread data = %#v", envelope.Data) } } func TestNormalizeSMSDeviceFilter(t *testing.T) { if got := normalizeSMSDeviceFilter(" ALL "); got != "" { t.Fatalf("all filter = %q", got) } if got := normalizeSMSDeviceFilter("EC20"); got != "EC20" { t.Fatalf("device filter = %q", got) } } func TestSMSSendOutcome(t *testing.T) { tests := []struct { name string all bool accepted int total int delivered bool want string }{ {name: "delivered", all: true, accepted: 1, total: 1, delivered: true, want: "delivered"}, {name: "accepted but unconfirmed", all: true, accepted: 2, total: 2, want: "accepted_unconfirmed"}, {name: "partial", accepted: 1, total: 2, want: "partial"}, {name: "failed", total: 1, want: "failed"}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { if got := smsSendOutcome(test.all, test.accepted, test.total, test.delivered); got != test.want { t.Fatalf("smsSendOutcome() = %q, want %q", got, test.want) } }) } } func TestBlockedSMSDestination(t *testing.T) { tests := []struct { name string phone string block bool }{ {"e164 china", "+8613800138000", true}, {"no plus china", "8613800138000", true}, {"international prefix china", "008613800138000", true}, {"spaced china", "+86 138 0013 8000", true}, {"dashed china", "+86-138-0013-8000", true}, {"us e164", "+12025550177", false}, {"us no plus", "12025550177", false}, {"uk e164", "+447700900123", false}, {"italy", "+393331234567", false}, {"russia", "+79161234567", false}, {"japan", "+819012345678", false}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { blocked, _ := blockedSMSDestination(test.phone) if blocked != test.block { t.Fatalf("blockedSMSDestination(%q) blocked = %v, want %v", test.phone, blocked, test.block) } }) } }