package adapter import ( "encoding/json" "io" "net/http" "net/http/httptest" "strings" "testing" "aiaa-notification-service/internal/config" ) func TestNewSenderSafew(t *testing.T) { s, err := NewSender("safew", &config.SMTPConfig{}, nil) if err != nil { t.Fatalf("NewSender(safew): %v", err) } if s.Type() != "safew" { t.Fatalf("Type() = %q, want safew", s.Type()) } } func TestSafeWSenderSendSuccess(t *testing.T) { var gotPath string var gotBody map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { gotPath = r.URL.Path raw, _ := io.ReadAll(r.Body) if err := json.Unmarshal(raw, &gotBody); err != nil { t.Errorf("unmarshal request: %v", err) } w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"ok":true,"result":{}}`)) })) defer srv.Close() sender := &SafeWSender{apiBase: srv.URL} cfg, _ := json.Marshal(map[string]any{"token": "tok-1", "chat_id": "123456789"}) if err := sender.Send("hello_world.", "price=1.5", cfg); err != nil { t.Fatalf("Send: %v", err) } if gotPath != "/bottok-1/sendMessage" { t.Fatalf("path = %q, want /bottok-1/sendMessage", gotPath) } if gotBody["chat_id"] != "123456789" { t.Fatalf("chat_id = %#v, want \"123456789\"", gotBody["chat_id"]) } if gotBody["parse_mode"] != nil && gotBody["parse_mode"] != "" { t.Fatalf("parse_mode = %#v, want omitted/plain", gotBody["parse_mode"]) } wantText := "price=1.5" if gotBody["text"] != wantText { t.Fatalf("text = %#v, want %#v", gotBody["text"], wantText) } } func TestSafeWSenderSendNumericChatID(t *testing.T) { var gotBody map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { raw, _ := io.ReadAll(r.Body) _ = json.Unmarshal(raw, &gotBody) w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"ok":true}`)) })) defer srv.Close() sender := &SafeWSender{apiBase: srv.URL} cfg := json.RawMessage(`{"token":"tok","chat_id":123456789}`) if err := sender.Send("t", "c", cfg); err != nil { t.Fatalf("Send: %v", err) } if gotBody["chat_id"] != "123456789" { t.Fatalf("chat_id = %#v, want string \"123456789\"", gotBody["chat_id"]) } } func TestSafeWSenderSendOKFalse(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"ok":false,"description":"chat not found"}`)) })) defer srv.Close() sender := &SafeWSender{apiBase: srv.URL} cfg, _ := json.Marshal(map[string]string{"token": "tok", "chat_id": "1"}) err := sender.Send("t", "c", cfg) if err == nil { t.Fatal("expected error") } if !strings.Contains(err.Error(), "chat not found") { t.Fatalf("error %q should contain description", err) } } func TestSafeWSenderSendHTTPError(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) _, _ = w.Write([]byte(`{"ok":false,"description":"Unauthorized"}`)) })) defer srv.Close() sender := &SafeWSender{apiBase: srv.URL} cfg, _ := json.Marshal(map[string]string{"token": "bad", "chat_id": "1"}) err := sender.Send("t", "c", cfg) if err == nil { t.Fatal("expected error") } if !strings.Contains(err.Error(), "Unauthorized") { t.Fatalf("error %q should contain description", err) } } func TestSafeWSenderSendMissingFields(t *testing.T) { hits := 0 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { hits++ w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"ok":true}`)) })) defer srv.Close() sender := &SafeWSender{apiBase: srv.URL} cases := []json.RawMessage{ json.RawMessage(`{"chat_id":"1"}`), json.RawMessage(`{"token":"tok"}`), json.RawMessage(`{"token":" ","chat_id":"1"}`), json.RawMessage(`{"token":"tok","chat_id":""}`), json.RawMessage(`{"token":"tok","chat_id":null}`), } for _, cfg := range cases { if err := sender.Send("t", "c", cfg); err == nil { t.Fatalf("expected error for config %s", cfg) } } if hits != 0 { t.Fatalf("unexpected HTTP calls: %d", hits) } if err := sender.Send("t", "c", json.RawMessage(`{`)); err == nil { t.Fatal("expected error for invalid json") } if hits != 0 { t.Fatalf("unexpected HTTP calls after invalid json: %d", hits) } }