"""Unit tests for AudioContent value object.""" import pytest from src.domain.models.audio_content import AudioContent class TestAudioContent: """Test cases for AudioContent value object.""" def test_valid_audio_content_creation(self): """Test creating valid AudioContent instance.""" audio_data = b"fake_audio_data" audio = AudioContent( data=audio_data, format="wav", sample_rate=44100, duration=10.5, filename="test.wav" ) assert audio.data == audio_data assert audio.format == "wav" assert audio.sample_rate == 44100 assert audio.duration == 10.5 assert audio.filename == "test.wav" assert audio.size_bytes == len(audio_data) assert audio.is_valid_format is True def test_audio_content_without_filename(self): """Test creating AudioContent without filename.""" audio = AudioContent( data=b"fake_audio_data", format="mp3", sample_rate=22050, duration=5.0 ) assert audio.filename is None assert audio.format == "mp3" def test_empty_audio_data_raises_error(self): """Test that empty audio data raises ValueError.""" with pytest.raises(ValueError, match="Audio data cannot be empty"): AudioContent( data=b"", format="wav", sample_rate=44100, duration=10.0 ) def test_non_bytes_audio_data_raises_error(self): """Test that non-bytes audio data raises TypeError.""" with pytest.raises(TypeError, match="Audio data must be bytes"): AudioContent( data="not_bytes", # type: ignore format="wav", sample_rate=44100, duration=10.0 ) def test_unsupported_format_raises_error(self): """Test that unsupported format raises ValueError.""" with pytest.raises(ValueError, match="Unsupported audio format: xyz"): AudioContent( data=b"fake_audio_data", format="xyz", sample_rate=44100, duration=10.0 ) def test_supported_formats(self): """Test all supported audio formats.""" supported_formats = ['wav', 'mp3', 'flac', 'ogg'] for fmt in supported_formats: audio = AudioContent( data=b"fake_audio_data", format=fmt, sample_rate=44100, duration=10.0 ) assert audio.format == fmt assert audio.is_valid_format is True def test_negative_sample_rate_raises_error(self): """Test that negative sample rate raises ValueError.""" with pytest.raises(ValueError, match="Sample rate must be positive"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=-1, duration=10.0 ) def test_zero_sample_rate_raises_error(self): """Test that zero sample rate raises ValueError.""" with pytest.raises(ValueError, match="Sample rate must be positive"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=0, duration=10.0 ) def test_sample_rate_too_low_raises_error(self): """Test that sample rate below 8000 raises ValueError.""" with pytest.raises(ValueError, match="Sample rate must be between 8000 and 192000 Hz"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=7999, duration=10.0 ) def test_sample_rate_too_high_raises_error(self): """Test that sample rate above 192000 raises ValueError.""" with pytest.raises(ValueError, match="Sample rate must be between 8000 and 192000 Hz"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=192001, duration=10.0 ) def test_valid_sample_rate_boundaries(self): """Test valid sample rate boundaries.""" # Test minimum valid sample rate audio_min = AudioContent( data=b"fake_audio_data", format="wav", sample_rate=8000, duration=10.0 ) assert audio_min.sample_rate == 8000 # Test maximum valid sample rate audio_max = AudioContent( data=b"fake_audio_data", format="wav", sample_rate=192000, duration=10.0 ) assert audio_max.sample_rate == 192000 def test_negative_duration_raises_error(self): """Test that negative duration raises ValueError.""" with pytest.raises(ValueError, match="Duration must be positive"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=-1.0 ) def test_zero_duration_raises_error(self): """Test that zero duration raises ValueError.""" with pytest.raises(ValueError, match="Duration must be positive"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=0.0 ) def test_duration_too_long_raises_error(self): """Test that duration over 1 hour raises ValueError.""" with pytest.raises(ValueError, match="Audio duration cannot exceed 1 hour"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=3601.0 # 1 hour + 1 second ) def test_valid_duration_boundary(self): """Test valid duration boundary (exactly 1 hour).""" audio = AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=3600.0 # Exactly 1 hour ) assert audio.duration == 3600.0 def test_empty_filename_raises_error(self): """Test that empty filename raises ValueError.""" with pytest.raises(ValueError, match="Filename cannot be empty string"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=10.0, filename="" ) def test_whitespace_filename_raises_error(self): """Test that whitespace-only filename raises ValueError.""" with pytest.raises(ValueError, match="Filename cannot be empty string"): AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=10.0, filename=" " ) def test_audio_content_is_immutable(self): """Test that AudioContent is immutable (frozen dataclass).""" audio = AudioContent( data=b"fake_audio_data", format="wav", sample_rate=44100, duration=10.0 ) with pytest.raises(AttributeError): audio.format = "mp3" # type: ignore def test_size_bytes_property(self): """Test size_bytes property returns correct value.""" test_data = b"test_audio_data_123" audio = AudioContent( data=test_data, format="wav", sample_rate=44100, duration=10.0 ) assert audio.size_bytes == len(test_data)