283 lines
8.9 KiB
Go
283 lines
8.9 KiB
Go
package database
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
|
|
"veza-backend-api/internal/models"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// setupTestDB crée une base de données de test en mémoire
|
|
func setupTestDB(t *testing.T) *gorm.DB {
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
|
require.NoError(t, err, "Failed to open test database")
|
|
return db
|
|
}
|
|
|
|
// TestRunMigrations teste l'exécution des migrations GORM
|
|
func TestRunMigrations(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
err := RunMigrations(db)
|
|
assert.NoError(t, err, "RunMigrations should not return an error")
|
|
|
|
// Vérifier que les tables existent
|
|
assert.True(t, db.Migrator().HasTable(&models.User{}), "Users table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.RefreshToken{}), "RefreshTokens table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.Track{}), "Tracks table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.Playlist{}), "Playlists table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.PlaylistTrack{}), "PlaylistTracks table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.Message{}), "Messages table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.Room{}), "Rooms table should exist")
|
|
assert.True(t, db.Migrator().HasTable(&models.RoomMember{}), "RoomMembers table should exist")
|
|
}
|
|
|
|
// TestRunMigrations_Idempotent teste que les migrations sont idempotentes
|
|
func TestRunMigrations_Idempotent(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
// Exécuter les migrations deux fois
|
|
err := RunMigrations(db)
|
|
assert.NoError(t, err, "First RunMigrations should not return an error")
|
|
|
|
err = RunMigrations(db)
|
|
assert.NoError(t, err, "Second RunMigrations should not return an error")
|
|
|
|
// Vérifier que les tables existent toujours
|
|
assert.True(t, db.Migrator().HasTable(&models.User{}))
|
|
assert.True(t, db.Migrator().HasTable(&models.Track{}))
|
|
}
|
|
|
|
// TestAddIndexes teste la création des indexes
|
|
func TestAddIndexes(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
// Exécuter les migrations (qui incluent addIndexes)
|
|
err := RunMigrations(db)
|
|
require.NoError(t, err, "RunMigrations should succeed")
|
|
|
|
// Pour SQLite, vérifier que les indexes existent en vérifiant les migrations
|
|
// Note: SQLite stocke les indexes différemment de PostgreSQL
|
|
// On vérifie plutôt que les migrations n'ont pas d'erreur
|
|
// et que les tables peuvent être créées avec les indexes
|
|
|
|
// Vérifier que les tables ont bien les colonnes indexées
|
|
var user models.User
|
|
// Vérifier que l'index existe (HasIndex retourne un bool, pas une erreur)
|
|
hasIndex := db.Migrator().HasIndex(&user, "idx_users_email")
|
|
// SQLite peut avoir un comportement différent, donc on accepte les deux cas
|
|
// L'important est que la migration fonctionne sans erreur
|
|
_ = hasIndex
|
|
|
|
// Vérifier qu'on peut créer un utilisateur (ce qui teste les contraintes)
|
|
user = models.User{
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
Role: "user",
|
|
}
|
|
err = db.Create(&user).Error
|
|
assert.NoError(t, err, "Should be able to create a user")
|
|
|
|
// Vérifier qu'on ne peut pas créer un utilisateur avec un email dupliqué
|
|
user2 := models.User{
|
|
Username: "testuser2",
|
|
Email: "test@example.com",
|
|
Role: "user",
|
|
}
|
|
err = db.Create(&user2).Error
|
|
assert.Error(t, err, "Should not be able to create user with duplicate email")
|
|
}
|
|
|
|
// TestMigrations_UserRelations teste les relations entre User et autres modèles
|
|
func TestMigrations_UserRelations(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
err := RunMigrations(db)
|
|
require.NoError(t, err)
|
|
|
|
// Créer un utilisateur
|
|
user := models.User{
|
|
Username: "testuser",
|
|
Email: "test@example.com",
|
|
Role: "user",
|
|
}
|
|
err = db.Create(&user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Créer un refresh token pour cet utilisateur
|
|
refreshToken := models.RefreshToken{
|
|
UserID: user.ID,
|
|
TokenHash: "hash123",
|
|
ExpiresAt: db.NowFunc().AddDate(0, 0, 7),
|
|
}
|
|
err = db.Create(&refreshToken).Error
|
|
assert.NoError(t, err, "Should be able to create refresh token")
|
|
|
|
// Vérifier que la relation fonctionne
|
|
var retrievedToken models.RefreshToken
|
|
err = db.First(&retrievedToken, refreshToken.ID).Error
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, user.ID, retrievedToken.UserID)
|
|
}
|
|
|
|
// TestMigrations_TrackRelations teste les relations entre Track et User
|
|
func TestMigrations_TrackRelations(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
err := RunMigrations(db)
|
|
require.NoError(t, err)
|
|
|
|
// Créer un utilisateur
|
|
user := models.User{
|
|
Username: "creator",
|
|
Email: "creator@example.com",
|
|
Role: "user",
|
|
}
|
|
err = db.Create(&user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Créer une track pour cet utilisateur
|
|
track := models.Track{
|
|
UserID: user.ID,
|
|
Title: "Test Track",
|
|
Duration: 180,
|
|
}
|
|
err = db.Create(&track).Error
|
|
assert.NoError(t, err, "Should be able to create track")
|
|
|
|
// Vérifier que la relation fonctionne
|
|
var retrievedTrack models.Track
|
|
err = db.First(&retrievedTrack, track.ID).Error
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, user.ID, retrievedTrack.UserID)
|
|
}
|
|
|
|
// TestMigrations_PlaylistRelations teste les relations pour les playlists
|
|
func TestMigrations_PlaylistRelations(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
err := RunMigrations(db)
|
|
require.NoError(t, err)
|
|
|
|
// Créer un utilisateur
|
|
user := models.User{
|
|
Username: "playlist_owner",
|
|
Email: "owner@example.com",
|
|
Role: "user",
|
|
}
|
|
err = db.Create(&user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Créer une playlist
|
|
playlist := models.Playlist{
|
|
UserID: user.ID,
|
|
Title: "My Playlist",
|
|
}
|
|
err = db.Create(&playlist).Error
|
|
require.NoError(t, err)
|
|
|
|
// Créer une track
|
|
track := models.Track{
|
|
UserID: user.ID,
|
|
Title: "Track 1",
|
|
Duration: 200,
|
|
}
|
|
err = db.Create(&track).Error
|
|
require.NoError(t, err)
|
|
|
|
// Ajouter la track à la playlist
|
|
playlistTrack := models.PlaylistTrack{
|
|
PlaylistID: playlist.ID,
|
|
TrackID: track.ID,
|
|
Position: 1,
|
|
}
|
|
err = db.Create(&playlistTrack).Error
|
|
assert.NoError(t, err, "Should be able to add track to playlist")
|
|
|
|
// Vérifier la relation
|
|
var retrievedPlaylist models.Playlist
|
|
err = db.Preload("Tracks").First(&retrievedPlaylist, playlist.ID).Error
|
|
assert.NoError(t, err)
|
|
assert.Len(t, retrievedPlaylist.Tracks, 1)
|
|
}
|
|
|
|
// TestMigrations_RoomRelations teste les relations pour les rooms et messages
|
|
func TestMigrations_RoomRelations(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
err := RunMigrations(db)
|
|
require.NoError(t, err)
|
|
|
|
// Créer un utilisateur
|
|
user := models.User{
|
|
Username: "room_creator",
|
|
Email: "creator@example.com",
|
|
Role: "user",
|
|
}
|
|
err = db.Create(&user).Error
|
|
require.NoError(t, err)
|
|
|
|
// Créer une room
|
|
room := models.Room{
|
|
Name: "Test Room",
|
|
Type: "public",
|
|
CreatedBy: user.ID,
|
|
}
|
|
err = db.Create(&room).Error
|
|
require.NoError(t, err)
|
|
|
|
// Ajouter l'utilisateur à la room
|
|
roomMember := models.RoomMember{
|
|
RoomID: room.ID,
|
|
UserID: user.ID,
|
|
Role: "owner",
|
|
}
|
|
err = db.Create(&roomMember).Error
|
|
assert.NoError(t, err, "Should be able to add user to room")
|
|
|
|
// Créer un message dans la room
|
|
message := models.Message{
|
|
RoomID: room.ID,
|
|
UserID: user.ID,
|
|
Content: "Hello, world!",
|
|
Type: "text",
|
|
}
|
|
err = db.Create(&message).Error
|
|
assert.NoError(t, err, "Should be able to create message")
|
|
|
|
// Vérifier les relations
|
|
var retrievedRoom models.Room
|
|
err = db.Preload("Members").Preload("Messages").First(&retrievedRoom, room.ID).Error
|
|
assert.NoError(t, err)
|
|
assert.Len(t, retrievedRoom.Members, 1)
|
|
assert.Len(t, retrievedRoom.Messages, 1)
|
|
}
|
|
|
|
// TestEmailVerificationTokensMigration teste que la migration pour la table email_verification_tokens existe et peut être lue
|
|
func TestEmailVerificationTokensMigration(t *testing.T) {
|
|
migrationPath := "migrations/018_create_email_verification_tokens.sql"
|
|
|
|
// Vérifier que le fichier existe
|
|
content, err := os.ReadFile(migrationPath)
|
|
require.NoError(t, err, "Migration file should exist and be readable")
|
|
|
|
// Vérifier que le contenu n'est pas vide
|
|
assert.NotEmpty(t, content, "Migration file should not be empty")
|
|
|
|
// Vérifier que le contenu contient les éléments essentiels
|
|
contentStr := string(content)
|
|
assert.Contains(t, contentStr, "CREATE TABLE email_verification_tokens", "Should create email_verification_tokens table")
|
|
assert.Contains(t, contentStr, "user_id BIGINT", "Should have user_id column")
|
|
assert.Contains(t, contentStr, "token VARCHAR(255)", "Should have token column")
|
|
assert.Contains(t, contentStr, "expires_at TIMESTAMP", "Should have expires_at column")
|
|
assert.Contains(t, contentStr, "used BOOLEAN", "Should have used column")
|
|
assert.Contains(t, contentStr, "REFERENCES users(id) ON DELETE CASCADE", "Should have foreign key constraint")
|
|
assert.Contains(t, contentStr, "idx_email_verification_tokens_token", "Should have index on token")
|
|
assert.Contains(t, contentStr, "idx_email_verification_tokens_user_id", "Should have index on user_id")
|
|
assert.Contains(t, contentStr, "idx_email_verification_tokens_expires_at", "Should have index on expires_at")
|
|
}
|