package handler import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" ) func TestHealthHandler(t *testing.T) { h := NewHealthHandler() req := httptest.NewRequest("GET", "/health", nil) rr := httptest.NewRecorder() h.Health(rr, req) if rr.Code != http.StatusOK { t.Errorf("expected 200, got %d", rr.Code) } var resp map[string]string json.NewDecoder(rr.Body).Decode(&resp) if resp["status"] != "ok" { t.Errorf("expected status ok, got %s", resp["status"]) } if resp["service"] != "homelab-api" { t.Errorf("expected service homelab-api, got %s", resp["service"]) } } func TestWriteJSON(t *testing.T) { rr := httptest.NewRecorder() data := map[string]string{"hello": "world"} writeJSON(rr, data, http.StatusCreated) if rr.Code != http.StatusCreated { t.Errorf("expected 201, got %d", rr.Code) } if ct := rr.Header().Get("Content-Type"); ct != "application/json" { t.Errorf("expected application/json, got %s", ct) } var resp map[string]string json.NewDecoder(rr.Body).Decode(&resp) if resp["hello"] != "world" { t.Errorf("expected world, got %s", resp["hello"]) } } func TestWriteError(t *testing.T) { rr := httptest.NewRecorder() writeError(rr, "something went wrong", http.StatusBadRequest) if rr.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d", rr.Code) } var resp map[string]string json.NewDecoder(rr.Body).Decode(&resp) if resp["error"] != "something went wrong" { t.Errorf("expected 'something went wrong', got %s", resp["error"]) } } func TestInterestHandler_Unauthorized(t *testing.T) { h := &InterestHandler{secretKey: "my-secret"} t.Run("missing key", func(t *testing.T) { req := httptest.NewRequest("POST", "/internal/calculate-interest", nil) rr := httptest.NewRecorder() h.CalculateInterest(rr, req) if rr.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", rr.Code) } }) t.Run("wrong key", func(t *testing.T) { req := httptest.NewRequest("POST", "/internal/calculate-interest", nil) req.Header.Set("X-Internal-Key", "wrong-key") rr := httptest.NewRecorder() h.CalculateInterest(rr, req) if rr.Code != http.StatusUnauthorized { t.Errorf("expected 401, got %d", rr.Code) } }) } // Test request validation (without real service, just checking decoding) func TestDecodeInvalidJSON(t *testing.T) { tests := []struct { name string body string handler http.HandlerFunc }{ {"invalid json", "{bad", func(w http.ResponseWriter, r *http.Request) { var req struct{ Email string } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, "invalid request body", http.StatusBadRequest) return } }}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { req := httptest.NewRequest("POST", "/test", bytes.NewBufferString(tt.body)) rr := httptest.NewRecorder() tt.handler(rr, req) if rr.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d", rr.Code) } }) } }