public void ApplyEnhancements_DuplicateEnhancementRequestsMade_OnlyUniqueResultsAddedToIdentity(
            string filePath,
            TvReleaseIdentity identity,
            TvDbEnhancement tvDbEnhancement,
            SubDbFileHashEnhancement subDbFileHashEnhancement,
            IEpisodeSubtitleDownloader downloader,
            IEnhancementProvider enhancementProvider
            )
        {
            var expectedEnhancements = new IEnhancement[] {tvDbEnhancement, subDbFileHashEnhancement};
            var downloaders = new[] {downloader};
            var enhancementRequests = new IEnhancementRequest[]
            {
                new EnhancementRequest<TvDbEnhancement>(),
                new EnhancementRequest<TvDbEnhancement>(),
                new EnhancementRequest<SubDbFileHashEnhancement>()
            };
            A.CallTo(() => downloader.EnhancementRequests).Returns(enhancementRequests);
            A.CallTo(
                () =>
                    enhancementProvider.GetEnhancement(A<Type>.That.IsEqualTo(typeof (TvDbEnhancement)), filePath,
                        identity))
                .Returns(tvDbEnhancement);
            A.CallTo(
                () =>
                    enhancementProvider.GetEnhancement(A<Type>.That.IsEqualTo(typeof (SubDbFileHashEnhancement)),
                        filePath, identity))
                .Returns(subDbFileHashEnhancement);
            var sut = new EnhancementApplicator(downloaders, enhancementProvider);

            sut.ApplyEnhancements(filePath, identity);

            Assert.That(identity.Enhancements, Is.EquivalentTo(expectedEnhancements));
        }
 public bool Equals(TvReleaseIdentity other)
 {
     if (ReferenceEquals(null, other)) return false;
     if (ReferenceEquals(this, other)) return true;
     return string.Equals(other.SeriesName, SeriesName, StringComparison.OrdinalIgnoreCase)
         && other.Season == Season
         && string.Equals(other.ReleaseGroup, ReleaseGroup, StringComparison.OrdinalIgnoreCase)
         && other.Episode == Episode && other.EndEpisode == EndEpisode;
 }
        public void FilterOutSubtitlesNotMatching_SomeMatching_AllMatchingAreLeft(
            IEnumerable<Subtitle> subtitles, 
            TvReleaseIdentity identity,
            [Frozen]IEpisodeParser parser,
            SubtitleMatcher sut)
        {
            var matching = subtitles.Take(2);
            A.CallTo(() => parser.ExtractReleaseIdentity(A<Subtitle>.That.Matches(s => matching.Contains(s))))
                .Returns(identity);

            var results = sut.FilterOutSubtitlesNotMatching(subtitles, identity);

            Assert.That(results.Select(r => r.Id), Is.EquivalentTo(matching.Select(s => s.Id)));
        }
        public void ProcessFile_CannotParseName_ReturnsTrue(
            string fileName,
            string[] ignored,
            TvReleaseIdentity tvRelease,
            [Frozen] IEpisodeParser episodeParser,
            FileProcessor sut)
        {
            var emptyEpisode = new TvReleaseIdentity();
            A.CallTo(() => episodeParser.ParseEpisodeInfo(fileName)).Returns(emptyEpisode);

            bool result = sut.ProcessFile(fileName, ignored);

            Assert.That(result, Is.True);
        }
        public void ProcessFile_CannotParseName_IsNotDownloaded(
            string fileName,
            string[] ignored,
            TvReleaseIdentity tvRelease,
            [Frozen] IEpisodeParser episodeParser,
            [Frozen] ISubtitleDownloadService subtitleService,
            FileProcessor sut)
        {
            var emptyEpisode = new TvReleaseIdentity();
            A.CallTo(() => episodeParser.ParseEpisodeInfo(fileName)).Returns(emptyEpisode);

            sut.ProcessFile(fileName, ignored);

            A.CallTo(() => subtitleService.DownloadSubtitle(A<string>._, A<TvReleaseIdentity>._, A<IEnumerable<Language>>._)).MustNotHaveHappened();
        }
        public void ExtractReleaseIdentity_SubtitleWithAllProperties_ReleaseIdentityMatches(
            Subtitle subtitle,
            EpisodeParser sut)
        {
            var expected = new TvReleaseIdentity
            {
                SeriesName = subtitle.SeriesName,
                Season = subtitle.Season.Value,
                Episode = subtitle.Episode.Value,
                EndEpisode = subtitle.EndEpisode.Value,
                ReleaseGroup = subtitle.ReleaseGroup
            };
            var result = sut.ExtractReleaseIdentity(subtitle);

            Assert.That(result, Is.EqualTo(expected));
        }
        public void ApplyEnhancements_EnhancementRequestsMade_ResultsAddedToIdentity(
            string filePath,
            TvReleaseIdentity identity,
            IEnumerable<IEnhancementRequest> enhancementRequests,
            IEnhancement[] enhancements,
            IEpisodeSubtitleDownloader downloader,
            IEnhancementProvider enhancementProvider
            )
        {
            var downloaders = new[] {downloader};
            A.CallTo(() => downloader.EnhancementRequests).Returns(enhancementRequests);
            A.CallTo(() => enhancementProvider.GetEnhancement(A<Type>._, filePath, identity))
                .ReturnsNextFromSequence(enhancements);
            var sut = new EnhancementApplicator(downloaders, enhancementProvider);

            sut.ApplyEnhancements(filePath, identity);

            Assert.That(identity.Enhancements, Is.EquivalentTo(enhancements));
        }
        public void DownloadSubtitle_MatchingSubtitlesDownloaderFails_ShouldReturnFalse(
            string file,
            Language[] languages,
            TvReleaseIdentity identity,
            Subtitle[] matches,
            Language language,
            ISubtitleRanker subtitleRanker,
            IEnhancementProvider enhancementProvider,
            [Frozen]IEpisodeSubtitleDownloader fakeDownloader)
        {
            A.CallTo(() => fakeDownloader.SearchSubtitle(A<TvReleaseIdentity>._, A<Language[]>._)).Returns(matches);
            A.CallTo(() => fakeDownloader.TryDownloadSubtitle(A<Subtitle>._, A<string>._)).Returns(false);
            A.CallTo(() => fakeDownloader.CanHandleAtLeastOneOf(A<Language[]>._)).Returns(true);
            var downloaders = new[] { fakeDownloader };
            var service = new SubtitleDownloadService(downloaders, enhancementProvider, subtitleRanker);

            bool success = service.DownloadSubtitle(file, identity, languages);

            Assert.That(success, Is.False);
        }
        public void SearchSubtitle_MultipleValidSubtitlesFound_OrderedByLanguagePriority(
            TvReleaseIdentity tvReleaseIdentity,
            string id,
            string fileName,
            Language[] expectedLanguages,
            Language missingLanguage,
            [Frozen]IEpisodeParser nameParser,
            [Frozen]ISubtitleDownloader downloader,
            SubtitleDownloaderWrapper downloaderWrapper
            )
        {
            var subtitles = expectedLanguages.Select(l => new Subtitle(id, fileName, l));
            A.CallTo(() => downloader.SearchSubtitles(A<SearchQuery>._)).Returns(subtitles);
            A.CallTo(() => nameParser.ExtractReleaseIdentity(A<Subtitle>._)).Returns(tvReleaseIdentity);
            var languages = new [] { expectedLanguages[0], missingLanguage, expectedLanguages[1], expectedLanguages[2] };

            var results = downloaderWrapper.SearchSubtitle(tvReleaseIdentity, languages);

            Assert.That(results.Select(s => s.Language), Is.EquivalentTo(expectedLanguages));
        }
        public void ProcessFile_AllLanguagesAlreadyDownloaded_ReturnsTrue( 
            Language[] languages,
            string fileName,
            TvReleaseIdentity tvRelease,
            ILogger logger,
            IEpisodeParser episodeParser,
            ISubtitleDownloadService subtitleService,
            [Frozen]IFileOperations fileOperations,
            FileProcessor sut)
        {
            var settings = new LanguageSettings(languages);
            A.CallTo(() => fileOperations.GetDowloadedSubtitleLanguages(A<string>._, languages)).Returns(languages);
            A.CallTo(() => subtitleService.DownloadSubtitle(A<string>._, A<TvReleaseIdentity>._, A<IEnumerable<Language>>._))
                .Returns(false);
            A.CallTo(() => episodeParser.ParseEpisodeInfo(A<string>._)).Returns(tvRelease);
            var processor = new FileProcessor(episodeParser, logger, subtitleService, fileOperations, settings);

            bool result = processor.ProcessFile(fileName, new string[0]);

            Assert.That(result, Is.True);
        }
        public void ExtractReleaseIdentity_SubtitleWithAllNullValues_ReleaseIdentityMatches(
            Subtitle subtitle,
            EpisodeParser sut)
        {
            subtitle.SeriesName = null;
            subtitle.ReleaseGroup = null;
            subtitle.Season = null;
            subtitle.Episode = null;
            subtitle.EndEpisode = null;

            var expected = new TvReleaseIdentity
            {
                SeriesName = null,
                Season = 0,
                Episode = 0,
                EndEpisode = 0,
                ReleaseGroup = null
            };
            var result = sut.ExtractReleaseIdentity(subtitle);

            Assert.That(result, Is.EqualTo(expected));
        }
        public void DownloadSubtitle_MatchingSubtitlesDownloaderSucceeds_DownloaderShouldDownloadFirstLanguage(
            string file,
            Subtitle[] matches,
            TvReleaseIdentity identity,
            ISubtitleRanker subtitleRanker,
            IEpisodeSubtitleDownloader fakeDownloader,
            IEnhancementProvider enhancementProvider
            )
        {
            var languages = matches.Skip(1).Select(m => m.Language);
            var expectedLanguage = languages.First();
            A.CallTo(() => fakeDownloader.SearchSubtitle(A<TvReleaseIdentity>._, A<Language[]>._)).Returns(matches);
            A.CallTo(() => fakeDownloader.TryDownloadSubtitle(A<Subtitle>._, A<string>._)).Returns(true);
            A.CallTo(() => fakeDownloader.CanHandleAtLeastOneOf(A<Language[]>._)).Returns(true);
            var downloaders = new[] { fakeDownloader };
            var service = new SubtitleDownloadService(downloaders, enhancementProvider, subtitleRanker);

            service.DownloadSubtitle(file, identity, languages);

            A.CallTo(() => fakeDownloader.TryDownloadSubtitle(A<Subtitle>.That.Matches(s => s.Language == expectedLanguage), A<string>._))
                .MustHaveHappened(Repeated.Exactly.Once);
        }
        public void DownloadSubtitle_DownloaderHasEnhancementRequests_ProvidesEnhancements(
            SubDbFileHashEnhancement enhancement,
            string file,
            TvReleaseIdentity identity,
            Subtitle[] matches,
            [Frozen]IEnumerable<IEpisodeSubtitleDownloader> downloaders,
            [Frozen]IEnhancementProvider enhancementProvider,
            SubtitleDownloadService sut
            )
        {
            var languages = matches.Select(m => m.Language);
            var downloaderWithRequest = downloaders.First();
            A.CallTo(() => downloaderWithRequest.CanHandleAtLeastOneOf(A<Language[]>._)).Returns(true);
            A.CallTo(() => downloaderWithRequest.EnhancementRequests)
                .Returns(new[] {new EnhancementRequest<SubDbFileHashEnhancement>()});
            A.CallTo(() => enhancementProvider.GetEnhancement(typeof(SubDbFileHashEnhancement), file, identity))
                .Returns(enhancement);

            sut.DownloadSubtitle(file, identity, languages);

            A.CallTo(() => downloaderWithRequest.SearchSubtitle(
                A<TvReleaseIdentity>.That.Matches(r => r.Enhancements.Contains(enhancement)),
                A<IEnumerable<Language>>._)).MustHaveHappened();
        }
        public void DownloadSubtitle_SomeDowloadersCantHandleLanguages_OnlyCallsDownloadersThatHandlesLanguages(
            string file,
            TvReleaseIdentity identity,
            Subtitle[] matches,
            [Frozen]IEpisodeSubtitleDownloader[] downloaders,
            SubtitleDownloadService sut
            )
        {
            var expectedDownloader = downloaders.First();
            A.CallTo(() => expectedDownloader.SearchSubtitle(A<TvReleaseIdentity>._, A<Language[]>._)).Returns(matches);
            A.CallTo(() => expectedDownloader.TryDownloadSubtitle(A<Subtitle>._, A<string>._)).Returns(true);
            A.CallTo(() => expectedDownloader.CanHandleAtLeastOneOf(A<Language[]>._)).Returns(true);

            var incapableDownloaders = downloaders.Skip(1).ToArray();
            incapableDownloaders.ForEach(incapableDownloader =>
                A.CallTo(() => incapableDownloader.CanHandleAtLeastOneOf(A<Language[]>._)).Returns(false)
            );

            var languages = matches.Select(m => m.Language);

            sut.DownloadSubtitle(file, identity, languages);

            incapableDownloaders.ForEach(incapableDownloader =>
                A.CallTo(() => incapableDownloader.SearchSubtitle(A<TvReleaseIdentity>._, A<Language[]>._))
                    .MustNotHaveHappened()
            );
        }
 public void IsEquivalent(string name1, string name2, bool expected)
 {
     var id1 = new TvReleaseIdentity { SeriesName = name1 };
     var id2 = new TvReleaseIdentity { SeriesName = name2 };
     Assert.That(id1.IsEquivalent(id2), Is.EqualTo(expected));
 }
        public void ProcessFile_ShowIsIgnored_DoesNotDownload(
            string fileName,
            string[] ignored,
            TvReleaseIdentity tvRelease,
            [Frozen] IEpisodeParser episodeParser,
            [Frozen] ISubtitleDownloadService subtitleService,
            FileProcessor sut)
        {
            tvRelease.SeriesName = ignored.First();
            A.CallTo(() => episodeParser.ParseEpisodeInfo(fileName)).Returns(tvRelease);

            sut.ProcessFile(fileName, ignored);

            A.CallTo(() => subtitleService.DownloadSubtitle(A<string>._, A<TvReleaseIdentity>._, A<IEnumerable<Language>>._)).MustNotHaveHappened();
        }
        public void ApplyEnhancements_MultipleDownloaders_AllDownloadersRequestsAreUsed(
            string filePath,
            TvReleaseIdentity identity,
            IEnumerable<IEnhancementRequest> enhancementRequests,
            [Frozen]IEnumerable<IEpisodeSubtitleDownloader> downloaders,
            [Frozen]IEnhancementProvider enhancementProvider,
            EnhancementApplicator sut
            )
        {
            var expectedNumberOfCalls = downloaders.Count() * enhancementRequests.Count();
            foreach (var downloader in downloaders)
            {
                A.CallTo(() => downloader.EnhancementRequests).ReturnsNextFromSequence(enhancementRequests);
            }
            sut.ApplyEnhancements(filePath, identity);

            A.CallTo(() => enhancementProvider.GetEnhancement(A<Type>._, A<string>._, A<TvReleaseIdentity>._)).MustHaveHappened(Repeated.Exactly.Times(expectedNumberOfCalls));
        }
        public void ProcessFile_ShowIsIgnored_ReturnsTrue(
            string fileName,
            [Frozen]string[] ignored,
            TvReleaseIdentity tvRelease,
            [Frozen] IEpisodeParser episodeParser,
            FileProcessor sut)
        {
            tvRelease.SeriesName = ignored.First();
            A.CallTo(() => episodeParser.ParseEpisodeInfo(fileName)).Returns(tvRelease);

            bool result = sut.ProcessFile(fileName, ignored);

            Assert.That(result, Is.True);
        }
        public void Parse_ParsableName_PopulatedEpisodeInfo(string name, string seriesName, int season, int episode, int endEpisodeNumber, string releaseGroup)
        {
            var expected = new TvReleaseIdentity {
                SeriesName = seriesName,
                Season = season,
                Episode = episode,
                EndEpisode = endEpisodeNumber,
                ReleaseGroup = releaseGroup
            };
            var parser = new EpisodeParser();

            var info = parser.ParseEpisodeInfo(name);

            Assert.That(info, Is.EqualTo(expected));
        }
        public void ProcessFile_SomeLanguagesAlreadyDownloaded_TriesToDownloadOnlyNotDownloaded(
            string fileName,
            TvReleaseIdentity tvRelease,
            [Frozen]LanguageSettings languageSettings,
            [Frozen]IEpisodeParser episodeParser,
            [Frozen]ISubtitleDownloadService subtitleService,
            [Frozen]IFileOperations fileOperations,
            FileProcessor sut)
        {
            var languages = languageSettings.Languages.ToArray();
            var alreadyDownloadedLanguages = languages.Skip(1);
            var expected = languages.Take(1);
            A.CallTo(() => fileOperations.GetDowloadedSubtitleLanguages(fileName,
                A<IEnumerable<Language>>.That.IsSameSequenceAs(languages)))
               .Returns(alreadyDownloadedLanguages);
            A.CallTo(() => episodeParser.ParseEpisodeInfo(A<string>._)).Returns(tvRelease);

            sut.ProcessFile(fileName, new string[0]);

            A.CallTo(() => subtitleService.DownloadSubtitle(A<string>._, A<TvReleaseIdentity>._, A<Language[]>
                .That.IsSameSequenceAs(expected))).MustHaveHappened();
        }
        public void ProcessFile_DownloadsSuccesfully_ReturnsTrue(
            string fileName,
            string[] ignored,
            TvReleaseIdentity tvRelease,
            [Frozen] IEpisodeParser episodeParser,
            [Frozen] ISubtitleDownloadService subtitleService,
            FileProcessor sut)
        {
            A.CallTo(() => subtitleService.DownloadSubtitle(A<string>._, A<TvReleaseIdentity>._, A<IEnumerable<Language>>._))
                .Returns(true);
            A.CallTo(() => episodeParser.ParseEpisodeInfo(A<string>._)).Returns(tvRelease);

            var result = sut.ProcessFile(fileName, ignored);

            Assert.That(result, Is.True);
        }
        public void SearchSubtitle_ThrowsException_ReturnEmptyResultSet(
            TvReleaseIdentity tvReleaseIdentity,
            Language[] languages,
            [Frozen]ISubtitleDownloader downloader,
            SubtitleDownloaderWrapper downloaderWrapper)
        {
            A.CallTo(() => downloader.SearchSubtitles(A<SearchQuery>._)).Throws<Exception>();

            var results = downloaderWrapper.SearchSubtitle(tvReleaseIdentity, languages);

            Assert.That(results, Is.Empty);
        }
        public bool IsEquivalent(TvReleaseIdentity other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            if (SeriesName == null || other.SeriesName == null) return Equals(other);

            return string.Equals(other.SeriesName.RemoveNonAlphaNumericChars(),  SeriesName.RemoveNonAlphaNumericChars(), StringComparison.OrdinalIgnoreCase)
                && other.Season == Season
                && string.Equals(other.ReleaseGroup, ReleaseGroup, StringComparison.OrdinalIgnoreCase)
                && other.Episode == Episode && other.EndEpisode == EndEpisode;
        }
        public void SearchSubtitle_NonEquivalentSubtitlesFound_OnlyIncludesEquivalent(
            TvReleaseIdentity tvReleaseIdentity,
            string id,
            string programName,
            Language[] supportedLanguages,
            string otherShow,
            [Frozen]IEpisodeParser nameParser,
            [Frozen]ISubtitleDownloader downloader,
            SubtitleDownloaderWrapper downloaderWrapper)
        {
            var anyOfTheSupportedLanguages = supportedLanguages.First();
            var subtitles = new List<Subtitle>
                                {
                new Subtitle(id, tvReleaseIdentity.ToString(), anyOfTheSupportedLanguages),
                new Subtitle(id, tvReleaseIdentity.ToString(), anyOfTheSupportedLanguages),
                new Subtitle(id, otherShow, anyOfTheSupportedLanguages)
            };
            A.CallTo(() => downloader.SearchSubtitles(A<SearchQuery>._)).Returns(subtitles);

            var results = downloaderWrapper.SearchSubtitle(tvReleaseIdentity, supportedLanguages);

            Assert.That(results.Select(s => s.FileName), Has.All.StringStarting(tvReleaseIdentity.ToString()));
        }