- Backend: Add X-API-Deprecated header alongside existing X-API-Version-Deprecated - Frontend: Show deprecation warning toast when deprecated API version detected - Warning shown only once per session to avoid spam - Includes sunset date in warning message if available
209 lines
4.9 KiB
Go
209 lines
4.9 KiB
Go
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")
|
|
}
|