package api import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "time" "github.com/michaeldileo/SafelyYouCodingChallenge/internal/store" ) func TestPostHeartbeat_UnknownDevice_404(t *testing.T) { s := store.New([]store.DeviceID{"known"}) srv := NewServer(s) req := httptest.NewRequest(http.MethodPost, "/api/v1/devices/missing/heartbeat", strings.NewReader(`{"sent_at":"2024-01-01T12:00:00Z"}`)) rec := httptest.NewRecorder() srv.Handler().ServeHTTP(rec, req) if rec.Code != http.StatusNotFound { t.Fatalf("status = %d, want 404", rec.Code) } var body msgResponse if err := json.NewDecoder(rec.Body).Decode(&body); err != nil { t.Fatalf("decode: %v", err) } if body.Msg == "" { t.Fatal("expected non-empty msg") } } func TestPostAndGetStats_RoundTrip(t *testing.T) { id := store.DeviceID("device-1") s := store.New([]store.DeviceID{id}) srv := NewServer(s) h := srv.Handler() t0 := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC) // two heartbeats one minute apart → uptime 200 postJSON(t, h, http.MethodPost, "/api/v1/devices/device-1/heartbeat", `{"sent_at":"`+t0.Format(time.RFC3339)+`"}`, http.StatusNoContent) postJSON(t, h, http.MethodPost, "/api/v1/devices/device-1/heartbeat", `{"sent_at":"`+t0.Add(time.Minute).Format(time.RFC3339)+`"}`, http.StatusNoContent) // upload 197331667813 ns → "3m17.331667813s" postJSON(t, h, http.MethodPost, "/api/v1/devices/device-1/stats", `{"sent_at":"2024-01-01T12:00:00Z","upload_time":197331667813}`, http.StatusNoContent) req := httptest.NewRequest(http.MethodGet, "/api/v1/devices/device-1/stats", nil) rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Fatalf("status = %d, want 200", rec.Code) } var got getDeviceStatsResponse if err := json.NewDecoder(rec.Body).Decode(&got); err != nil { t.Fatalf("decode: %v", err) } if got.Uptime != 200 { t.Fatalf("uptime = %v, want 200", got.Uptime) } if got.AvgUploadTime != "3m17.331667813s" { t.Fatalf("avg_upload_time = %q, want 3m17.331667813s", got.AvgUploadTime) } } func postJSON(t *testing.T, h http.Handler, method, path, body string, wantStatus int) { t.Helper() req := httptest.NewRequest(method, path, strings.NewReader(body)) req.Header.Set("Content-Type", "application/json") rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != wantStatus { t.Fatalf("%s %s status = %d, want %d; body=%s", method, path, rec.Code, wantStatus, rec.Body.String()) } }