package api import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "time" "dana/internal/onec" ) func TestOnecPushEndpoints(t *testing.T) { app := &API{ onecHook: "test-secret-key", onec: onec.New("", "test-secret-key", "X-Api-Key"), } mux := app.Routes() // 1. Unauthorized request req := httptest.NewRequest(http.MethodGet, "/api/v1/onec/appointments/pending", nil) w := httptest.NewRecorder() mux.ServeHTTP(w, req) if w.Code != http.StatusUnauthorized { t.Fatalf("expected 401 unauthorized, got %d", w.Code) } // 2. Authorized check with invalid body req = httptest.NewRequest(http.MethodPost, "/api/v1/onec/sync/all", bytes.NewReader([]byte("{invalid-json"))) req.Header.Set("X-Api-Key", "test-secret-key") w = httptest.NewRecorder() mux.ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Fatalf("expected 400 bad request, got %d", w.Code) } // 3. FindSlotBounds test now := time.Now() slots := []onec.Slot{ {Start: now.Add(time.Hour), End: now.Add(2 * time.Hour)}, {Start: now, End: now.Add(30 * time.Minute)}, {Start: now.Add(3 * time.Hour), End: now.Add(4 * time.Hour)}, } minT, maxT := findSlotBounds(slots) if !minT.Equal(now) { t.Errorf("expected minT = %v, got %v", now, minT) } if !maxT.Equal(now.Add(4 * time.Hour)) { t.Errorf("expected maxT = %v, got %v", now.Add(4*time.Hour), maxT) } } func TestOnecConfirmBadID(t *testing.T) { app := &API{ onecHook: "test-secret-key", } mux := app.Routes() body, _ := json.Marshal(confirmAppointmentReq{OnecAppointmentID: "001"}) req := httptest.NewRequest(http.MethodPost, "/api/v1/onec/appointments/invalid-id/confirm", bytes.NewReader(body)) req.Header.Set("X-Api-Key", "test-secret-key") w := httptest.NewRecorder() mux.ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Fatalf("expected 400 bad id, got %d", w.Code) } } func TestPushMergesDuplicateSlotsConservatively(t *testing.T) { start := time.Now().UTC() end := start.Add(time.Hour) free := onec.Slot{DoctorID: "d", BranchID: "b", Start: start, End: end, Status: "free"} busy := free busy.Status = "busy" for _, slots := range [][]onec.Slot{{free, busy}, {busy, free}} { got := mergeOnecSlots(slots) if len(got) != 1 || got[0].Status != "busy" { t.Fatalf("busy duplicate lost: %+v", got) } } }