veza/veza-backend-api/internal/services/metadata_service_test.go

240 lines
6.5 KiB
Go

package services
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)
func setupTestMetadataService(t *testing.T) *MetadataService {
logger := zap.NewNop()
return NewMetadataService(logger)
}
func TestMetadataService_NewMetadataService(t *testing.T) {
service := setupTestMetadataService(t)
assert.NotNil(t, service)
assert.NotNil(t, service.logger)
}
func TestMetadataService_ValidateMetadata_Valid(t *testing.T) {
service := setupTestMetadataService(t)
metadata := &AudioMetadata{
Title: "Test Title",
Artist: "Test Artist",
Album: "Test Album",
Genre: "Rock",
Year: 2023,
Track: 1,
}
err := service.ValidateMetadata(metadata)
assert.NoError(t, err)
}
func TestMetadataService_ValidateMetadata_MissingTitle(t *testing.T) {
service := setupTestMetadataService(t)
metadata := &AudioMetadata{
Title: "",
Artist: "Test Artist",
}
err := service.ValidateMetadata(metadata)
assert.Error(t, err)
assert.Contains(t, err.Error(), "title is required")
}
func TestMetadataService_ValidateMetadata_MissingArtist(t *testing.T) {
service := setupTestMetadataService(t)
metadata := &AudioMetadata{
Title: "Test Title",
Artist: "",
}
err := service.ValidateMetadata(metadata)
assert.Error(t, err)
assert.Contains(t, err.Error(), "artist is required")
}
func TestMetadataService_ValidateMetadata_MissingBoth(t *testing.T) {
service := setupTestMetadataService(t)
metadata := &AudioMetadata{
Title: "",
Artist: "",
}
err := service.ValidateMetadata(metadata)
assert.Error(t, err)
assert.Contains(t, err.Error(), "title is required")
}
func TestMetadataService_getDefaultMetadata_SimpleFilename(t *testing.T) {
service := setupTestMetadataService(t)
filePath := "/path/to/track.mp3"
metadata := service.getDefaultMetadata(filePath)
assert.NotNil(t, metadata)
assert.Equal(t, "track", metadata.Title)
assert.Equal(t, "Unknown", metadata.Artist)
assert.Equal(t, ".mp3", metadata.Format)
assert.Equal(t, "", metadata.Album)
assert.Equal(t, "", metadata.Genre)
assert.Equal(t, 0, metadata.Year)
assert.Equal(t, 0, metadata.Track)
}
func TestMetadataService_getDefaultMetadata_WithExtension(t *testing.T) {
service := setupTestMetadataService(t)
testCases := []struct {
name string
filePath string
expected string
}{
{"MP3", "/path/to/song.mp3", ".mp3"},
{"FLAC", "/path/to/song.flac", ".flac"},
{"WAV", "/path/to/song.wav", ".wav"},
{"M4A", "/path/to/song.m4a", ".m4a"},
{"OGG", "/path/to/song.ogg", ".ogg"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
metadata := service.getDefaultMetadata(tc.filePath)
assert.Equal(t, tc.expected, metadata.Format)
})
}
}
func TestMetadataService_getDefaultMetadata_ComplexFilename(t *testing.T) {
service := setupTestMetadataService(t)
filePath := "/path/to/Artist - Song Title (Remix).mp3"
metadata := service.getDefaultMetadata(filePath)
assert.NotNil(t, metadata)
// The current implementation doesn't properly parse "Artist - Title" pattern
// but it should still extract the filename
assert.Contains(t, metadata.Title, "Artist")
}
func TestMetadataService_getDefaultMetadata_NoExtension(t *testing.T) {
service := setupTestMetadataService(t)
filePath := "/path/to/track"
metadata := service.getDefaultMetadata(filePath)
assert.NotNil(t, metadata)
assert.Equal(t, "track", metadata.Title)
assert.Equal(t, "", metadata.Format)
}
func TestMetadataService_ExtractMetadata_NonExistentFile(t *testing.T) {
service := setupTestMetadataService(t)
filePath := "/nonexistent/path/to/file.mp3"
metadata, err := service.ExtractMetadata(filePath)
assert.Error(t, err)
assert.Nil(t, metadata)
assert.Contains(t, err.Error(), "failed to open file")
}
func TestMetadataService_ExtractMetadata_InvalidFile(t *testing.T) {
service := setupTestMetadataService(t)
// Create a temporary file that's not a valid audio file
tmpFile, err := os.CreateTemp("", "test_*.txt")
require.NoError(t, err)
defer os.Remove(tmpFile.Name())
defer tmpFile.Close()
_, err = tmpFile.WriteString("This is not an audio file")
require.NoError(t, err)
tmpFile.Close()
// ExtractMetadata should handle invalid files gracefully
metadata, err := service.ExtractMetadata(tmpFile.Name())
// Should return default metadata instead of error
assert.NoError(t, err)
assert.NotNil(t, metadata)
assert.Equal(t, filepath.Ext(tmpFile.Name()), metadata.Format)
}
func TestMetadataService_ExtractMetadata_EmptyFile(t *testing.T) {
service := setupTestMetadataService(t)
// Create an empty temporary file
tmpFile, err := os.CreateTemp("", "test_*.mp3")
require.NoError(t, err)
defer os.Remove(tmpFile.Name())
tmpFile.Close()
// ExtractMetadata should handle empty files gracefully
metadata, err := service.ExtractMetadata(tmpFile.Name())
// Should return default metadata instead of error
assert.NoError(t, err)
assert.NotNil(t, metadata)
assert.Equal(t, ".mp3", metadata.Format)
}
func TestMetadataService_AudioMetadata_Fields(t *testing.T) {
metadata := &AudioMetadata{
Title: "Test Title",
Artist: "Test Artist",
Album: "Test Album",
Genre: "Rock",
Year: 2023,
Track: 1,
Duration: 180.5,
Bitrate: 320,
Format: ".mp3",
}
assert.Equal(t, "Test Title", metadata.Title)
assert.Equal(t, "Test Artist", metadata.Artist)
assert.Equal(t, "Test Album", metadata.Album)
assert.Equal(t, "Rock", metadata.Genre)
assert.Equal(t, 2023, metadata.Year)
assert.Equal(t, 1, metadata.Track)
assert.Equal(t, 180.5, metadata.Duration)
assert.Equal(t, 320, metadata.Bitrate)
assert.Equal(t, ".mp3", metadata.Format)
}
func TestMetadataService_getDefaultMetadata_PathVariations(t *testing.T) {
service := setupTestMetadataService(t)
testCases := []struct {
name string
filePath string
expectedTitle string
}{
{"Unix path", "/home/user/music/song.mp3", "song"},
{"Windows path", filepath.Join("C:", "Users", "Music", "song.mp3"), "song"},
{"Relative path", "./music/song.mp3", "song"},
{"Filename only", "song.mp3", "song"},
{"Nested path", "/very/deep/nested/path/to/song.mp3", "song"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
metadata := service.getDefaultMetadata(tc.filePath)
// Use filepath.Base to get the expected filename regardless of OS
expectedBase := filepath.Base(tc.filePath)
expectedTitle := expectedBase[:len(expectedBase)-len(filepath.Ext(expectedBase))]
assert.Equal(t, expectedTitle, metadata.Title)
})
}
}