veza/veza-backend-api/internal/handlers/track_handler_test.go.bak

1036 lines
27 KiB
Go
Raw Normal View History

2025-12-03 19:29:37 +00:00
package handlers
import (
"bytes"
"encoding/json"
"fmt"
"github.com/google/uuid"
"mime/multipart"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"veza-backend-api/internal/models"
"veza-backend-api/internal/services"
)
// createTestMP3 creates a minimal valid MP3 file header for testing
func createTestMP3() ([]byte, error) {
// MP3 file header (ID3v2 tag)
header := []byte{
'I', 'D', '3', // ID3v2 marker
0x03, 0x00, // Version
0x00, // Flags
0x00, 0x00, 0x00, 0x00, // Size (0 for test)
}
return header, nil
}
// createTestAudioFile creates a test audio file with specified extension
func createTestAudioFile(ext string) ([]byte, error) {
switch ext {
case ".mp3":
return createTestMP3()
case ".flac":
// FLAC file header
return []byte{'f', 'L', 'a', 'C', 0x00, 0x00, 0x00, 0x22}, nil
case ".wav":
// WAV file header
return []byte{'R', 'I', 'F', 'F', 0x00, 0x00, 0x00, 0x00, 'W', 'A', 'V', 'E'}, nil
case ".ogg":
// OGG file header
return []byte{'O', 'g', 'g', 'S', 0x00, 0x02, 0x00, 0x00}, nil
default:
return createTestMP3()
}
}
func setupTestTrackHandler(t *testing.T) (*TrackHandler, *gorm.DB, func()) {
gin.SetMode(gin.TestMode)
// Setup in-memory SQLite database
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
assert.NoError(t, err)
// Auto-migrate
err = db.AutoMigrate(&models.Track{}, &models.User{})
assert.NoError(t, err)
// Create test user
user := &models.User{
ID: 123,
Username: "testuser",
Email: "test@example.com",
IsActive: true,
}
err = db.Create(user).Error
assert.NoError(t, err)
// Setup logger
logger := zap.NewNop()
// Setup test upload directory
testUploadDir := "test_uploads/tracks"
trackService := services.NewTrackService(db, logger, testUploadDir)
trackUploadService := services.NewTrackUploadService(db, logger)
chunkService := services.NewTrackChunkService("test_uploads/tracks/chunks", logger)
trackLikeService := services.NewTrackLikeService(db, logger)
// Pass nil for streamService in tests
trackHandler := NewTrackHandler(trackService, trackUploadService, chunkService, trackLikeService, nil)
// Cleanup function
cleanup := func() {
os.RemoveAll("test_uploads")
}
return trackHandler, db, cleanup
}
func TestTrackHandler_UploadTrack_Success(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Create test MP3 file
mp3Data, err := createTestAudioFile(".mp3")
assert.NoError(t, err)
// Create multipart form
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", "test.mp3")
assert.NoError(t, err)
_, err = part.Write(mp3Data)
assert.NoError(t, err)
writer.Close()
// Create request
req := httptest.NewRequest("POST", "/api/v1/tracks", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
// Set user_id in context (simulating auth middleware)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
// Execute
handler.UploadTrack(c)
// Assert
assert.Equal(t, http.StatusCreated, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response, "track")
track := response["track"].(map[string]interface{})
assert.Equal(t, float64(123), track["user_id"])
assert.Equal(t, "test", track["title"])
assert.Equal(t, "MP3", track["format"])
// Verify track was created in DB
var dbTrack models.Track
err = db.First(&dbTrack, track["id"]).Error
assert.NoError(t, err)
assert.Equal(t, int64(123), dbTrack.UserID)
assert.Equal(t, "test", dbTrack.Title)
}
func TestTrackHandler_UploadTrack_Unauthorized(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Create request without user_id in context
req := httptest.NewRequest("POST", "/api/v1/tracks/upload", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
// No user_id set
// Execute
handler.UploadTrack(c)
// Assert
assert.Equal(t, http.StatusUnauthorized, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "unauthorized", response["error"])
}
func TestTrackHandler_UploadTrack_NoFile(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Create request without file
req := httptest.NewRequest("POST", "/api/v1/tracks/upload", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
// Execute
handler.UploadTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response["error"], "no file provided")
}
func TestTrackHandler_UploadTrack_InvalidFormat(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Create test file with invalid format
invalidData := []byte("not an audio file")
// Create multipart form
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", "test.txt")
assert.NoError(t, err)
_, err = part.Write(invalidData)
assert.NoError(t, err)
writer.Close()
// Create request
req := httptest.NewRequest("POST", "/api/v1/tracks", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
// Execute
handler.UploadTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response["error"], "Invalid file format")
}
func TestTrackHandler_UploadTrack_FileTooLarge(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Create a large file (over 100MB)
largeData := make([]byte, 101*1024*1024) // 101MB
// Create multipart form
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", "large.mp3")
assert.NoError(t, err)
_, err = part.Write(largeData)
assert.NoError(t, err)
writer.Close()
// Create request
req := httptest.NewRequest("POST", "/api/v1/tracks", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
// Execute
handler.UploadTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response["error"], "File size exceeds maximum")
}
func TestTrackHandler_UploadTrack_ValidFormats(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
formats := []struct {
ext string
expected string
}{
{".mp3", "MP3"},
{".flac", "FLAC"},
{".wav", "WAV"},
{".ogg", "OGG"},
}
for _, format := range formats {
t.Run(format.ext, func(t *testing.T) {
// Create test audio file
audioData, err := createTestAudioFile(format.ext)
assert.NoError(t, err)
// Create multipart form
body := new(bytes.Buffer)
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile("file", "test"+format.ext)
assert.NoError(t, err)
_, err = part.Write(audioData)
assert.NoError(t, err)
writer.Close()
// Create request
req := httptest.NewRequest("POST", "/api/v1/tracks", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
// Execute
handler.UploadTrack(c)
// Assert
if w.Code != http.StatusCreated {
t.Logf("Response body: %s", w.Body.String())
}
assert.Equal(t, http.StatusCreated, w.Code, "Format %s should be accepted", format.ext)
})
}
}
func TestTrackHandler_ListTracks_Success(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer quelques tracks avec statut completed
track1 := &models.Track{
UserID: 123,
Title: "Track 1",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "Track 2",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Jazz",
Duration: 200,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
// Créer request
req := httptest.NewRequest("GET", "/api/v1/tracks?page=1&limit=20", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
// Execute
handler.ListTracks(c)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response, "tracks")
assert.Contains(t, response, "pagination")
tracks := response["tracks"].([]interface{})
assert.GreaterOrEqual(t, len(tracks), 2)
pagination := response["pagination"].(map[string]interface{})
assert.Equal(t, float64(1), pagination["page"])
assert.Equal(t, float64(20), pagination["limit"])
}
func TestTrackHandler_ListTracks_WithFilters(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer tracks avec différents genres
track1 := &models.Track{
UserID: 123,
Title: "Rock Track",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "Jazz Track",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Jazz",
Duration: 200,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
// Test avec filtre genre
req := httptest.NewRequest("GET", "/api/v1/tracks?genre=Rock", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
handler.ListTracks(c)
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
tracks := response["tracks"].([]interface{})
assert.Equal(t, 1, len(tracks))
track := tracks[0].(map[string]interface{})
assert.Equal(t, "Rock", track["genre"])
}
func TestTrackHandler_ListTracks_WithPagination(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer 5 tracks
for i := 1; i <= 5; i++ {
track := &models.Track{
UserID: 123,
Title: "Track " + string(rune('0'+i)),
FilePath: "/test/track" + string(rune('0'+i)) + ".mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
}
// Test page 1 avec limit 2
req := httptest.NewRequest("GET", "/api/v1/tracks?page=1&limit=2", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
handler.ListTracks(c)
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
tracks := response["tracks"].([]interface{})
assert.Equal(t, 2, len(tracks))
pagination := response["pagination"].(map[string]interface{})
assert.Equal(t, float64(1), pagination["page"])
assert.Equal(t, float64(2), pagination["limit"])
assert.Equal(t, float64(5), pagination["total"])
}
func TestTrackHandler_ListTracks_WithSorting(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer tracks avec différents titres
track1 := &models.Track{
UserID: 123,
Title: "A Track",
FilePath: "/test/track1.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track1).Error
assert.NoError(t, err)
track2 := &models.Track{
UserID: 123,
Title: "Z Track",
FilePath: "/test/track2.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err = db.Create(track2).Error
assert.NoError(t, err)
// Test avec tri par titre asc
req := httptest.NewRequest("GET", "/api/v1/tracks?sort_by=title&sort_order=asc", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
handler.ListTracks(c)
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
tracks := response["tracks"].([]interface{})
assert.GreaterOrEqual(t, len(tracks), 2)
// Vérifier que le tri est appliqué (A avant Z)
firstTrack := tracks[0].(map[string]interface{})
assert.Equal(t, "A Track", firstTrack["title"])
}
func TestTrackHandler_UpdateTrack_Success(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Créer request body
updateData := map[string]interface{}{
"title": "Updated Title",
"genre": "Jazz",
}
body, _ := json.Marshal(updateData)
// Créer request
req := httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/tracks/%d", track.ID), bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: fmt.Sprintf("%d", track.ID)}}
// Execute
handler.UpdateTrack(c)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response, "track")
updatedTrack := response["track"].(map[string]interface{})
assert.Equal(t, "Updated Title", updatedTrack["title"])
assert.Equal(t, "Jazz", updatedTrack["genre"])
}
func TestTrackHandler_UpdateTrack_NotFound(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request body
updateData := map[string]interface{}{
"title": "Updated Title",
}
body, _ := json.Marshal(updateData)
// Créer request avec un ID qui n'existe pas
req := httptest.NewRequest("PUT", "/api/v1/tracks/99999", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: "99999"}}
// Execute
handler.UpdateTrack(c)
// Assert
assert.Equal(t, http.StatusNotFound, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "track not found", response["error"])
}
func TestTrackHandler_UpdateTrack_Forbidden(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer un track appartenant à l'utilisateur 123
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Créer request body
updateData := map[string]interface{}{
"title": "Updated Title",
}
body, _ := json.Marshal(updateData)
// Créer request avec un autre utilisateur (456)
req := httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/tracks/%d", track.ID), bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(456))
c.Params = gin.Params{gin.Param{Key: "id", Value: fmt.Sprintf("%d", track.ID)}}
// Execute
handler.UpdateTrack(c)
// Assert
assert.Equal(t, http.StatusForbidden, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "forbidden", response["error"])
}
func TestTrackHandler_UpdateTrack_Unauthorized(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request body
updateData := map[string]interface{}{
"title": "Updated Title",
}
body, _ := json.Marshal(updateData)
// Créer request sans user_id
req := httptest.NewRequest("PUT", "/api/v1/tracks/1", bytes.NewBuffer(body))
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
// Pas de user_id
c.Params = gin.Params{gin.Param{Key: "id", Value: "1"}}
// Execute
handler.UpdateTrack(c)
// Assert
assert.Equal(t, http.StatusUnauthorized, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "unauthorized", response["error"])
}
func TestTrackHandler_UpdateTrack_InvalidID(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request body
updateData := map[string]interface{}{
"title": "Updated Title",
}
body, _ := json.Marshal(updateData)
// Créer request avec un ID invalide
req := httptest.NewRequest("PUT", "/api/v1/tracks/invalid", bytes.NewBuffer(body))
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: "invalid"}}
// Execute
handler.UpdateTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "invalid track id", response["error"])
}
func TestTrackHandler_UpdateTrack_EmptyTitle(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Original Title",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Créer request body avec titre vide
updateData := map[string]interface{}{
"title": "",
}
body, _ := json.Marshal(updateData)
// Créer request
req := httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/tracks/%d", track.ID), bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: fmt.Sprintf("%d", track.ID)}}
// Execute
handler.UpdateTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response["error"], "title cannot be empty")
}
func TestTrackHandler_DeleteTrack_Success(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Test Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Créer request
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/v1/tracks/%d", track.ID), nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: fmt.Sprintf("%d", track.ID)}}
// Execute
handler.DeleteTrack(c)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "track deleted successfully", response["message"])
// Vérifier que le track a été supprimé
var deletedTrack models.Track
err = db.First(&deletedTrack, track.ID).Error
assert.Error(t, err)
assert.Equal(t, gorm.ErrRecordNotFound, err)
}
func TestTrackHandler_DeleteTrack_NotFound(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request avec un ID qui n'existe pas
req := httptest.NewRequest("DELETE", "/api/v1/tracks/99999", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: "99999"}}
// Execute
handler.DeleteTrack(c)
// Assert
assert.Equal(t, http.StatusNotFound, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "track not found", response["error"])
}
func TestTrackHandler_DeleteTrack_Forbidden(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer un track appartenant à l'utilisateur 123
track := &models.Track{
UserID: 123,
Title: "Test Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Créer request avec un autre utilisateur (456)
req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/v1/tracks/%d", track.ID), nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(456))
c.Params = gin.Params{gin.Param{Key: "id", Value: fmt.Sprintf("%d", track.ID)}}
// Execute
handler.DeleteTrack(c)
// Assert
assert.Equal(t, http.StatusForbidden, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "forbidden", response["error"])
// Vérifier que le track n'a pas été supprimé
var existingTrack models.Track
err = db.First(&existingTrack, track.ID).Error
assert.NoError(t, err)
assert.Equal(t, track.ID, existingTrack.ID)
}
func TestTrackHandler_DeleteTrack_Unauthorized(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request sans user_id
req := httptest.NewRequest("DELETE", "/api/v1/tracks/1", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
// Pas de user_id
c.Params = gin.Params{gin.Param{Key: "id", Value: "1"}}
// Execute
handler.DeleteTrack(c)
// Assert
assert.Equal(t, http.StatusUnauthorized, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "unauthorized", response["error"])
}
func TestTrackHandler_DeleteTrack_InvalidID(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request avec un ID invalide
req := httptest.NewRequest("DELETE", "/api/v1/tracks/invalid", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: "invalid"}}
// Execute
handler.DeleteTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "invalid track id", response["error"])
}
func TestTrackHandler_GetTrack_Success(t *testing.T) {
handler, db, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer un track
track := &models.Track{
UserID: 123,
Title: "Test Track",
FilePath: "/test/track.mp3",
FileSize: 5 * 1024 * 1024,
Format: "MP3",
Genre: "Rock",
Duration: 180,
IsPublic: true,
Status: models.TrackStatusCompleted,
}
err := db.Create(track).Error
assert.NoError(t, err)
// Créer request
req := httptest.NewRequest("GET", fmt.Sprintf("/api/v1/tracks/%d", track.ID), nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: fmt.Sprintf("%d", track.ID)}}
// Execute
handler.GetTrack(c)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response map[string]interface{}
err = json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Contains(t, response, "track")
retrievedTrack := response["track"].(map[string]interface{})
assert.Equal(t, float64(track.ID), retrievedTrack["id"])
assert.Equal(t, track.Title, retrievedTrack["title"])
}
func TestTrackHandler_GetTrack_NotFound(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request avec un ID qui n'existe pas
req := httptest.NewRequest("GET", "/api/v1/tracks/99999", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: "99999"}}
// Execute
handler.GetTrack(c)
// Assert
assert.Equal(t, http.StatusNotFound, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "track not found", response["error"])
}
func TestTrackHandler_GetTrack_InvalidID(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request avec un ID invalide
req := httptest.NewRequest("GET", "/api/v1/tracks/invalid", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{gin.Param{Key: "id", Value: "invalid"}}
// Execute
handler.GetTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "invalid track id", response["error"])
}
func TestTrackHandler_GetTrack_MissingID(t *testing.T) {
handler, _, cleanup := setupTestTrackHandler(t)
defer cleanup()
// Créer request sans ID
req := httptest.NewRequest("GET", "/api/v1/tracks/", nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Request = req
c.Set("user_id", int64(123))
c.Params = gin.Params{}
// Execute
handler.GetTrack(c)
// Assert
assert.Equal(t, http.StatusBadRequest, w.Code)
var response map[string]interface{}
err := json.Unmarshal(w.Body.Bytes(), &response)
assert.NoError(t, err)
assert.Equal(t, "track id is required", response["error"])
}