More work on the calendar, including unit tests

pull/3895/head
Jamie Rees 6 years ago
parent 9a267465a7
commit 7fdbc10ccc

@ -0,0 +1,152 @@

using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using Moq;
using NUnit.Framework;
using Ombi.Core.Authentication;
using Ombi.Core.Engine.V2;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests;
namespace Ombi.Core.Tests.Engine
{
[TestFixture]
public class CalendarEngineTests
{
public Mock<IMovieRequestRepository> MovieRepo { get; set; }
public Mock<ITvRequestRepository> TvRepo { get; set; }
public CalendarEngine CalendarEngine { get; set; }
[SetUp]
public void Setup()
{
MovieRepo = new Mock<IMovieRequestRepository>();
TvRepo = new Mock<ITvRequestRepository>();
var principle = new Mock<IPrincipal>();
var identity = new Mock<IIdentity>();
identity.Setup(x => x.Name).Returns("UnitTest");
principle.Setup(x => x.Identity).Returns(identity.Object);
CalendarEngine = new CalendarEngine(principle.Object, null, null, MovieRepo.Object, TvRepo.Object);
}
[Test]
public async Task Calendar_Movies_OnlyGet_PreviousAndFuture_90_Days()
{
var movies = new List<MovieRequests>
{
new MovieRequests
{
Title="Invalid",
ReleaseDate = new DateTime(2018,10,01)
},
new MovieRequests
{
Title="Invalid",
ReleaseDate = DateTime.Now.AddDays(91)
},
new MovieRequests
{
Title="Valid",
ReleaseDate = DateTime.Now
}
};
MovieRepo.Setup(x => x.GetAll()).Returns(movies.AsQueryable());
var data = await CalendarEngine.GetCalendarData();
Assert.That(data.Count, Is.EqualTo(1));
Assert.That(data[0].Title, Is.EqualTo("Valid"));
}
[Test]
public async Task Calendar_Episodes_OnlyGet_PreviousAndFuture_90_Days()
{
var tv = new List<ChildRequests>
{
new ChildRequests
{
SeasonRequests = new List<SeasonRequests>
{
new SeasonRequests
{
Episodes = new List<EpisodeRequests>
{
new EpisodeRequests
{
Title = "Invalid",
AirDate = new DateTime(2018,01,01)
},
new EpisodeRequests
{
Title = "Invalid",
AirDate = DateTime.Now.AddDays(91)
},
new EpisodeRequests
{
Title = "Valid",
AirDate = DateTime.Now
},
}
}
}
},
};
TvRepo.Setup(x => x.GetChild()).Returns(tv.AsQueryable());
var data = await CalendarEngine.GetCalendarData();
Assert.That(data.Count, Is.EqualTo(1));
Assert.That(data[0].Title, Is.EqualTo("Valid"));
}
[TestCaseSource(nameof(StatusColorData))]
public async Task<string> Calendar_StatusColor(AvailabilityTestModel model)
{
var movies = new List<MovieRequests>
{
new MovieRequests
{
Title="Valid",
ReleaseDate = DateTime.Now,
Denied = model.Denied,
Approved = model.Approved,
Available = model.Available
},
};
MovieRepo.Setup(x => x.GetAll()).Returns(movies.AsQueryable());
var data = await CalendarEngine.GetCalendarData();
return data[0].BackgroundColor;
}
public static IEnumerable<TestCaseData> StatusColorData
{
get
{
yield return new TestCaseData(new AvailabilityTestModel
{
Approved = true,
Denied = true
}).Returns("red").SetName("Calendar_DeniedRequest");
yield return new TestCaseData(new AvailabilityTestModel
{
Available = true,
Approved = true
}).Returns("#469c83").SetName("Calendar_AvailableRequest");
yield return new TestCaseData(new AvailabilityTestModel
{
Approved = true
}).Returns("teal").SetName("Calendar_ApprovedRequest");
}
}
}
public class AvailabilityTestModel
{
public bool Available { get; set; }
public bool Denied { get; set; }
public bool Approved { get; set; }
}
}

@ -3,16 +3,22 @@ using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Ombi.Api.Sonarr.Models;
using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Models.Search.V2;
using Ombi.Core.Rule.Interfaces;
using Ombi.Helpers;
using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests;
namespace Ombi.Core.Engine.V2
{
public class CalendarEngine : BaseEngine, ICalendarEngine
{
public DateTime DaysAgo => DateTime.Now.AddDays(-90);
public DateTime DaysAhead => DateTime.Now.AddDays(90);
public CalendarEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo,
ITvRequestRepository tvRequestRepo) : base(user, um, rules)
{
@ -27,14 +33,21 @@ namespace Ombi.Core.Engine.V2
{
var viewModel = new List<CalendarViewModel>();
var movies = _movieRepo.GetAll().Where(x =>
x.ReleaseDate > DateTime.Now.AddDays(-30) && x.ReleaseDate < DateTime.Now.AddDays(30));
var episodes = _tvRepo.GetChild().SelectMany(x => x.SeasonRequests.SelectMany(e => e.Episodes)).ToList();
x.ReleaseDate > DaysAgo && x.ReleaseDate < DaysAhead);
var episodes = _tvRepo.GetChild().SelectMany(x => x.SeasonRequests.SelectMany(e => e.Episodes
.Where(w => w.AirDate > DaysAgo && w.AirDate < DaysAhead)));
foreach (var e in episodes)
{
viewModel.Add(new CalendarViewModel
{
Title = e.Title,
Start = e.AirDate.Date
Start = e.AirDate.Date,
Type = RequestType.TvShow,
BackgroundColor = GetBackgroundColor(e),
ExtraParams = new List<ExtraParams>
{
new ExtraParams { Overview = e.Season?.ChildRequest?.ParentRequest?.Overview ?? string.Empty, ProviderId = e.Season?.ChildRequest?.ParentRequest?.TvDbId ?? 0}
}
});
}
@ -43,11 +56,72 @@ namespace Ombi.Core.Engine.V2
viewModel.Add(new CalendarViewModel
{
Title = m.Title,
Start = m.ReleaseDate.Date
Start = m.ReleaseDate.Date,
BackgroundColor = GetBackgroundColor(m),
Type = RequestType.Movie,
ExtraParams = new List<ExtraParams>
{
new ExtraParams { Overview = m.Overview, ProviderId = m.TheMovieDbId}
}
});
}
return viewModel;
}
private string GetBackgroundColor(MovieRequests req)
{
if (req.Available)
{
return "#469c83";
}
if (!req.Available)
{
if (req.Denied ?? false)
{
return "red";
}
if (req.Approved)
{
// We are approved state
return "blue";
}
if (!req.Approved)
{
// Processing
return "teal";
}
}
return "gray";
}
private string GetBackgroundColor(EpisodeRequests req)
{
if (req.Available)
{
return "#469c83";
}
if (!req.Available)
{
if (req.Approved)
{
// We are approved state
return "blue";
}
if (!req.Approved)
{
// Processing
return "teal";
}
}
return "gray";
}
}
}

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using Ombi.Store.Entities;
namespace Ombi.Core.Models.Search.V2
{
@ -6,5 +8,32 @@ namespace Ombi.Core.Models.Search.V2
{
public string Title { get; set; }
public DateTime Start { get; set; }
public string BackgroundColor { get; set; }
public RequestType Type { get; set; }
public List<ExtraParams> ExtraParams { get; set; }
public string BorderColor
{
get
{
switch (Type)
{
case RequestType.TvShow:
return "#ff0000";
case RequestType.Movie:
return "#0d5a3e";
case RequestType.Album:
return "#797979";
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
public class ExtraParams
{
public int ProviderId { get; set; }
public string Overview { get; set; }
}
}

@ -28,7 +28,7 @@ namespace Ombi.Helpers
return result;
}
using (await _mutex.LockAsync())
//using (await _mutex.LockAsync())
{
if (_memoryCache.TryGetValue(cacheKey, out result))
{

@ -2631,6 +2631,11 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
"dev": true
},
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"copy-concurrently": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
@ -3881,6 +3886,11 @@
"mime-types": "^2.1.12"
}
},
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@ -4477,6 +4487,18 @@
"rimraf": "2"
}
},
"fullcalendar": {
"version": "4.0.0-alpha.2",
"resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-4.0.0-alpha.2.tgz",
"integrity": "sha512-2trFzbvQWHijyt+u8Zv98PPfDkFH5bU5Yoqvn2ot5PTwIkLK95xrNat5jTHfpBMwh+KqHQSnux/BcGXARYgwcw==",
"requires": {
"luxon": "^1.4.2",
"moment": "^2.22.2",
"moment-timezone": "^0.5.21",
"rrule": "^2.5.6",
"superagent": "^3.8.3"
}
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -5988,6 +6010,11 @@
"yallist": "^2.1.2"
}
},
"luxon": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.12.0.tgz",
"integrity": "sha512-enPnPIHd5ZnZT0vpj9Xv8aq4j0yueAkhnh4xUKUHpqlgSm1r/8s6xTMjfyp2ugOWP7zivqJqgVTkW+rpHed61w=="
},
"magic-string": {
"version": "0.25.2",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz",
@ -6220,8 +6247,7 @@
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
"dev": true
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"micromatch": {
"version": "3.1.10",
@ -6256,9 +6282,7 @@
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
"optional": true
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.38.0",
@ -6416,6 +6440,14 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"moment-timezone": {
"version": "0.5.23",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.23.tgz",
"integrity": "sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w==",
"requires": {
"moment": ">= 2.9.0"
}
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -8168,6 +8200,14 @@
"inherits": "^2.0.1"
}
},
"rrule": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.0.tgz",
"integrity": "sha512-TRigkTJtG7Y1yOjNSKvFvVmvj/PzRZLR8lLcPW9GASOlaoqoL1J0kNuUV9I3LuZc7qFT+QB2NbxSLL9d33/ylg==",
"requires": {
"luxon": "^1.3.3"
}
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
@ -9145,6 +9185,38 @@
"when": "~3.6.x"
}
},
"superagent": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
"integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
"requires": {
"component-emitter": "^1.2.0",
"cookiejar": "^2.1.0",
"debug": "^3.1.0",
"extend": "^3.0.0",
"form-data": "^2.3.1",
"formidable": "^1.2.0",
"methods": "^1.1.1",
"mime": "^1.4.1",
"qs": "^6.5.1",
"readable-stream": "^2.3.5"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",

@ -1,4 +1,5 @@
import { Component, OnInit } from "@angular/core";
import { CalendarService } from "../../services/calendar.service";
import { ICalendarModel } from "../../interfaces/ICalendar";
@ -19,31 +20,6 @@ export class CalendarComponent implements OnInit {
debugger;
this.loading()
this.entries = await this.calendarService.getCalendarEntries();
this.events = [
{
"title": "All Day Event",
"start": new Date(),
"eventColor":"black"
},
{
"title": "Long Event",
"start": "2016-01-07",
"end": "2016-01-10"
},
{
"title": "Repeating Event",
"start": "2016-01-09T16:00:00"
},
{
"title": "Repeating Event",
"start": "2016-01-16T16:00:00"
},
{
"title": "Conference",
"start": "2016-01-11",
"end": "2016-01-13"
}
];
this.options = {
defaultDate: new Date(),
@ -52,6 +28,10 @@ export class CalendarComponent implements OnInit {
center: 'title',
right: 'month,agendaWeek'
},
eventClick: (e: any) => {
debugger;
e.preventDefault();
}
};
this.finishLoading();
}

@ -25,7 +25,7 @@
<button mat-raised-button class="btn-green btn-spacing" *ngIf="movie.available"> {{
'Common.Available' | translate }}</button>
<span *ngIf="!movie.available">
<span *ngIf="movie.requested|| movie.approved; then requestedBtn else notRequestedBtn"></span>
<span *ngIf="movie.requested || movie.approved; then requestedBtn else notRequestedBtn"></span>
<ng-template #requestedBtn>
<button mat-raised-button *ngIf="!hasRequest || hasRequest && !movieRequest.denied" class="btn-spacing" color="warn" [disabled]><i class="fa fa-check"></i>

@ -23,7 +23,7 @@ namespace Ombi.Controllers.V2
[HttpGet]
public async Task<List<CalendarViewModel>> GetCalendarEntried()
public async Task<List<CalendarViewModel>> GetCalendarEntries()
{
return await _calendarEngine.GetCalendarData();
}
Loading…
Cancel
Save