package services import ( "testing" "time" "go.uber.org/zap" ) func TestNewS3StorageService(t *testing.T) { tests := []struct { name string cfg S3Config wantErr bool }{ { name: "valid config with bucket", cfg: S3Config{ Bucket: "test-bucket", Region: "us-east-1", Logger: zap.NewNop(), }, wantErr: false, }, { name: "missing bucket", cfg: S3Config{ Region: "us-east-1", Logger: zap.NewNop(), }, wantErr: true, }, { name: "default region", cfg: S3Config{ Bucket: "test-bucket", Logger: zap.NewNop(), }, wantErr: false, }, { name: "with custom endpoint", cfg: S3Config{ Bucket: "test-bucket", Region: "us-east-1", Endpoint: "http://localhost:9000", Logger: zap.NewNop(), }, wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Note: Ces tests ne peuvent pas réellement se connecter à S3 sans credentials // Ils testent principalement la validation de configuration // Pour des tests d'intégration réels, il faudrait utiliser un mock ou un service local comme MinIO service, err := NewS3StorageService(tt.cfg) if (err != nil) != tt.wantErr { t.Errorf("NewS3StorageService() error = %v, wantErr %v", err, tt.wantErr) return } if !tt.wantErr && service == nil { t.Error("NewS3StorageService() returned nil service without error") } }) } } func TestS3StorageService_GetPublicURL(t *testing.T) { tests := []struct { name string service *S3StorageService key string expected string }{ { name: "AWS S3 standard URL", service: &S3StorageService{ bucket: "test-bucket", region: "us-east-1", endpoint: "", }, key: "tracks/user123/track456/file.mp3", expected: "https://test-bucket.s3.us-east-1.amazonaws.com/tracks/user123/track456/file.mp3", }, { name: "MinIO custom endpoint URL", service: &S3StorageService{ bucket: "test-bucket", region: "us-east-1", endpoint: "http://localhost:9000", }, key: "tracks/user123/track456/file.mp3", expected: "http://localhost:9000/test-bucket/tracks/user123/track456/file.mp3", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { url := tt.service.GetPublicURL(tt.key) if url != tt.expected { t.Errorf("GetPublicURL() = %v, want %v", url, tt.expected) } }) } } func TestS3Config_Defaults(t *testing.T) { cfg := S3Config{ Bucket: "test-bucket", Logger: zap.NewNop(), } service, err := NewS3StorageService(cfg) if err == nil { // Si le service est créé, vérifier les valeurs par défaut if service.region != "us-east-1" { t.Errorf("Expected default region 'us-east-1', got %s", service.region) } if service.urlExpiry != time.Hour { t.Errorf("Expected default URL expiry 1h, got %v", service.urlExpiry) } } // Note: Le service peut échouer si le bucket n'existe pas, ce qui est normal _ = err } // TestS3StorageService_InterfaceCompliance vérifie que S3StorageService implémente bien l'interface S3Service func TestS3StorageService_InterfaceCompliance(t *testing.T) { var _ S3Service = (*S3StorageService)(nil) } // Note: Les tests d'intégration réels nécessiteraient: // 1. Un service S3 local (MinIO) ou des credentials AWS de test // 2. Des mocks pour le client S3 // 3. Un contexte de test avec timeout // // Exemple de test d'intégration (à implémenter avec MinIO): // func TestS3StorageService_UploadFile_Integration(t *testing.T) { // cfg := S3Config{ // Bucket: "test-bucket", // Region: "us-east-1", // Endpoint: "http://localhost:9000", // MinIO // AccessKey: "minioadmin", // SecretKey: "minioadmin", // Logger: zap.NewNop(), // } // service, err := NewS3StorageService(cfg) // if err != nil { // t.Skip("S3 service not available for integration test") // return // } // // ctx := context.Background() // testData := []byte("test file content") // key := "test/key.txt" // // url, err := service.UploadFile(ctx, testData, key, "text/plain") // if err != nil { // t.Fatalf("UploadFile() error = %v", err) // } // if url == "" { // t.Error("UploadFile() returned empty URL") // } // // // Cleanup // defer service.DeleteFile(ctx, key) // }