685 lines
20 KiB
Go
685 lines
20 KiB
Go
//go:build integration || pagination
|
|
// +build integration pagination
|
|
|
|
package pagination
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap/zaptest"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
"veza-backend-api/internal/core/track"
|
|
"veza-backend-api/internal/handlers"
|
|
"veza-backend-api/internal/models"
|
|
"veza-backend-api/internal/repositories"
|
|
"veza-backend-api/internal/services"
|
|
)
|
|
|
|
// setupPaginationTestRouter crée un router de test avec des données pour tester la pagination
|
|
func setupPaginationTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, uuid.UUID, func()) {
|
|
gin.SetMode(gin.TestMode)
|
|
logger := zaptest.NewLogger(t)
|
|
|
|
// Setup in-memory SQLite database
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err)
|
|
db.Exec("PRAGMA foreign_keys = ON")
|
|
|
|
// Auto-migrate models
|
|
err = db.AutoMigrate(
|
|
&models.User{},
|
|
&models.Track{},
|
|
&models.Playlist{},
|
|
&models.PlaylistTrack{},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Create test user
|
|
userID := uuid.New()
|
|
user := &models.User{
|
|
ID: userID,
|
|
Email: "test@example.com",
|
|
Username: "testuser",
|
|
PasswordHash: "$2a$10$abcdefghijklmnopqrstuvwxyz1234567890",
|
|
IsVerified: true,
|
|
}
|
|
err = db.Create(user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Create 50 tracks for pagination testing
|
|
uploadDir := t.TempDir()
|
|
for i := 0; i < 50; i++ {
|
|
track := &models.Track{
|
|
ID: uuid.New(),
|
|
UserID: userID,
|
|
Title: fmt.Sprintf("Test Track %d", i+1),
|
|
IsPublic: true,
|
|
}
|
|
err = db.Create(track).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Create 50 playlists for pagination testing
|
|
for i := 0; i < 50; i++ {
|
|
playlist := &models.Playlist{
|
|
ID: uuid.New(),
|
|
UserID: userID,
|
|
Title: fmt.Sprintf("Test Playlist %d", i+1),
|
|
IsPublic: true,
|
|
}
|
|
err = db.Create(playlist).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Create 10 additional users for pagination testing
|
|
for i := 0; i < 10; i++ {
|
|
user := &models.User{
|
|
ID: uuid.New(),
|
|
Email: fmt.Sprintf("user%d@example.com", i+1),
|
|
Username: fmt.Sprintf("user%d", i+1),
|
|
PasswordHash: "$2a$10$abcdefghijklmnopqrstuvwxyz1234567890",
|
|
IsVerified: true,
|
|
}
|
|
err = db.Create(user).Error
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Setup services (minimal setup for pagination tests)
|
|
|
|
trackService := track.NewTrackService(db, logger, uploadDir)
|
|
trackUploadService := services.NewTrackUploadService(db, logger)
|
|
chunkService := services.NewTrackChunkService(t.TempDir(), nil, logger)
|
|
likeService := services.NewTrackLikeService(db, logger)
|
|
streamService := services.NewStreamService("http://localhost:8082", logger)
|
|
trackHandler := track.NewTrackHandler(trackService, trackUploadService, chunkService, likeService, streamService)
|
|
|
|
playlistRepo := repositories.NewPlaylistRepository(db)
|
|
playlistTrackRepo := repositories.NewPlaylistTrackRepository(db)
|
|
playlistCollaboratorRepo := repositories.NewPlaylistCollaboratorRepository(db)
|
|
userRepo := repositories.NewGormUserRepository(db)
|
|
playlistService := services.NewPlaylistService(playlistRepo, playlistTrackRepo, playlistCollaboratorRepo, userRepo, logger)
|
|
playlistHandler := handlers.NewPlaylistHandler(playlistService, db, logger)
|
|
|
|
userService := services.NewUserServiceWithDB(userRepo, db)
|
|
profileHandler := handlers.NewProfileHandler(userService, logger)
|
|
|
|
// Create router
|
|
router := gin.New()
|
|
|
|
// Public routes
|
|
tracks := router.Group("/api/v1/tracks")
|
|
{
|
|
tracks.GET("", trackHandler.ListTracks)
|
|
}
|
|
|
|
users := router.Group("/api/v1/users")
|
|
{
|
|
users.GET("", profileHandler.ListUsers)
|
|
}
|
|
|
|
// Protected routes (with mock auth)
|
|
protected := router.Group("/api/v1")
|
|
protected.Use(func(c *gin.Context) {
|
|
c.Set("user_id", userID)
|
|
c.Next()
|
|
})
|
|
|
|
playlists := protected.Group("/playlists")
|
|
{
|
|
playlists.GET("", playlistHandler.GetPlaylists)
|
|
}
|
|
|
|
cleanup := func() {
|
|
// Cleanup handled by t.TempDir()
|
|
}
|
|
|
|
return router, db, userID, cleanup
|
|
}
|
|
|
|
// TestPagination_Tracks_Default teste la pagination par défaut pour les tracks
|
|
func TestPagination_Tracks_Default(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/tracks", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, resp["success"].(bool))
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
tracks, ok := data["tracks"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.LessOrEqual(t, len(tracks), 20, "Default limit should be 20")
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, float64(1), pagination["page"], "Default page should be 1")
|
|
assert.Equal(t, float64(20), pagination["limit"], "Default limit should be 20")
|
|
}
|
|
|
|
// TestPagination_Tracks_CustomParams teste la pagination avec des paramètres personnalisés
|
|
func TestPagination_Tracks_CustomParams(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/tracks?page=2&limit=10", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
tracks, ok := data["tracks"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.LessOrEqual(t, len(tracks), 10, "Should return at most 10 tracks")
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, float64(2), pagination["page"], "Page should be 2")
|
|
assert.Equal(t, float64(10), pagination["limit"], "Limit should be 10")
|
|
}
|
|
|
|
// TestPagination_Tracks_InvalidParams teste la validation des paramètres invalides
|
|
func TestPagination_Tracks_InvalidParams(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
tests := []struct {
|
|
name string
|
|
query string
|
|
expectedPage float64
|
|
expectedLimit float64
|
|
}{
|
|
{
|
|
name: "Negative page",
|
|
query: "page=-1&limit=10",
|
|
expectedPage: 1,
|
|
expectedLimit: 10,
|
|
},
|
|
{
|
|
name: "Zero page",
|
|
query: "page=0&limit=10",
|
|
expectedPage: 1,
|
|
expectedLimit: 10,
|
|
},
|
|
{
|
|
name: "Negative limit",
|
|
query: "page=1&limit=-5",
|
|
expectedPage: 1,
|
|
expectedLimit: 20,
|
|
},
|
|
{
|
|
name: "Zero limit",
|
|
query: "page=1&limit=0",
|
|
expectedPage: 1,
|
|
expectedLimit: 20,
|
|
},
|
|
{
|
|
name: "Limit too high",
|
|
query: "page=1&limit=200",
|
|
expectedPage: 1,
|
|
expectedLimit: 20, // Should default to 20 or max 100
|
|
},
|
|
{
|
|
name: "Invalid page format",
|
|
query: "page=abc&limit=10",
|
|
expectedPage: 1,
|
|
expectedLimit: 10,
|
|
},
|
|
{
|
|
name: "Invalid limit format",
|
|
query: "page=1&limit=xyz",
|
|
expectedPage: 1,
|
|
expectedLimit: 20,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/tracks?%s", tt.query), nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, tt.expectedPage, pagination["page"], "Page should be corrected")
|
|
assert.Equal(t, tt.expectedLimit, pagination["limit"], "Limit should be corrected")
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestPagination_Tracks_Metadata teste les métadonnées de pagination
|
|
func TestPagination_Tracks_Metadata(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/tracks?page=1&limit=10", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
// Verify pagination metadata
|
|
assert.Contains(t, pagination, "page")
|
|
assert.Contains(t, pagination, "limit")
|
|
assert.Contains(t, pagination, "total")
|
|
assert.Contains(t, pagination, "total_pages")
|
|
|
|
total := pagination["total"].(float64)
|
|
assert.Greater(t, total, float64(0), "Total should be greater than 0")
|
|
|
|
totalPages := pagination["total_pages"].(float64)
|
|
assert.Greater(t, totalPages, float64(0), "Total pages should be greater than 0")
|
|
}
|
|
|
|
// TestPagination_Tracks_Navigation teste la navigation entre les pages
|
|
func TestPagination_Tracks_Navigation(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Get first page
|
|
req1 := httptest.NewRequest(http.MethodGet, "/api/v1/tracks?page=1&limit=10", nil)
|
|
w1 := httptest.NewRecorder()
|
|
router.ServeHTTP(w1, req1)
|
|
|
|
assert.Equal(t, http.StatusOK, w1.Code)
|
|
|
|
var resp1 map[string]interface{}
|
|
err := json.Unmarshal(w1.Body.Bytes(), &resp1)
|
|
require.NoError(t, err)
|
|
|
|
data1, _ := resp1["data"].(map[string]interface{})
|
|
tracks1, _ := data1["tracks"].([]interface{})
|
|
pagination1, _ := data1["pagination"].(map[string]interface{})
|
|
|
|
// Get second page
|
|
req2 := httptest.NewRequest(http.MethodGet, "/api/v1/tracks?page=2&limit=10", nil)
|
|
w2 := httptest.NewRecorder()
|
|
router.ServeHTTP(w2, req2)
|
|
|
|
assert.Equal(t, http.StatusOK, w2.Code)
|
|
|
|
var resp2 map[string]interface{}
|
|
err = json.Unmarshal(w2.Body.Bytes(), &resp2)
|
|
require.NoError(t, err)
|
|
|
|
data2, _ := resp2["data"].(map[string]interface{})
|
|
tracks2, _ := data2["tracks"].([]interface{})
|
|
pagination2, _ := data2["pagination"].(map[string]interface{})
|
|
|
|
// Verify pages are different
|
|
assert.Equal(t, float64(1), pagination1["page"])
|
|
assert.Equal(t, float64(2), pagination2["page"])
|
|
|
|
// Verify tracks are different (if we have enough tracks)
|
|
if len(tracks1) > 0 && len(tracks2) > 0 {
|
|
track1ID := tracks1[0].(map[string]interface{})["id"].(string)
|
|
track2ID := tracks2[0].(map[string]interface{})["id"].(string)
|
|
assert.NotEqual(t, track1ID, track2ID, "Tracks should be different between pages")
|
|
}
|
|
}
|
|
|
|
// TestPagination_Users_Default teste la pagination par défaut pour les users
|
|
func TestPagination_Users_Default(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/users", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, resp["success"].(bool))
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
users, ok := data["users"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.LessOrEqual(t, len(users), 20, "Default limit should be 20")
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, float64(1), pagination["page"], "Default page should be 1")
|
|
assert.Equal(t, float64(20), pagination["limit"], "Default limit should be 20")
|
|
}
|
|
|
|
// TestPagination_Users_CustomParams teste la pagination avec des paramètres personnalisés pour users
|
|
func TestPagination_Users_CustomParams(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/users?page=2&limit=5", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
users, ok := data["users"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.LessOrEqual(t, len(users), 5, "Should return at most 5 users")
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, float64(2), pagination["page"], "Page should be 2")
|
|
assert.Equal(t, float64(5), pagination["limit"], "Limit should be 5")
|
|
}
|
|
|
|
// TestPagination_Users_Metadata teste les métadonnées de pagination pour users
|
|
func TestPagination_Users_Metadata(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/users?page=1&limit=5", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
// Verify pagination metadata
|
|
assert.Contains(t, pagination, "page")
|
|
assert.Contains(t, pagination, "limit")
|
|
assert.Contains(t, pagination, "total")
|
|
assert.Contains(t, pagination, "total_pages")
|
|
assert.Contains(t, pagination, "has_next")
|
|
assert.Contains(t, pagination, "has_prev")
|
|
|
|
total := pagination["total"].(float64)
|
|
assert.Greater(t, total, float64(0), "Total should be greater than 0")
|
|
|
|
hasNext := pagination["has_next"].(bool)
|
|
hasPrev := pagination["has_prev"].(bool)
|
|
|
|
// On first page, should not have previous
|
|
assert.False(t, hasPrev, "First page should not have previous")
|
|
|
|
// If total > limit, should have next
|
|
if total > pagination["limit"].(float64) {
|
|
assert.True(t, hasNext, "Should have next page if total > limit")
|
|
}
|
|
}
|
|
|
|
// TestPagination_Playlists_Default teste la pagination par défaut pour les playlists
|
|
func TestPagination_Playlists_Default(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/playlists", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, resp["success"].(bool))
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
playlists, ok := data["playlists"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.LessOrEqual(t, len(playlists), 20, "Default limit should be 20")
|
|
|
|
// Playlists endpoint might return different structure
|
|
// Check if pagination is present
|
|
if pagination, ok := data["pagination"].(map[string]interface{}); ok {
|
|
assert.Equal(t, float64(1), pagination["page"], "Default page should be 1")
|
|
assert.Equal(t, float64(20), pagination["limit"], "Default limit should be 20")
|
|
} else {
|
|
// Some endpoints might return page/limit directly
|
|
assert.Contains(t, data, "page")
|
|
assert.Contains(t, data, "limit")
|
|
}
|
|
}
|
|
|
|
// TestPagination_Playlists_CustomParams teste la pagination avec des paramètres personnalisés pour playlists
|
|
func TestPagination_Playlists_CustomParams(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/playlists?page=2&limit=15", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
playlists, ok := data["playlists"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.LessOrEqual(t, len(playlists), 15, "Should return at most 15 playlists")
|
|
}
|
|
|
|
// TestPagination_Consistency teste que tous les endpoints utilisent le même format de pagination
|
|
func TestPagination_Consistency(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
endpoints := []string{
|
|
"/api/v1/tracks?page=1&limit=10",
|
|
"/api/v1/users?page=1&limit=10",
|
|
"/api/v1/playlists?page=1&limit=10",
|
|
}
|
|
|
|
for _, endpoint := range endpoints {
|
|
t.Run(fmt.Sprintf("Consistency: %s", endpoint), func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, endpoint, nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
// All endpoints should return success: true
|
|
assert.True(t, resp["success"].(bool))
|
|
|
|
// All endpoints should have data
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok, "Response should have data field")
|
|
|
|
// All endpoints should have pagination info (either in pagination object or directly)
|
|
hasPagination := false
|
|
if _, ok := data["pagination"]; ok {
|
|
hasPagination = true
|
|
} else if _, ok := data["page"]; ok {
|
|
hasPagination = true
|
|
}
|
|
assert.True(t, hasPagination, "Response should have pagination information")
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestPagination_EdgeCases teste les cas limites de pagination
|
|
func TestPagination_EdgeCases(t *testing.T) {
|
|
router, _, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
tests := []struct {
|
|
name string
|
|
query string
|
|
expectedStatus int
|
|
}{
|
|
{
|
|
name: "Empty query",
|
|
query: "",
|
|
expectedStatus: http.StatusOK,
|
|
},
|
|
{
|
|
name: "Very large page number",
|
|
query: "page=999999&limit=10",
|
|
expectedStatus: http.StatusOK,
|
|
},
|
|
{
|
|
name: "Page 1 with limit 1",
|
|
query: "page=1&limit=1",
|
|
expectedStatus: http.StatusOK,
|
|
},
|
|
{
|
|
name: "Maximum limit",
|
|
query: "page=1&limit=100",
|
|
expectedStatus: http.StatusOK,
|
|
},
|
|
{
|
|
name: "Limit exceeds maximum",
|
|
query: "page=1&limit=1000",
|
|
expectedStatus: http.StatusOK,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/tracks?%s", tt.query), nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, tt.expectedStatus, w.Code, "Should handle edge case gracefully")
|
|
|
|
if w.Code == http.StatusOK {
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
assert.True(t, resp["success"].(bool), "Response should be successful")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestPagination_TotalCount teste que le total count est correct
|
|
func TestPagination_TotalCount(t *testing.T) {
|
|
router, db, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Count total tracks in database
|
|
var totalTracks int64
|
|
db.Model(&models.Track{}).Count(&totalTracks)
|
|
|
|
// Request first page
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/tracks?page=1&limit=10", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
// Verify total matches database count
|
|
responseTotal := pagination["total"].(float64)
|
|
assert.Equal(t, float64(totalTracks), responseTotal, "Total should match database count")
|
|
}
|
|
|
|
// TestPagination_TotalPages teste le calcul de total_pages
|
|
func TestPagination_TotalPages(t *testing.T) {
|
|
router, db, _, cleanup := setupPaginationTestRouter(t)
|
|
defer cleanup()
|
|
|
|
// Count total tracks
|
|
var totalTracks int64
|
|
db.Model(&models.Track{}).Count(&totalTracks)
|
|
|
|
limit := 10
|
|
expectedTotalPages := int((totalTracks + int64(limit) - 1) / int64(limit))
|
|
|
|
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/v1/tracks?page=1&limit=%d", limit), nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
var resp map[string]interface{}
|
|
err := json.Unmarshal(w.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
|
|
data, ok := resp["data"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
pagination, ok := data["pagination"].(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
totalPages := pagination["total_pages"].(float64)
|
|
assert.Equal(t, float64(expectedTotalPages), totalPages, "Total pages should be calculated correctly")
|
|
}
|