using System.Reflection; using ErsatzTV.Controllers.Api; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using NUnit.Framework; using Shouldly; namespace ErsatzTV.Tests.Controllers; [TestFixture] public class ApiErrorResponseMetadataTests { [TestCase(typeof(ChannelController), nameof(ChannelController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.CreateFromLineup), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.CreateFromLineup), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.Update), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.Update), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.Delete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.BulkRenumber), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.BulkRenumber), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.BulkMoveToGroup), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.BulkMoveToGroup), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.BulkDelete), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.BulkDelete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelController), nameof(ChannelController.ResetPlayout), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelController), nameof(ChannelController.ResetPlayout), StatusCodes.Status409Conflict)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.GetDefault), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.SetDefault), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.SetDefault), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.Update), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.Update), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(ChannelTemplateController), nameof(ChannelTemplateController.Delete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(CollectionController), nameof(CollectionController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(CollectionController), nameof(CollectionController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(CollectionController), nameof(CollectionController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(CollectionController), nameof(CollectionController.Update), StatusCodes.Status404NotFound)] [TestCase(typeof(CollectionController), nameof(CollectionController.Update), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(CollectionController), nameof(CollectionController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(CollectionController), nameof(CollectionController.Delete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(CollectionController), nameof(CollectionController.AddItems), StatusCodes.Status404NotFound)] [TestCase(typeof(CollectionController), nameof(CollectionController.AddItems), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(CollectionController), nameof(CollectionController.RemoveItem), StatusCodes.Status404NotFound)] [TestCase(typeof(CollectionController), nameof(CollectionController.RemoveItem), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.Update), StatusCodes.Status404NotFound)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.Update), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(SmartCollectionController), nameof(SmartCollectionController.Delete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.Update), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.Update), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.Delete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.GetItems), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.AddItem), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.AddItem), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.ReplaceItems), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.ReplaceItems), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.DeleteItem), StatusCodes.Status404NotFound)] [TestCase(typeof(ScheduleController), nameof(ScheduleController.DeleteItem), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(BlockController), nameof(BlockController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.CreateGroup), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(BlockController), nameof(BlockController.DeleteGroup), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(BlockController), nameof(BlockController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.GetItems), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.Replace), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.Replace), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(BlockController), nameof(BlockController.Preview), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.Copy), StatusCodes.Status404NotFound)] [TestCase(typeof(BlockController), nameof(BlockController.Copy), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(TemplateController), nameof(TemplateController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.CreateGroup), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(TemplateController), nameof(TemplateController.DeleteGroup), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(TemplateController), nameof(TemplateController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.GetItems), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.Replace), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.Replace), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(TemplateController), nameof(TemplateController.Copy), StatusCodes.Status404NotFound)] [TestCase(typeof(TemplateController), nameof(TemplateController.Copy), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(DecoController), nameof(DecoController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoController), nameof(DecoController.CreateGroup), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(DecoController), nameof(DecoController.DeleteGroup), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoController), nameof(DecoController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoController), nameof(DecoController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(DecoController), nameof(DecoController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoController), nameof(DecoController.Replace), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoController), nameof(DecoController.Replace), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.CreateGroup), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.DeleteGroup), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.GetItems), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.Replace), StatusCodes.Status404NotFound)] [TestCase(typeof(DecoTemplateController), nameof(DecoTemplateController.Replace), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.UpdateDefaultDeco), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.UpdateDefaultDeco), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.UpdateDefaultDeco), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Create), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Create), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Update), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Update), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Update), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Delete), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Delete), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.Delete), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.GetAlternateSchedules), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.GetAlternateSchedules), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.ReplaceAlternateSchedules), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.ReplaceAlternateSchedules), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.ReplaceAlternateSchedules), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.GetTemplates), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.GetTemplates), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.ReplaceTemplates), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.ReplaceTemplates), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.ReplaceTemplates), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.EraseItems), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.EraseItems), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.EraseItems), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.EraseItemsAndHistory), StatusCodes.Status404NotFound)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.EraseItemsAndHistory), StatusCodes.Status409Conflict)] [TestCase(typeof(PlayoutController), nameof(PlayoutController.EraseItemsAndHistory), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.GetById), StatusCodes.Status404NotFound)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.AddOne), StatusCodes.Status404NotFound)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.AddOne), StatusCodes.Status401Unauthorized)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.AddOne), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.UpdateOne), StatusCodes.Status404NotFound)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.UpdateOne), StatusCodes.Status401Unauthorized)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.UpdateOne), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.DeleteProfileAsync), StatusCodes.Status404NotFound)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.DeleteProfileAsync), StatusCodes.Status401Unauthorized)] [TestCase(typeof(FFmpegProfileController), nameof(FFmpegProfileController.DeleteProfileAsync), StatusCodes.Status422UnprocessableEntity)] [TestCase(typeof(LibrariesController), nameof(LibrariesController.ScanShow), StatusCodes.Status404NotFound)] public void Api_Error_Response_Metadata_Should_Document_ProblemDetails( Type controllerType, string actionName, int statusCode) { MethodInfo action = controllerType.GetMethods().Single(m => m.Name == actionName); ProducesResponseTypeAttribute? metadata = action .GetCustomAttributes(inherit: true) .SingleOrDefault(a => a.StatusCode == statusCode); metadata.ShouldNotBeNull($"{controllerType.Name}.{actionName} should document HTTP {statusCode}"); metadata.Type.ShouldBe(typeof(ProblemDetails)); } }