package api import ( "net/http" "net/http/httptest" "testing" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" ) func TestNewVersionManager(t *testing.T) { logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) assert.NotNil(t, vm) assert.Equal(t, DefaultAPIVersion, vm.GetDefaultVersion()) assert.NotEmpty(t, vm.GetAllVersions()) } func TestVersionManager_RegisterVersion(t *testing.T) { logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) version := &APIVersion{ Version: "v2", Deprecated: false, Description: "New API version", } vm.RegisterVersion(version) retrieved, exists := vm.GetVersion("v2") require.True(t, exists) assert.Equal(t, version, retrieved) } func TestVersionManager_GetVersion_NotFound(t *testing.T) { logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) _, exists := vm.GetVersion("v99") assert.False(t, exists) } func TestNormalizeVersion(t *testing.T) { tests := []struct { input string expected string }{ {"v1", "v1"}, {"1", "v1"}, {"V1", "v1"}, {" v2 ", "v2"}, {"2", "v2"}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { result := normalizeVersion(tt.input) assert.Equal(t, tt.expected, result) }) } } func TestParseAcceptHeader(t *testing.T) { tests := []struct { name string accept string expected string }{ { name: "vnd.veza.v1", accept: "application/vnd.veza.v1+json", expected: "v1", }, { name: "vnd.veza.v2", accept: "application/vnd.veza.v2+json", expected: "v2", }, { name: "multiple accept types", accept: "application/json, application/vnd.veza.v1+json", expected: "v1", }, { name: "no version", accept: "application/json", expected: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := parseAcceptHeader(tt.accept) assert.Equal(t, tt.expected, result) }) } } func TestVersionMiddleware_HeaderXAPIVersion(t *testing.T) { gin.SetMode(gin.TestMode) logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) router := gin.New() router.Use(VersionMiddleware(vm)) router.GET("/test", func(c *gin.Context) { version := GetAPIVersion(c) c.JSON(200, gin.H{"version": version}) }) w := httptest.NewRecorder() req := httptest.NewRequest("GET", "/test", nil) req.Header.Set(APIVersionHeader, "v1") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) assert.Equal(t, "v1", w.Header().Get(APIVersionHeader)) } func TestVersionMiddleware_AcceptHeader(t *testing.T) { gin.SetMode(gin.TestMode) logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) router := gin.New() router.Use(VersionMiddleware(vm)) router.GET("/test", func(c *gin.Context) { version := GetAPIVersion(c) c.JSON(200, gin.H{"version": version}) }) w := httptest.NewRecorder() req := httptest.NewRequest("GET", "/test", nil) req.Header.Set(AcceptHeaderVersion, "application/vnd.veza.v1+json") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) } func TestVersionMiddleware_InvalidVersion(t *testing.T) { gin.SetMode(gin.TestMode) logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) router := gin.New() router.Use(VersionMiddleware(vm)) router.GET("/test", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) w := httptest.NewRecorder() req := httptest.NewRequest("GET", "/test", nil) req.Header.Set(APIVersionHeader, "v99") router.ServeHTTP(w, req) assert.Equal(t, http.StatusBadRequest, w.Code) } func TestVersionMiddleware_DeprecatedVersion(t *testing.T) { gin.SetMode(gin.TestMode) logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) // Enregistrer une version dépréciée vm.RegisterVersion(&APIVersion{ Version: "v0", Deprecated: true, SunsetDate: "2025-12-31T00:00:00Z", Description: "Deprecated version", }) router := gin.New() router.Use(VersionMiddleware(vm)) router.GET("/test", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) }) w := httptest.NewRecorder() req := httptest.NewRequest("GET", "/test", nil) req.Header.Set(APIVersionHeader, "v0") router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) assert.Equal(t, "true", w.Header().Get("X-API-Deprecated")) assert.Equal(t, "true", w.Header().Get("X-API-Version-Deprecated")) assert.Equal(t, "2025-12-31T00:00:00Z", w.Header().Get("Sunset")) } func TestVersionInfoHandler(t *testing.T) { gin.SetMode(gin.TestMode) logger, _ := zap.NewDevelopment() vm := NewVersionManager(logger) router := gin.New() router.GET("/api/versions", VersionInfoHandler(vm)) w := httptest.NewRecorder() req := httptest.NewRequest("GET", "/api/versions", nil) router.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) assert.Contains(t, w.Body.String(), "current_version") assert.Contains(t, w.Body.String(), "versions") }