From 9fb8af7e092ff75b6d5fae994cd480420c3ac909 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Fri, 30 Sep 2022 20:55:56 +0100 Subject: [PATCH] =?UTF-8?q?test:=20=F0=9F=A7=AA=20added=20full=20test=20co?= =?UTF-8?q?verage=20to=20the=20plex=20availability=20checker,=20also=20fix?= =?UTF-8?q?ed=20a=20small=20few=20bugs=20in=20there=20at=20the=20same=20ti?= =?UTF-8?q?me?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AvailabilityCheckerTests.cs | 13 +- .../Ombi.Schedule.Tests.csproj | 1 + .../PlexAvailabilityCheckerTests.cs | 247 ++++++++++++++---- .../Jobs/Plex/PlexAvailabilityChecker.cs | 19 +- .../Entities/IMediaServerContent.cs | 4 +- src/Ombi.Store/Entities/MediaServerContent.cs | 2 +- src/Ombi.Tests/SignalRHelper.cs | 21 ++ 7 files changed, 236 insertions(+), 71 deletions(-) create mode 100644 src/Ombi.Tests/SignalRHelper.cs diff --git a/src/Ombi.Schedule.Tests/AvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/AvailabilityCheckerTests.cs index 41f51deee..d909b7519 100644 --- a/src/Ombi.Schedule.Tests/AvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/AvailabilityCheckerTests.cs @@ -11,10 +11,9 @@ using Ombi.Schedule.Jobs; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; using Ombi.Store.Repository.Requests; -using System; +using Ombi.Tests; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; namespace Ombi.Schedule.Tests @@ -29,14 +28,8 @@ namespace Ombi.Schedule.Tests public void SetUp() { _mocker = new AutoMocker(); - Mock mockClients = new Mock(); - Mock mockClientProxy = new Mock(); - mockClients.Setup(clients => clients.Clients(It.IsAny>())).Returns(mockClientProxy.Object); - - var hubContext = new Mock>(); - hubContext.Setup(x => x.Clients).Returns(() => mockClients.Object); - _mocker.Use(hubContext); - + var hub = SignalRHelper.MockHub(); + _mocker.Use(hub); _subject = _mocker.CreateInstance(); } diff --git a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj index d8e698d0e..d2215c5f1 100644 --- a/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj +++ b/src/Ombi.Schedule.Tests/Ombi.Schedule.Tests.csproj @@ -20,6 +20,7 @@ + diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs index 6a549458b..d25bb8413 100644 --- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs @@ -19,49 +19,140 @@ using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; using Ombi.Helpers; using Ombi.Core.Services; +using Ombi.Tests; +using Moq.AutoMock; +using Ombi.Settings.Settings.Models; +using Ombi.Notifications.Models; namespace Ombi.Schedule.Tests { [TestFixture] - [Ignore("Need to work out how to mockout the hub context")] public class PlexAvailabilityCheckerTests { + private AutoMocker _mocker; + private PlexAvailabilityChecker _subject; + [SetUp] public void Setup() { - _repo = new Mock(); - _tv = new Mock(); - _movie = new Mock(); - _notify = new Mock(); - var hub = new Mock>(); - hub.Setup(x => - x.Clients.Clients(It.IsAny>()).SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())); - NotificationHub.UsersOnline.TryAdd("A", new HubUsers()); - Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object, Mock.Of()); + _mocker = new AutoMocker(); + + var hub = SignalRHelper.MockHub(); + _mocker.Use(hub); + + _subject = _mocker.CreateInstance(); } - - private Mock _repo; - private Mock _tv; - private Mock _movie; - private Mock _notify; - private PlexAvailabilityChecker Checker; - [Test] - public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex() + public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex_WithImdbId() { var request = new MovieRequests { ImdbId = "test" }; - _movie.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); - _repo.Setup(x => x.Get("test", ProviderType.ImdbId)).ReturnsAsync(new PlexServerContent()); + _mocker.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); + _mocker.Setup>(x => x.Get("test", ProviderType.ImdbId)).ReturnsAsync(new PlexServerContent()); - await Checker.Execute(null); + await _subject.Execute(null); - _movie.Verify(x => x.Save(), Times.Once); + Assert.Multiple(() => + { + Assert.That(request.Available, Is.True); + Assert.That(request.MarkedAsAvailable, Is.Not.Null); + Assert.That(request.Available4K, Is.False); + Assert.That(request.MarkedAsAvailable4K, Is.Null); + }); - Assert.True(request.Available); + _mocker.Verify(x => x.SaveChangesAsync(), Times.Once); + _mocker.Verify(x => x.Get("test", ProviderType.ImdbId), Times.Once); + _mocker.Verify(x => x.Get(It.IsAny(), ProviderType.TheMovieDbId), Times.Never); + _mocker.Verify(x => x.Notify(It.Is(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once); + } + + [Test] + public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex_WithTheMovieDbId() + { + var request = new MovieRequests + { + ImdbId = null, + TheMovieDbId = 33 + }; + _mocker.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); + _mocker.Setup>(x => x.Get(It.IsAny(), ProviderType.ImdbId)).ReturnsAsync((PlexServerContent)null); + _mocker.Setup>(x => x.Get("33", ProviderType.TheMovieDbId)).ReturnsAsync(new PlexServerContent()); + + await _subject.Execute(null); + + Assert.Multiple(() => + { + Assert.That(request.Available, Is.True); + Assert.That(request.MarkedAsAvailable, Is.Not.Null); + Assert.That(request.Available4K, Is.False); + Assert.That(request.MarkedAsAvailable4K, Is.Null); + }); + + _mocker.Verify(x => x.SaveChangesAsync(), Times.Once); + _mocker.Verify(x => x.Get(It.IsAny(), ProviderType.ImdbId), Times.Never); + _mocker.Verify(x => x.Get(It.IsAny(), ProviderType.TheMovieDbId), Times.Once); + _mocker.Verify(x => x.Notify(It.Is(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once); + } + + [Test] + public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex_WithTheMovieDbId_4K_Enabled () + { + _mocker.Setup>(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); + var request = new MovieRequests + { + ImdbId = "test" + }; + _mocker.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); + _mocker.Setup>(x => x.Get("test", ProviderType.ImdbId)).ReturnsAsync(new PlexServerContent { Quality = "1080p" }); + + await _subject.Execute(null); + + Assert.Multiple(() => + { + Assert.That(request.Available, Is.True); + Assert.That(request.MarkedAsAvailable, Is.Not.Null); + Assert.That(request.Available4K, Is.False); + Assert.That(request.MarkedAsAvailable4K, Is.Null); + }); + + _mocker.Verify(x => x.SaveChangesAsync(), Times.Once); + _mocker.Verify(x => x.Get("test", ProviderType.ImdbId), Times.Once); + _mocker.Verify(x => x.Get(It.IsAny(), ProviderType.TheMovieDbId), Times.Never); + _mocker.Verify(x => x.Notify(It.Is(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once); + } + + [Test] + public async Task ProcessMovies_4K_ShouldMarkAvailable_WhenInPlex_WithImdbId_And_4K_FeatureEnabled() + { + _mocker.Setup>(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true); + var request = new MovieRequests + { + ImdbId = "test", + Is4kRequest = true, + Has4KRequest = true, + }; + _mocker.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); + _mocker.Setup>(x => x.Get("test", ProviderType.ImdbId)).ReturnsAsync(new PlexServerContent { Has4K = true }); + + await _subject.Execute(null); + + _mocker.Verify(x => x.SaveChangesAsync(), Times.Once); + + Assert.Multiple(() => + { + Assert.That(request.Available, Is.False); + Assert.That(request.MarkedAsAvailable, Is.Null); + Assert.That(request.Available4K, Is.True); + Assert.That(request.MarkedAsAvailable4K, Is.Not.Null); + }); + + _mocker.Verify(x => x.SaveChangesAsync(), Times.Once); + _mocker.Verify(x => x.Get("test", ProviderType.ImdbId), Times.Once); + _mocker.Verify(x => x.Get(It.IsAny(), ProviderType.TheMovieDbId), Times.Never); + _mocker.Verify(x => x.Notify(It.Is(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once); } [Test] @@ -71,19 +162,96 @@ namespace Ombi.Schedule.Tests { ImdbId = "test" }; - _movie.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); + _mocker.Setup(x => x.GetAll()).Returns(new List { request }.AsQueryable()); - await Checker.Execute(null); + await _subject.Execute(null); Assert.False(request.Available); } [Test] - public async Task ProcessTv_ShouldMark_Episode_Available_WhenInPlex() + public async Task ProcessTv_ShouldMark_Episode_Available_WhenInPlex_MovieDbId() { - var request = new ChildRequests + var request = CreateChildRequest(null, 33, 99); + _mocker.Setup(x => x.GetChild()).Returns(new List { request }.AsQueryable().BuildMock().Object); + _mocker.Setup>(x => x.GetAllEpisodes()).Returns(new List { - ParentRequest = new TvRequests { TvDbId = 1 }, + new PlexEpisode + { + Series = new PlexServerContent + { + TheMovieDbId = 33.ToString(), + Title = "Test" + }, + EpisodeNumber = 1, + SeasonNumber = 2, + } + }.AsQueryable().BuildMock().Object); + + await _subject.Execute(null); + + _mocker.Verify(x => x.Save(), Times.AtLeastOnce); + + Assert.True(request.SeasonRequests[0].Episodes[0].Available); + } + + [Test] + public async Task ProcessTv_ShouldMark_Episode_Available_WhenInPlex_ImdbId() + { + var request = CreateChildRequest("abc", -1, 99); + _mocker.Setup(x => x.GetChild()).Returns(new List { request }.AsQueryable().BuildMock().Object); + _mocker.Setup>(x => x.GetAllEpisodes()).Returns(new List + { + new PlexEpisode + { + Series = new PlexServerContent + { + ImdbId = "abc", + }, + EpisodeNumber = 1, + SeasonNumber = 2, + } + }.AsQueryable().BuildMock().Object); + + await _subject.Execute(null); + + _mocker.Verify(x => x.Save(), Times.AtLeastOnce); + + Assert.True(request.SeasonRequests[0].Episodes[0].Available); + } + + [Test] + public async Task ProcessTv_ShouldMark_Episode_Available_By_TitleMatch() + { + var request = CreateChildRequest("abc", -1, 99); + _mocker.Setup(x => x.GetChild()).Returns(new List { request }.AsQueryable().BuildMock().Object); + _mocker.Setup>(x => x.GetAllEpisodes()).Returns(new List + { + new PlexEpisode + { + Series = new PlexServerContent + { + Title = "UNITTEST", + ImdbId = "invlaid", + }, + EpisodeNumber = 1, + SeasonNumber = 2, + } + }.AsQueryable().BuildMock().Object); + + await _subject.Execute(null); + + _mocker.Verify(x => x.Save(), Times.AtLeastOnce); + + Assert.True(request.SeasonRequests[0].Episodes[0].Available); + } + + private ChildRequests CreateChildRequest(string imdbId, int theMovieDbId, int tvdbId) + { + return new ChildRequests + { + Title = "UnitTest", + ParentRequest = new TvRequests { ImdbId = imdbId, ExternalProviderId = theMovieDbId, TvDbId = tvdbId }, SeasonRequests = new EditableList { new SeasonRequests @@ -93,7 +261,7 @@ namespace Ombi.Schedule.Tests new EpisodeRequests { EpisodeNumber = 1, - Season = new SeasonRequests + Season = new SeasonRequests { SeasonNumber = 2 } @@ -106,27 +274,6 @@ namespace Ombi.Schedule.Tests Email = "abc" } }; - _tv.Setup(x => x.GetChild()).Returns(new List { request }.AsQueryable().BuildMock().Object); - _repo.Setup(x => x.GetAllEpisodes()).Returns(new List - { - new PlexEpisode - { - Series = new PlexServerContent - { - TvDbId = 1.ToString(), - }, - EpisodeNumber = 1, - SeasonNumber = 2 - } - }.AsQueryable().BuildMock().Object); - _repo.Setup(x => x.Include(It.IsAny>(),It.IsAny>>())); - - await Checker.Execute(null); - - _tv.Verify(x => x.Save(), Times.Once); - - Assert.True(request.SeasonRequests[0].Episodes[0].Available); - } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 34cd0964a..70a500298 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -38,7 +38,6 @@ namespace Ombi.Schedule.Jobs.Plex { try { - await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) .SendAsync(NotificationHub.NotificationEvent, "Plex Availability Check Started"); await ProcessMovies(); @@ -70,16 +69,22 @@ namespace Ombi.Schedule.Jobs.Plex { var useImdb = false; var useTvDb = false; + var useMovieDb = false; if (child.ParentRequest.ImdbId.HasValue()) { useImdb = true; } - if (child.ParentRequest.TvDbId.ToString().HasValue()) + if (child.ParentRequest.TvDbId > 0) { useTvDb = true; } + if (child.ParentRequest.ExternalProviderId > 0) + { + useMovieDb = true; + } + var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; IQueryable seriesEpisodes = null; @@ -91,18 +96,16 @@ namespace Ombi.Schedule.Jobs.Plex { seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString()); } - - if (seriesEpisodes == null) + if (useMovieDb && (seriesEpisodes == null || !seriesEpisodes.Any())) { - continue; + seriesEpisodes = plexEpisodes.Where(x => x.Series.TheMovieDbId == child.ParentRequest.ExternalProviderId.ToString()); } - if (!seriesEpisodes.Any()) + if (seriesEpisodes == null || !seriesEpisodes.Any()) { // Let's try and match the series by name seriesEpisodes = plexEpisodes.Where(x => - x.Series.Title == child.Title); - + x.Series.Title.Equals(child.Title, StringComparison.InvariantCultureIgnoreCase)); } await ProcessTvShow(seriesEpisodes, child); diff --git a/src/Ombi.Store/Entities/IMediaServerContent.cs b/src/Ombi.Store/Entities/IMediaServerContent.cs index fa6772fbd..afe97c9ed 100644 --- a/src/Ombi.Store/Entities/IMediaServerContent.cs +++ b/src/Ombi.Store/Entities/IMediaServerContent.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Ombi.Store.Entities { - public interface IMediaServerContent: IEntity + public interface IMediaServerContent : IEntity { public string Title { get; set; } public string ImdbId { get; set; } @@ -29,7 +29,7 @@ namespace Ombi.Store.Entities public bool HasTheMovieDb => !string.IsNullOrEmpty(TheMovieDbId); } - public interface IMediaServerEpisode: IBaseMediaServerEpisode + public interface IMediaServerEpisode : IBaseMediaServerEpisode { public string Title { get; set; } /// diff --git a/src/Ombi.Store/Entities/MediaServerContent.cs b/src/Ombi.Store/Entities/MediaServerContent.cs index 4f086060b..9424aeca9 100644 --- a/src/Ombi.Store/Entities/MediaServerContent.cs +++ b/src/Ombi.Store/Entities/MediaServerContent.cs @@ -36,7 +36,7 @@ namespace Ombi.Store.Entities public abstract RecentlyAddedType RecentlyAddedType { get; } } - public abstract class MediaServerEpisode: Entity, IMediaServerEpisode + public abstract class MediaServerEpisode : Entity, IMediaServerEpisode { public int EpisodeNumber { get; set; } public int SeasonNumber { get; set; } diff --git a/src/Ombi.Tests/SignalRHelper.cs b/src/Ombi.Tests/SignalRHelper.cs new file mode 100644 index 000000000..80a7fcdd0 --- /dev/null +++ b/src/Ombi.Tests/SignalRHelper.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.SignalR; +using Moq; +using System.Collections.Generic; + +namespace Ombi.Tests +{ + public class SignalRHelper + { + public static Mock> MockHub() where T : Hub + { + Mock mockClients = new Mock(); + Mock mockClientProxy = new Mock(); + mockClients.Setup(clients => clients.Clients(It.IsAny>())).Returns(mockClientProxy.Object); + + var hubContext = new Mock>(); + hubContext.Setup(x => x.Clients).Returns(() => mockClients.Object); + + return hubContext; + } + } +}