test: 🧪 added full test coverage to the plex availability checker, also fixed a small few bugs in there at the same time

This commit is contained in:
tidusjar 2022-09-30 20:55:56 +01:00
commit 9fb8af7e09
7 changed files with 236 additions and 71 deletions

View file

@ -11,10 +11,9 @@ using Ombi.Schedule.Jobs;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
using System; using Ombi.Tests;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ombi.Schedule.Tests namespace Ombi.Schedule.Tests
@ -29,14 +28,8 @@ namespace Ombi.Schedule.Tests
public void SetUp() public void SetUp()
{ {
_mocker = new AutoMocker(); _mocker = new AutoMocker();
Mock<IHubClients> mockClients = new Mock<IHubClients>(); var hub = SignalRHelper.MockHub<NotificationHub>();
Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>(); _mocker.Use(hub);
mockClients.Setup(clients => clients.Clients(It.IsAny<IReadOnlyList<string>>())).Returns(mockClientProxy.Object);
var hubContext = new Mock<IHubContext<NotificationHub>>();
hubContext.Setup(x => x.Clients).Returns(() => mockClients.Object);
_mocker.Use(hubContext);
_subject = _mocker.CreateInstance<TestAvailabilityChecker>(); _subject = _mocker.CreateInstance<TestAvailabilityChecker>();
} }

View file

@ -20,6 +20,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" /> <ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" />
<ProjectReference Include="..\Ombi.Test.Common\Ombi.Test.Common.csproj" /> <ProjectReference Include="..\Ombi.Test.Common\Ombi.Test.Common.csproj" />
<ProjectReference Include="..\Ombi.Tests\Ombi.Tests.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -19,49 +19,140 @@ using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Tests;
using Moq.AutoMock;
using Ombi.Settings.Settings.Models;
using Ombi.Notifications.Models;
namespace Ombi.Schedule.Tests namespace Ombi.Schedule.Tests
{ {
[TestFixture] [TestFixture]
[Ignore("Need to work out how to mockout the hub context")]
public class PlexAvailabilityCheckerTests public class PlexAvailabilityCheckerTests
{ {
private AutoMocker _mocker;
private PlexAvailabilityChecker _subject;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_repo = new Mock<IPlexContentRepository>(); _mocker = new AutoMocker();
_tv = new Mock<ITvRequestRepository>();
_movie = new Mock<IMovieRequestRepository>(); var hub = SignalRHelper.MockHub<NotificationHub>();
_notify = new Mock<INotificationHelper>(); _mocker.Use(hub);
var hub = new Mock<IHubContext<NotificationHub>>();
hub.Setup(x => _subject = _mocker.CreateInstance<PlexAvailabilityChecker>();
x.Clients.Clients(It.IsAny<IReadOnlyList<string>>()).SendCoreAsync(It.IsAny<string>(), It.IsAny<object[]>(), It.IsAny<CancellationToken>()));
NotificationHub.UsersOnline.TryAdd("A", new HubUsers());
Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object, Mock.Of<IFeatureService>());
} }
private Mock<IPlexContentRepository> _repo;
private Mock<ITvRequestRepository> _tv;
private Mock<IMovieRequestRepository> _movie;
private Mock<INotificationHelper> _notify;
private PlexAvailabilityChecker Checker;
[Test] [Test]
public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex() public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex_WithImdbId()
{ {
var request = new MovieRequests var request = new MovieRequests
{ {
ImdbId = "test" ImdbId = "test"
}; };
_movie.Setup(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable()); _mocker.Setup<IMovieRequestRepository>(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable());
_repo.Setup(x => x.Get("test", ProviderType.ImdbId)).ReturnsAsync(new PlexServerContent()); _mocker.Setup<IPlexContentRepository, Task<PlexServerContent>>(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<IMovieRequestRepository>(x => x.SaveChangesAsync(), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get("test", ProviderType.ImdbId), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get(It.IsAny<string>(), ProviderType.TheMovieDbId), Times.Never);
_mocker.Verify<INotificationHelper>(x => x.Notify(It.Is<NotificationOptions>(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<IMovieRequestRepository>(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable());
_mocker.Setup<IPlexContentRepository, Task<PlexServerContent>>(x => x.Get(It.IsAny<string>(), ProviderType.ImdbId)).ReturnsAsync((PlexServerContent)null);
_mocker.Setup<IPlexContentRepository, Task<PlexServerContent>>(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<IMovieRequestRepository>(x => x.SaveChangesAsync(), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get(It.IsAny<string>(), ProviderType.ImdbId), Times.Never);
_mocker.Verify<IPlexContentRepository>(x => x.Get(It.IsAny<string>(), ProviderType.TheMovieDbId), Times.Once);
_mocker.Verify<INotificationHelper>(x => x.Notify(It.Is<NotificationOptions>(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once);
}
[Test]
public async Task ProcessMovies_ShouldMarkAvailable_WhenInPlex_WithTheMovieDbId_4K_Enabled ()
{
_mocker.Setup<IFeatureService, Task<bool>>(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true);
var request = new MovieRequests
{
ImdbId = "test"
};
_mocker.Setup<IMovieRequestRepository>(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable());
_mocker.Setup<IPlexContentRepository, Task<PlexServerContent>>(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<IMovieRequestRepository>(x => x.SaveChangesAsync(), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get("test", ProviderType.ImdbId), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get(It.IsAny<string>(), ProviderType.TheMovieDbId), Times.Never);
_mocker.Verify<INotificationHelper>(x => x.Notify(It.Is<NotificationOptions>(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once);
}
[Test]
public async Task ProcessMovies_4K_ShouldMarkAvailable_WhenInPlex_WithImdbId_And_4K_FeatureEnabled()
{
_mocker.Setup<IFeatureService, Task<bool>>(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true);
var request = new MovieRequests
{
ImdbId = "test",
Is4kRequest = true,
Has4KRequest = true,
};
_mocker.Setup<IMovieRequestRepository>(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable());
_mocker.Setup<IPlexContentRepository, Task<PlexServerContent>>(x => x.Get("test", ProviderType.ImdbId)).ReturnsAsync(new PlexServerContent { Has4K = true });
await _subject.Execute(null);
_mocker.Verify<IMovieRequestRepository>(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<IMovieRequestRepository>(x => x.SaveChangesAsync(), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get("test", ProviderType.ImdbId), Times.Once);
_mocker.Verify<IPlexContentRepository>(x => x.Get(It.IsAny<string>(), ProviderType.TheMovieDbId), Times.Never);
_mocker.Verify<INotificationHelper>(x => x.Notify(It.Is<NotificationOptions>(x => x.NotificationType == NotificationType.RequestAvailable)), Times.Once);
} }
[Test] [Test]
@ -71,19 +162,96 @@ namespace Ombi.Schedule.Tests
{ {
ImdbId = "test" ImdbId = "test"
}; };
_movie.Setup(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable()); _mocker.Setup<IMovieRequestRepository>(x => x.GetAll()).Returns(new List<MovieRequests> { request }.AsQueryable());
await Checker.Execute(null); await _subject.Execute(null);
Assert.False(request.Available); Assert.False(request.Available);
} }
[Test] [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<ITvRequestRepository>(x => x.GetChild()).Returns(new List<ChildRequests> { request }.AsQueryable().BuildMock().Object);
_mocker.Setup<IPlexContentRepository, IQueryable<IMediaServerEpisode>>(x => x.GetAllEpisodes()).Returns(new List<PlexEpisode>
{ {
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<ITvRequestRepository>(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<ITvRequestRepository>(x => x.GetChild()).Returns(new List<ChildRequests> { request }.AsQueryable().BuildMock().Object);
_mocker.Setup<IPlexContentRepository, IQueryable<IMediaServerEpisode>>(x => x.GetAllEpisodes()).Returns(new List<PlexEpisode>
{
new PlexEpisode
{
Series = new PlexServerContent
{
ImdbId = "abc",
},
EpisodeNumber = 1,
SeasonNumber = 2,
}
}.AsQueryable().BuildMock().Object);
await _subject.Execute(null);
_mocker.Verify<ITvRequestRepository>(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<ITvRequestRepository>(x => x.GetChild()).Returns(new List<ChildRequests> { request }.AsQueryable().BuildMock().Object);
_mocker.Setup<IPlexContentRepository, IQueryable<IMediaServerEpisode>>(x => x.GetAllEpisodes()).Returns(new List<PlexEpisode>
{
new PlexEpisode
{
Series = new PlexServerContent
{
Title = "UNITTEST",
ImdbId = "invlaid",
},
EpisodeNumber = 1,
SeasonNumber = 2,
}
}.AsQueryable().BuildMock().Object);
await _subject.Execute(null);
_mocker.Verify<ITvRequestRepository>(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<SeasonRequests> SeasonRequests = new EditableList<SeasonRequests>
{ {
new SeasonRequests new SeasonRequests
@ -106,27 +274,6 @@ namespace Ombi.Schedule.Tests
Email = "abc" Email = "abc"
} }
}; };
_tv.Setup(x => x.GetChild()).Returns(new List<ChildRequests> { request }.AsQueryable().BuildMock().Object);
_repo.Setup(x => x.GetAllEpisodes()).Returns(new List<PlexEpisode>
{
new PlexEpisode
{
Series = new PlexServerContent
{
TvDbId = 1.ToString(),
},
EpisodeNumber = 1,
SeasonNumber = 2
}
}.AsQueryable().BuildMock().Object);
_repo.Setup(x => x.Include(It.IsAny<IQueryable<PlexEpisode>>(),It.IsAny<Expression<Func<PlexEpisode, PlexServerContent>>>()));
await Checker.Execute(null);
_tv.Verify(x => x.Save(), Times.Once);
Assert.True(request.SeasonRequests[0].Episodes[0].Available);
} }
} }
} }

View file

@ -38,7 +38,6 @@ namespace Ombi.Schedule.Jobs.Plex
{ {
try try
{ {
await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) await _hub.Clients.Clients(NotificationHub.AdminConnectionIds)
.SendAsync(NotificationHub.NotificationEvent, "Plex Availability Check Started"); .SendAsync(NotificationHub.NotificationEvent, "Plex Availability Check Started");
await ProcessMovies(); await ProcessMovies();
@ -70,16 +69,22 @@ namespace Ombi.Schedule.Jobs.Plex
{ {
var useImdb = false; var useImdb = false;
var useTvDb = false; var useTvDb = false;
var useMovieDb = false;
if (child.ParentRequest.ImdbId.HasValue()) if (child.ParentRequest.ImdbId.HasValue())
{ {
useImdb = true; useImdb = true;
} }
if (child.ParentRequest.TvDbId.ToString().HasValue()) if (child.ParentRequest.TvDbId > 0)
{ {
useTvDb = true; useTvDb = true;
} }
if (child.ParentRequest.ExternalProviderId > 0)
{
useMovieDb = true;
}
var tvDbId = child.ParentRequest.TvDbId; var tvDbId = child.ParentRequest.TvDbId;
var imdbId = child.ParentRequest.ImdbId; var imdbId = child.ParentRequest.ImdbId;
IQueryable<IMediaServerEpisode> seriesEpisodes = null; IQueryable<IMediaServerEpisode> seriesEpisodes = null;
@ -91,18 +96,16 @@ namespace Ombi.Schedule.Jobs.Plex
{ {
seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString()); seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString());
} }
if (useMovieDb && (seriesEpisodes == null || !seriesEpisodes.Any()))
if (seriesEpisodes == null)
{ {
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 // Let's try and match the series by name
seriesEpisodes = plexEpisodes.Where(x => seriesEpisodes = plexEpisodes.Where(x =>
x.Series.Title == child.Title); x.Series.Title.Equals(child.Title, StringComparison.InvariantCultureIgnoreCase));
} }
await ProcessTvShow(seriesEpisodes, child); await ProcessTvShow(seriesEpisodes, child);

View file

@ -0,0 +1,21 @@
using Microsoft.AspNetCore.SignalR;
using Moq;
using System.Collections.Generic;
namespace Ombi.Tests
{
public class SignalRHelper
{
public static Mock<IHubContext<T>> MockHub<T>() where T : Hub
{
Mock<IHubClients> mockClients = new Mock<IHubClients>();
Mock<IClientProxy> mockClientProxy = new Mock<IClientProxy>();
mockClients.Setup(clients => clients.Clients(It.IsAny<IReadOnlyList<string>>())).Returns(mockClientProxy.Object);
var hubContext = new Mock<IHubContext<T>>();
hubContext.Setup(x => x.Clients).Returns(() => mockClients.Object);
return hubContext;
}
}
}