diff --git a/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioBitDepthSpecificationFixture.cs b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioBitDepthSpecificationFixture.cs new file mode 100644 index 000000000..f1ae1f8d4 --- /dev/null +++ b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioBitDepthSpecificationFixture.cs @@ -0,0 +1,127 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.CustomFormats.Specifications +{ + [TestFixture] + public class AudioBitDepthSpecificationFixture : CoreTest + { + private CustomFormatInput _input; + + [SetUp] + public void Setup() + { + _input = new CustomFormatInput + { + AlbumInfo = new ParsedAlbumInfo(), + MediaInfo = new MediaInfoModel() + }; + } + + [TestCase(16, 16, 24, true)] + [TestCase(24, 16, 24, true)] + [TestCase(24, 24, 32, true)] + [TestCase(32, 24, 32, true)] + [TestCase(16, 24, 32, false)] + [TestCase(32, 0, 24, false)] + [TestCase(0, 16, 24, false)] + public void should_match_bit_depth_range(int bitDepth, int min, int max, bool expected) + { + _input.MediaInfo.AudioBits = bitDepth; + + var spec = new AudioBitDepthSpecification + { + Min = min, + Max = max + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_not_match_when_media_info_is_null() + { + _input.MediaInfo = null; + + var spec = new AudioBitDepthSpecification + { + Min = 16, + Max = 24 + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [TestCase(16, 16, 24, false)] + [TestCase(24, 16, 24, false)] + [TestCase(16, 24, 32, true)] + public void should_match_negated_bit_depth_range(int bitDepth, int min, int max, bool expected) + { + _input.MediaInfo.AudioBits = bitDepth; + + var spec = new AudioBitDepthSpecification + { + Min = min, + Max = max, + Negate = true + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_be_valid_when_min_is_zero() + { + var spec = new AudioBitDepthSpecification + { + Min = 0, + Max = 24 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_valid_when_max_equals_min() + { + var spec = new AudioBitDepthSpecification + { + Min = 24, + Max = 24 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_invalid_when_max_is_less_than_min() + { + var spec = new AudioBitDepthSpecification + { + Min = 24, + Max = 16 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + + [Test] + public void should_be_invalid_when_min_is_negative() + { + var spec = new AudioBitDepthSpecification + { + Min = -1, + Max = 24 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + } +} diff --git a/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioBitrateSpecificationFixture.cs b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioBitrateSpecificationFixture.cs new file mode 100644 index 000000000..15c38a196 --- /dev/null +++ b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioBitrateSpecificationFixture.cs @@ -0,0 +1,127 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.CustomFormats.Specifications +{ + [TestFixture] + public class AudioBitrateSpecificationFixture : CoreTest + { + private CustomFormatInput _input; + + [SetUp] + public void Setup() + { + _input = new CustomFormatInput + { + AlbumInfo = new ParsedAlbumInfo(), + MediaInfo = new MediaInfoModel() + }; + } + + [TestCase(320, 256, 320, true)] + [TestCase(256, 192, 320, true)] + [TestCase(128, 128, 256, true)] + [TestCase(1411, 1000, 1500, true)] + [TestCase(96, 128, 320, false)] + [TestCase(320, 0, 256, false)] + [TestCase(0, 128, 320, false)] + public void should_match_bitrate_range(int bitrate, int min, int max, bool expected) + { + _input.MediaInfo.AudioBitrate = bitrate; + + var spec = new AudioBitrateSpecification + { + Min = min, + Max = max + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_not_match_when_media_info_is_null() + { + _input.MediaInfo = null; + + var spec = new AudioBitrateSpecification + { + Min = 128, + Max = 320 + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [TestCase(320, 256, 320, false)] + [TestCase(256, 192, 320, false)] + [TestCase(96, 128, 320, true)] + public void should_match_negated_bitrate_range(int bitrate, int min, int max, bool expected) + { + _input.MediaInfo.AudioBitrate = bitrate; + + var spec = new AudioBitrateSpecification + { + Min = min, + Max = max, + Negate = true + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_be_valid_when_min_is_zero() + { + var spec = new AudioBitrateSpecification + { + Min = 0, + Max = 320 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_valid_when_max_equals_min() + { + var spec = new AudioBitrateSpecification + { + Min = 320, + Max = 320 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_invalid_when_max_is_less_than_min() + { + var spec = new AudioBitrateSpecification + { + Min = 320, + Max = 256 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + + [Test] + public void should_be_invalid_when_min_is_negative() + { + var spec = new AudioBitrateSpecification + { + Min = -1, + Max = 320 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + } +} diff --git a/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioChannelsSpecificationFixture.cs b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioChannelsSpecificationFixture.cs new file mode 100644 index 000000000..e35e1c7ae --- /dev/null +++ b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioChannelsSpecificationFixture.cs @@ -0,0 +1,127 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.CustomFormats.Specifications +{ + [TestFixture] + public class AudioChannelsSpecificationFixture : CoreTest + { + private CustomFormatInput _input; + + [SetUp] + public void Setup() + { + _input = new CustomFormatInput + { + AlbumInfo = new ParsedAlbumInfo(), + MediaInfo = new MediaInfoModel() + }; + } + + [TestCase(2, 2, 2, true)] + [TestCase(2, 1, 2, true)] + [TestCase(6, 2, 8, true)] + [TestCase(8, 6, 8, true)] + [TestCase(1, 2, 6, false)] + [TestCase(8, 0, 6, false)] + [TestCase(0, 2, 6, false)] + public void should_match_channels_range(int channels, int min, int max, bool expected) + { + _input.MediaInfo.AudioChannels = channels; + + var spec = new AudioChannelsSpecification + { + Min = min, + Max = max + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_not_match_when_media_info_is_null() + { + _input.MediaInfo = null; + + var spec = new AudioChannelsSpecification + { + Min = 2, + Max = 6 + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [TestCase(2, 2, 2, false)] + [TestCase(2, 1, 2, false)] + [TestCase(1, 2, 6, true)] + public void should_match_negated_channels_range(int channels, int min, int max, bool expected) + { + _input.MediaInfo.AudioChannels = channels; + + var spec = new AudioChannelsSpecification + { + Min = min, + Max = max, + Negate = true + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_be_valid_when_min_is_zero() + { + var spec = new AudioChannelsSpecification + { + Min = 0, + Max = 6 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_valid_when_max_equals_min() + { + var spec = new AudioChannelsSpecification + { + Min = 2, + Max = 2 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_invalid_when_max_is_less_than_min() + { + var spec = new AudioChannelsSpecification + { + Min = 6, + Max = 2 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + + [Test] + public void should_be_invalid_when_min_is_negative() + { + var spec = new AudioChannelsSpecification + { + Min = -1, + Max = 6 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + } +} diff --git a/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioCodecSpecificationFixture.cs b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioCodecSpecificationFixture.cs new file mode 100644 index 000000000..63458573f --- /dev/null +++ b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioCodecSpecificationFixture.cs @@ -0,0 +1,179 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.CustomFormats.Specifications +{ + [TestFixture] + public class AudioCodecSpecificationFixture : CoreTest + { + private CustomFormatInput _input; + + [SetUp] + public void Setup() + { + _input = new CustomFormatInput + { + AlbumInfo = new ParsedAlbumInfo(), + MediaInfo = new MediaInfoModel() + }; + } + + [TestCase("FLAC", "FLAC", true)] + [TestCase("MP3", "MP3", true)] + [TestCase("AAC", "AAC", true)] + [TestCase("ALAC", "ALAC", true)] + [TestCase("OPUS", "OPUS", true)] + [TestCase("WavPack", "WavPack", true)] + [TestCase("APE", "APE", true)] + [TestCase("FLAC", "MP3", false)] + [TestCase("MP3", "FLAC", false)] + public void should_match_codec_exact(string actualCodec, string pattern, bool expected) + { + _input.MediaInfo.AudioFormat = actualCodec; + + var spec = new AudioCodecSpecification + { + Value = pattern + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [TestCase("FLAC", "flac", true)] + [TestCase("mp3", "MP3", true)] + [TestCase("AAC", "aac", true)] + public void should_match_codec_case_insensitive(string actualCodec, string pattern, bool expected) + { + _input.MediaInfo.AudioFormat = actualCodec; + + var spec = new AudioCodecSpecification + { + Value = pattern + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [TestCase("FLAC", "FLAC|MP3", true)] + [TestCase("MP3", "FLAC|MP3", true)] + [TestCase("AAC", "FLAC|MP3", false)] + [TestCase("ALAC", "ALAC|OPUS|WavPack", true)] + public void should_match_codec_regex(string actualCodec, string pattern, bool expected) + { + _input.MediaInfo.AudioFormat = actualCodec; + + var spec = new AudioCodecSpecification + { + Value = pattern + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_not_match_when_media_info_is_null() + { + _input.MediaInfo = null; + + var spec = new AudioCodecSpecification + { + Value = "FLAC" + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [Test] + public void should_not_match_when_audio_format_is_null() + { + _input.MediaInfo.AudioFormat = null; + + var spec = new AudioCodecSpecification + { + Value = "FLAC" + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [Test] + public void should_not_match_when_audio_format_is_empty() + { + _input.MediaInfo.AudioFormat = string.Empty; + + var spec = new AudioCodecSpecification + { + Value = "FLAC" + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [TestCase("FLAC", "FLAC", false)] + [TestCase("MP3", "MP3", false)] + [TestCase("FLAC", "MP3", true)] + public void should_match_negated_codec(string actualCodec, string pattern, bool expected) + { + _input.MediaInfo.AudioFormat = actualCodec; + + var spec = new AudioCodecSpecification + { + Value = pattern, + Negate = true + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_be_valid_when_value_is_set() + { + var spec = new AudioCodecSpecification + { + Value = "FLAC" + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_invalid_when_value_is_empty() + { + var spec = new AudioCodecSpecification + { + Value = string.Empty + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + + [Test] + public void should_be_invalid_when_value_is_whitespace() + { + var spec = new AudioCodecSpecification + { + Value = " " + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + + [Test] + public void should_be_invalid_when_value_is_null() + { + var spec = new AudioCodecSpecification + { + Value = null + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + } +} diff --git a/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioSampleRateSpecificationFixture.cs b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioSampleRateSpecificationFixture.cs new file mode 100644 index 000000000..501dab69f --- /dev/null +++ b/src/NzbDrone.Core.Test/CustomFormats/Specifications/AudioSampleRateSpecificationFixture.cs @@ -0,0 +1,127 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.CustomFormats; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.CustomFormats.Specifications +{ + [TestFixture] + public class AudioSampleRateSpecificationFixture : CoreTest + { + private CustomFormatInput _input; + + [SetUp] + public void Setup() + { + _input = new CustomFormatInput + { + AlbumInfo = new ParsedAlbumInfo(), + MediaInfo = new MediaInfoModel() + }; + } + + [TestCase(44100, 40000, 48000, true)] + [TestCase(48000, 40000, 50000, true)] + [TestCase(96000, 88200, 192000, true)] + [TestCase(192000, 176400, 192000, true)] + [TestCase(44100, 48000, 96000, false)] + [TestCase(192000, 0, 96000, false)] + [TestCase(0, 44100, 96000, false)] + public void should_match_sample_rate_range(int sampleRate, int min, int max, bool expected) + { + _input.MediaInfo.AudioSampleRate = sampleRate; + + var spec = new AudioSampleRateSpecification + { + Min = min, + Max = max + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_not_match_when_media_info_is_null() + { + _input.MediaInfo = null; + + var spec = new AudioSampleRateSpecification + { + Min = 44100, + Max = 48000 + }; + + spec.IsSatisfiedBy(_input).Should().BeFalse(); + } + + [TestCase(44100, 40000, 48000, false)] + [TestCase(48000, 40000, 50000, false)] + [TestCase(44100, 48000, 96000, true)] + public void should_match_negated_sample_rate_range(int sampleRate, int min, int max, bool expected) + { + _input.MediaInfo.AudioSampleRate = sampleRate; + + var spec = new AudioSampleRateSpecification + { + Min = min, + Max = max, + Negate = true + }; + + spec.IsSatisfiedBy(_input).Should().Be(expected); + } + + [Test] + public void should_be_valid_when_min_is_zero() + { + var spec = new AudioSampleRateSpecification + { + Min = 0, + Max = 48000 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_valid_when_max_equals_min() + { + var spec = new AudioSampleRateSpecification + { + Min = 44100, + Max = 44100 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeTrue(); + } + + [Test] + public void should_be_invalid_when_max_is_less_than_min() + { + var spec = new AudioSampleRateSpecification + { + Min = 48000, + Max = 44100 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + + [Test] + public void should_be_invalid_when_min_is_negative() + { + var spec = new AudioSampleRateSpecification + { + Min = -1, + Max = 48000 + }; + + var result = spec.Validate(); + result.IsValid.Should().BeFalse(); + } + } +} diff --git a/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/UpgradeSpecificationFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/UpgradeSpecificationFixture.cs index 557596f74..4a982a327 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/UpgradeSpecificationFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/TrackImport/Specifications/UpgradeSpecificationFixture.cs @@ -1,8 +1,11 @@ +using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; +using Moq; using NUnit.Framework; using NzbDrone.Core.Configuration; +using NzbDrone.Core.CustomFormats; using NzbDrone.Core.Datastore; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.TrackImport.Specifications; @@ -10,6 +13,7 @@ using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Profiles.Qualities; using NzbDrone.Core.Qualities; +using NzbDrone.Core.Test.CustomFormats; using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test.MediaFiles.TrackImport.Specifications @@ -20,14 +24,22 @@ public class UpgradeSpecificationFixture : CoreTest private Artist _artist; private Album _album; private LocalTrack _localTrack; + private CustomFormat _customFormat1; + private CustomFormat _customFormat2; [SetUp] public void Setup() { + _customFormat1 = new CustomFormat("My Format", new ReleaseTitleSpecification()) { Id = 1 }; + _customFormat2 = new CustomFormat("My Other Format", new ReleaseTitleSpecification()) { Id = 2 }; + + CustomFormatsTestHelpers.GivenCustomFormats(_customFormat1, _customFormat2); + _artist = Builder.CreateNew() .With(e => e.QualityProfile = new QualityProfile { Items = Qualities.QualityFixture.GetDefaultQualities(), + FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_customFormat1.Name, _customFormat2.Name) }).Build(); _album = Builder.CreateNew().Build(); @@ -236,5 +248,142 @@ public void should_return_true_if_track_file_is_null() Subject.IsSatisfiedBy(_localTrack, null).Accepted.Should().BeTrue(); } + + [Test] + public void should_return_false_if_custom_format_score_is_lower() + { + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny())) + .Returns(new List()); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny(), It.IsAny())) + .Returns(new List { _customFormat1 }); + + _localTrack.Tracks = Builder.CreateListOfSize(1) + .All() + .With(e => e.TrackFileId = 1) + .With(e => e.TrackFile = new LazyLoaded( + new TrackFile + { + Quality = new QualityModel(Quality.MP3_256, new Revision(version: 1)) + })) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localTrack, null).Accepted.Should().BeFalse(); + } + + [Test] + public void should_return_true_if_custom_format_score_is_higher() + { + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny())) + .Returns(new List { _customFormat1 }); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny(), It.IsAny())) + .Returns(new List()); + + _localTrack.Tracks = Builder.CreateListOfSize(1) + .All() + .With(e => e.TrackFileId = 1) + .With(e => e.TrackFile = new LazyLoaded( + new TrackFile + { + Quality = new QualityModel(Quality.MP3_256, new Revision(version: 1)) + })) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localTrack, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_true_if_custom_format_score_is_equal_and_does_not_prefer_propers() + { + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.DoNotPrefer); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny())) + .Returns(new List { _customFormat1 }); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny(), It.IsAny())) + .Returns(new List { _customFormat1 }); + + _localTrack.Tracks = Builder.CreateListOfSize(1) + .All() + .With(e => e.TrackFileId = 1) + .With(e => e.TrackFile = new LazyLoaded( + new TrackFile + { + Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) + })) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localTrack, null).Accepted.Should().BeTrue(); + } + + [Test] + public void should_return_false_if_custom_format_score_is_equal_and_not_a_revision_upgrade() + { + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.PreferAndUpgrade); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny())) + .Returns(new List { _customFormat1 }); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny(), It.IsAny())) + .Returns(new List { _customFormat1 }); + + _localTrack.Tracks = Builder.CreateListOfSize(1) + .All() + .With(e => e.TrackFileId = 1) + .With(e => e.TrackFile = new LazyLoaded( + new TrackFile + { + Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) + })) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localTrack, null).Accepted.Should().BeFalse(); + } + + [Test] + public void should_return_true_if_custom_formats_are_better_even_with_lower_revision() + { + Mocker.GetMock() + .Setup(s => s.DownloadPropersAndRepacks) + .Returns(ProperDownloadTypes.PreferAndUpgrade); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny())) + .Returns(new List { _customFormat1, _customFormat2 }); + + Mocker.GetMock() + .Setup(s => s.ParseCustomFormat(It.IsAny(), It.IsAny())) + .Returns(new List { _customFormat1 }); + + _localTrack.Tracks = Builder.CreateListOfSize(1) + .All() + .With(e => e.TrackFileId = 1) + .With(e => e.TrackFile = new LazyLoaded( + new TrackFile + { + Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)) + })) + .Build() + .ToList(); + + Subject.IsSatisfiedBy(_localTrack, null).Accepted.Should().BeTrue(); + } } } diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 531cbc38d..ba4d2e51a 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -143,6 +143,16 @@ "AuthenticationRequiredWarning": "To prevent remote access without authentication, {appName} now requires authentication to be enabled. You can optionally disable authentication from local addresses.", "Auto": "Auto", "AutoAdd": "Auto Add", + "AudioBitDepth": "Audio Bit Depth", + "AudioBitDepthHelpText": "The bit depth of the audio (e.g., 16 for CD quality, 24 for Hi-Res)", + "AudioBitrate": "Audio Bitrate", + "AudioBitrateHelpText": "The bitrate of the audio in kbps (e.g., 320 for MP3)", + "AudioChannels": "Audio Channels", + "AudioChannelsHelpText": "The number of audio channels (e.g., 2 for stereo, 6 for 5.1)", + "AudioCodec": "Audio Codec", + "AudioCodecHelpText": "The audio codec name or regex pattern (e.g., FLAC, MP3, AAC)", + "AudioSampleRate": "Audio Sample Rate", + "AudioSampleRateHelpText": "The sample rate of the audio in Hz (e.g., 44100 for CD quality, 192000 for Hi-Res)", "AutoRedownloadFailed": "Redownload Failed", "AutoRedownloadFailedFromInteractiveSearch": "Redownload Failed from Interactive Search", "AutoRedownloadFailedFromInteractiveSearchHelpText": "Automatically search for and attempt to download a different release when failed release was grabbed from interactive search",