// >>> VEZA:BEGIN api_health_test.go package integration import ( "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "veza-backend-api/internal/api" "veza-backend-api/internal/config" "veza-backend-api/internal/handlers" ) // setupTestRouter crée un router de test minimal func setupTestRouter() *gin.Engine { gin.SetMode(gin.TestMode) router := gin.New() // Créer un handler simple pour /health (utiliser Check qui retourne {status: "ok"}) healthHandler := handlers.NewHealthHandlerSimple(nil) router.GET("/health", healthHandler.Check) router.GET("/api/v1/health", healthHandler.Check) return router } // TestAPIHealth tests the health endpoint func TestAPIHealth(t *testing.T) { router := setupTestRouter() req := httptest.NewRequest("GET", "/health", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) // Le format standardisé retourne {success: true, data: {status: "ok"}} if data, ok := response["data"].(map[string]interface{}); ok { assert.Equal(t, "ok", data["status"]) } else { // Fallback pour format simple (si handler retourne directement) status, ok := response["status"] assert.True(t, ok, "Response should have status field: %v", response) assert.Contains(t, []interface{}{"ok", "healthy"}, status, "Status should be 'ok' or 'healthy'") } } // TestAPIHealthV1 tests the v1 health endpoint func TestAPIHealthV1(t *testing.T) { router := setupTestRouter() req := httptest.NewRequest("GET", "/api/v1/health", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var response map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) // Le format standardisé retourne {success: true, data: {status: "ok"}} if data, ok := response["data"].(map[string]interface{}); ok { assert.Equal(t, "ok", data["status"]) } else { // Fallback pour format simple (si handler retourne directement) status, ok := response["status"] assert.True(t, ok, "Response should have status field: %v", response) assert.Contains(t, []interface{}{"ok", "healthy"}, status, "Status should be 'ok' or 'healthy'") } } // TestAPIStatus tests the status endpoint func TestAPIStatus(t *testing.T) { // Skip si pas de DB configurée if testing.Short() { t.Skip("Skipping integration test in short mode") } // Créer une config de test cfg, err := config.NewConfig() if err != nil { t.Skipf("Skipping test: cannot create config: %v", err) return } // Créer un router avec la config gin.SetMode(gin.TestMode) router := gin.New() apiRouter := api.NewAPIRouter(cfg.Database, cfg) apiRouter.Setup(router) req := httptest.NewRequest("GET", "/api/v1/status", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var response handlers.StatusResponse err = json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.NotEmpty(t, response.Status) assert.GreaterOrEqual(t, response.UptimeSec, int64(0)) assert.NotNil(t, response.Services) } // TestAPIStatusDegraded tests status endpoint when a service is down func TestAPIStatusDegraded(t *testing.T) { // Ce test nécessite un mock ou une configuration spécifique // Pour l'instant, on vérifie juste que le endpoint répond if testing.Short() { t.Skip("Skipping integration test in short mode") } cfg, err := config.NewConfig() if err != nil { t.Skipf("Skipping test: cannot create config: %v", err) return } gin.SetMode(gin.TestMode) router := gin.New() apiRouter := api.NewAPIRouter(cfg.Database, cfg) apiRouter.Setup(router) req := httptest.NewRequest("GET", "/api/v1/status", nil) w := httptest.NewRecorder() router.ServeHTTP(w, req) // Le status peut être "ok" ou "degraded" selon l'état des services assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusServiceUnavailable) var response handlers.StatusResponse err = json.Unmarshal(w.Body.Bytes(), &response) assert.NoError(t, err) assert.Contains(t, []string{"ok", "degraded"}, response.Status) } // TestAPIHealthHTTP is a basic HTTP test func TestAPIHealthHTTP(t *testing.T) { // This test requires the API server to be running // In CI, use docker-compose or a test server baseURL := "http://localhost:8080" if testing.Short() { t.Skip("Skipping integration test in short mode") } resp, err := http.Get(baseURL + "/api/v1/health") if err != nil { t.Skipf("API server not available: %v", err) return } defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) } // <<< VEZA:END api_health_test.go