diff options
| author | Shadowghost <Ghost_of_Stone@web.de> | 2026-04-29 22:18:47 +0200 |
|---|---|---|
| committer | Shadowghost <Ghost_of_Stone@web.de> | 2026-04-29 22:18:47 +0200 |
| commit | 68ab58589444091925c15ad20d36f935b7bc2e21 (patch) | |
| tree | ba361c72e26cf0d5e11c29fecb5e6cfe188b1312 | |
| parent | b717754ed87200a95e62dfb209b41e9556a8fc49 (diff) | |
| parent | 105492ac2843fbae3df3999e99da6356a1851034 (diff) | |
Merge remote-tracking branch 'upstream/master' into epg-fixes
91 files changed, 309 insertions, 243 deletions
diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3f7a9454c5..9b44eff4c6 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "dotnet-ef": { - "version": "10.0.6", + "version": "10.0.7", "commands": [ "dotnet-ef" ] diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 9fdcaedf97..f0ecb166b4 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -35,7 +35,7 @@ jobs: --verbosity minimal - name: Merge code coverage results - uses: danielpalme/ReportGenerator-GitHub-Action@7ae927204961589fcb0b0be245c51fbbc87cbca2 # v5.5.5 + uses: danielpalme/ReportGenerator-GitHub-Action@a003c8fb9ac008fd0fffd5faa4f7d3ecb52e0675 # v5.5.7 with: reports: "**/coverage.cobertura.xml" targetdir: "merged/" diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 01f968690f..c42962786d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,5 +1,6 @@ # Jellyfin Contributors + - [0x25CBFC4F](https://github.com/0x25CBFC4F) - [1337joe](https://github.com/1337joe) - [97carmine](https://github.com/97carmine) - [Abbe98](https://github.com/Abbe98) @@ -14,7 +15,7 @@ - [bilde2910](https://github.com/bilde2910) - [bfayers](https://github.com/bfayers) - [BnMcG](https://github.com/BnMcG) - - [Bond-009](https://github.com/Bond-009) + - [Bond_009](https://github.com/Bond-009) - [brianjmurrell](https://github.com/brianjmurrell) - [bugfixin](https://github.com/bugfixin) - [chaosinnovator](https://github.com/chaosinnovator) @@ -31,6 +32,7 @@ - [DaveChild](https://github.com/DaveChild) - [DavidFair](https://github.com/DavidFair) - [Delgan](https://github.com/Delgan) + - [DerMaddis](https://github.com/dermaddis) - [Derpipose](https://github.com/Derpipose) - [dcrdev](https://github.com/dcrdev) - [dhartung](https://github.com/dhartung) @@ -54,6 +56,7 @@ - [geilername](https://github.com/geilername) - [GermanCoding](https://github.com/GermanCoding) - [gnattu](https://github.com/gnattu) + - [gnuyent](https://github.com/gnuyent) - [GodTamIt](https://github.com/GodTamIt) - [grafixeyehero](https://github.com/grafixeyehero) - [h1nk](https://github.com/h1nk) @@ -61,6 +64,7 @@ - [HelloWorld017](https://github.com/HelloWorld017) - [ikomhoog](https://github.com/ikomhoog) - [iwalton3](https://github.com/iwalton3) + - [Jakob Kukla](https://github.com/jakobkukla) - [jftuga](https://github.com/jftuga) - [jkhsjdhjs](https://github.com/jkhsjdhjs) - [jmshrv](https://github.com/jmshrv) @@ -69,8 +73,10 @@ - [JustAMan](https://github.com/JustAMan) - [justinfenn](https://github.com/justinfenn) - [JPVenson](https://github.com/JPVenson) + - [JPUC1143](https://github.com/Jpuc1143/) - [KerryRJ](https://github.com/KerryRJ) - [Larvitar](https://github.com/Larvitar) + - [lbenini](https://github.com/lbenini) - [LeoVerto](https://github.com/LeoVerto) - [Liggy](https://github.com/Liggy) - [lmaonator](https://github.com/lmaonator) @@ -83,15 +89,19 @@ - [marius-luca-87](https://github.com/marius-luca-87) - [mark-monteiro](https://github.com/mark-monteiro) - [MarkCiliaVincenti](https://github.com/MarkCiliaVincenti) + - [Martin Reuter](https://github.com/reuterma24) - [Matt07211](https://github.com/Matt07211) + - [Matthew Jones](https://github.com/matthew-jones-uk) - [Maxr1998](https://github.com/Maxr1998) - [mcarlton00](https://github.com/mcarlton00) + - [Michael McElroy](https://github.com/mcmcelro) - [mitchfizz05](https://github.com/mitchfizz05) - [mohd-akram](https://github.com/mohd-akram) - [MrTimscampi](https://github.com/MrTimscampi) - [n8225](https://github.com/n8225) - [Nalsai](https://github.com/Nalsai) - [Narfinger](https://github.com/Narfinger) + - [Nathan McCrina](https://github.com/nfmccrina) - [NathanPickard](https://github.com/NathanPickard) - [neilsb](https://github.com/neilsb) - [nevado](https://github.com/nevado) @@ -102,6 +112,7 @@ - [OancaAndrei](https://github.com/OancaAndrei) - [obradovichv](https://github.com/obradovichv) - [oddstr13](https://github.com/oddstr13) + - [olsh](https://github.com/olsh) - [orryverducci](https://github.com/orryverducci) - [petermcneil](https://github.com/petermcneil) - [Phlogi](https://github.com/Phlogi) @@ -112,6 +123,7 @@ - [RazeLighter777](https://github.com/RazeLighter777) - [redSpoutnik](https://github.com/redSpoutnik) - [ringmatter](https://github.com/ringmatter) + - [Robert Lützner](https://github.com/rluetzner) - [ryan-hartzell](https://github.com/ryan-hartzell) - [s0urcelab](https://github.com/s0urcelab) - [sachk](https://github.com/sachk) @@ -127,6 +139,7 @@ - [sl1288](https://github.com/sl1288) - [Smith00101010](https://github.com/Smith00101010) - [sorinyo2004](https://github.com/sorinyo2004) + - [Soumyadip Auddy](https://github.com/SoumyadipAuddy) - [sparky8251](https://github.com/sparky8251) - [spookbits](https://github.com/spookbits) - [ssenart](https://github.com/ssenart) @@ -149,6 +162,7 @@ - [twinkybot](https://github.com/twinkybot) - [Ullmie02](https://github.com/Ullmie02) - [Unhelpful](https://github.com/Unhelpful) + - [Utku Özdemir](https://github.com/utkuozdemir) - [viaregio](https://github.com/viaregio) - [vitorsemeano](https://github.com/vitorsemeano) - [voodoos](https://github.com/voodoos) @@ -213,6 +227,8 @@ - [ZeusCraft10](https://github.com/ZeusCraft10) - [MarcoCoreDuo](https://github.com/MarcoCoreDuo) - [LiHRaM](https://github.com/LiHRaM) + - [MSalman5230](https://github.com/MSalman5230) + - [dwandw](https://github.com/dwandw) # Emby Contributors @@ -276,17 +292,3 @@ - [tikuf](https://github.com/tikuf/) - [Tim Hobbs](https://github.com/timhobbs) - [SvenVandenbrande](https://github.com/SvenVandenbrande) - - [olsh](https://github.com/olsh) - - [lbenini](https://github.com/lbenini) - - [gnuyent](https://github.com/gnuyent) - - [Matthew Jones](https://github.com/matthew-jones-uk) - - [Jakob Kukla](https://github.com/jakobkukla) - - [Utku Özdemir](https://github.com/utkuozdemir) - - [JPUC1143](https://github.com/Jpuc1143/) - - [0x25CBFC4F](https://github.com/0x25CBFC4F) - - [Robert Lützner](https://github.com/rluetzner) - - [Nathan McCrina](https://github.com/nfmccrina) - - [Martin Reuter](https://github.com/reuterma24) - - [Michael McElroy](https://github.com/mcmcelro) - - [Soumyadip Auddy](https://github.com/SoumyadipAuddy) - - [DerMaddis](https://github.com/dermaddis) diff --git a/Directory.Packages.props b/Directory.Packages.props index d2b715d6aa..9768d39a27 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ <ItemGroup Label="Package Dependencies"> <PackageVersion Include="AsyncKeyedLock" Version="8.0.2" /> <PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" /> - <PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" /> + <PackageVersion Include="AutoFixture.Xunit3" Version="4.19.0" /> <PackageVersion Include="AutoFixture" Version="4.18.1" /> <PackageVersion Include="BDInfo" Version="0.8.0" /> <PackageVersion Include="BitFaster.Caching" Version="2.5.4" /> @@ -14,10 +14,10 @@ <PackageVersion Include="BlurHashSharp" Version="1.4.0-pre.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="coverlet.collector" Version="10.0.0" /> - <PackageVersion Include="Diacritics" Version="4.1.4" /> + <PackageVersion Include="Diacritics" Version="4.1.8" /> <PackageVersion Include="DiscUtils.Udf" Version="0.16.13" /> <PackageVersion Include="DotNet.Glob" Version="3.1.3" /> - <PackageVersion Include="FsCheck.Xunit" Version="3.3.2" /> + <PackageVersion Include="FsCheck.Xunit.v3" Version="3.3.3" /> <PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.1" /> <PackageVersion Include="ICU4N.Transliterator" Version="60.1.0-alpha.356" /> <PackageVersion Include="IDisposableAnalyzers" Version="4.0.8" /> @@ -26,28 +26,28 @@ <PackageVersion Include="libse" Version="4.0.12" /> <PackageVersion Include="LrcParser" Version="2025.623.0" /> <PackageVersion Include="MetaBrainz.MusicBrainz" Version="8.0.1" /> - <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.6" /> - <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.6" /> + <PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="10.0.7" /> + <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.7" /> <PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="5.3.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0" /> - <PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.6" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.6" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.6" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.6" /> - <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.6" /> - <PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.6" /> - <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.4.0" /> + <PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.7" /> + <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.7" /> + <PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.7" /> + <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.5.1" /> <PackageVersion Include="MimeTypes" Version="2.5.2" /> <PackageVersion Include="Morestachio" Version="5.0.1.631" /> <PackageVersion Include="Moq" Version="4.18.4" /> @@ -77,14 +77,13 @@ <PackageVersion Include="Svg.Skia" Version="3.4.1" /> <PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="10.1.7" /> <PackageVersion Include="Swashbuckle.AspNetCore" Version="10.1.7" /> - <PackageVersion Include="System.Text.Json" Version="10.0.6" /> + <PackageVersion Include="System.Text.Json" Version="10.0.7" /> <PackageVersion Include="TagLibSharp" Version="2.3.0" /> - <PackageVersion Include="z440.atl.core" Version="7.12.0" /> + <PackageVersion Include="z440.atl.core" Version="7.13.0" /> <PackageVersion Include="TMDbLib" Version="3.0.0" /> <PackageVersion Include="UTF.Unknown" Version="2.6.0" /> - <PackageVersion Include="Xunit.Priority" Version="1.1.6" /> - <PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" /> - <PackageVersion Include="Xunit.SkippableFact" Version="1.5.61" /> - <PackageVersion Include="xunit" Version="2.9.3" /> + <PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" /> + <PackageVersion Include="xunit.v3" Version="3.2.2" /> + <PackageVersion Include="Xunit.v3.Priority" Version="1.1.18" /> </ItemGroup> </Project> diff --git a/Emby.Server.Implementations/Localization/Core/ht.json b/Emby.Server.Implementations/Localization/Core/ht.json index f927d3173a..183c422a85 100644 --- a/Emby.Server.Implementations/Localization/Core/ht.json +++ b/Emby.Server.Implementations/Localization/Core/ht.json @@ -58,5 +58,8 @@ "ValueSpecialEpisodeName": "Spesyal - {0}", "VersionNumber": "Vesyon {0}", "TasksApplicationCategory": "Aplikasyon", - "TasksMaintenanceCategory": "Antretyen" + "TasksMaintenanceCategory": "Antretyen", + "AppDeviceValues": "Aplikasyon: {0}, Aparèy: {1}", + "AuthenticationSucceededWithUserName": "{0} otantifye avèk siksè", + "CameraImageUploadedFrom": "Une nouvelle image de la caméra a été téléchargée depuis {0}" } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 6b8888d244..d4d0f4537b 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -832,10 +832,6 @@ namespace Emby.Server.Implementations.Session { data.Played = true; } - else - { - data.Played = false; - } _userDataManager.SaveUserData(user, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None); } diff --git a/Jellyfin.Api/Controllers/ActivityLogController.cs b/Jellyfin.Api/Controllers/ActivityLogController.cs index 47d3f4b7f7..d6cc0e71a4 100644 --- a/Jellyfin.Api/Controllers/ActivityLogController.cs +++ b/Jellyfin.Api/Controllers/ActivityLogController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("System/ActivityLog")] [Authorize(Policy = Policies.RequiresElevation)] +[Tags("System")] public class ActivityLogController : BaseJellyfinApiController { private readonly IActivityManager _activityManager; diff --git a/Jellyfin.Api/Controllers/ApiKeyController.cs b/Jellyfin.Api/Controllers/ApiKeyController.cs index 3363d7bad2..161479e4ca 100644 --- a/Jellyfin.Api/Controllers/ApiKeyController.cs +++ b/Jellyfin.Api/Controllers/ApiKeyController.cs @@ -14,6 +14,7 @@ namespace Jellyfin.Api.Controllers; /// Authentication controller. /// </summary> [Route("Auth")] +[Tags("Authentication")] public class ApiKeyController : BaseJellyfinApiController { private readonly IAuthenticationManager _authenticationManager; diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index 99b0fde06d..f97ab414ce 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -25,6 +25,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("Artists")] [Authorize] +[Tags("Artist")] public class ArtistsController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs index 0d85b3a0db..e46ef0e31d 100644 --- a/Jellyfin.Api/Controllers/ChannelsController.cs +++ b/Jellyfin.Api/Controllers/ChannelsController.cs @@ -25,6 +25,7 @@ namespace Jellyfin.Api.Controllers; /// Channels Controller. /// </summary> [Authorize] +[Tags("Channel")] public class ChannelsController : BaseJellyfinApiController { private readonly IChannelManager _channelManager; diff --git a/Jellyfin.Api/Controllers/ClientLogController.cs b/Jellyfin.Api/Controllers/ClientLogController.cs index 139888bde8..c213b87940 100644 --- a/Jellyfin.Api/Controllers/ClientLogController.cs +++ b/Jellyfin.Api/Controllers/ClientLogController.cs @@ -15,6 +15,7 @@ namespace Jellyfin.Api.Controllers; /// Client log controller. /// </summary> [Authorize] +[Tags("System")] public class ClientLogController : BaseJellyfinApiController { private const int MaxDocumentSize = 1_000_000; diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index 9e03fbeb06..ecd667b2e8 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -20,6 +20,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("System")] [Authorize] +[Tags("System")] public class ConfigurationController : BaseJellyfinApiController { private readonly IServerConfigurationManager _configurationManager; diff --git a/Jellyfin.Api/Controllers/DevicesController.cs b/Jellyfin.Api/Controllers/DevicesController.cs index 50050262f0..eadb8c9855 100644 --- a/Jellyfin.Api/Controllers/DevicesController.cs +++ b/Jellyfin.Api/Controllers/DevicesController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers; /// Devices Controller. /// </summary> [Authorize(Policy = Policies.RequiresElevation)] +[Tags("Device")] public class DevicesController : BaseJellyfinApiController { private readonly IDeviceManager _deviceManager; diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index ef54e9db54..61d40a7268 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -20,6 +20,7 @@ namespace Jellyfin.Api.Controllers; /// Display Preferences Controller. /// </summary> [Authorize] +[Tags("DisplayPreference")] public class DisplayPreferencesController : BaseJellyfinApiController { private readonly IDisplayPreferencesManager _displayPreferencesManager; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index c13da3ac7b..c059f5880d 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -38,6 +38,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize] +[ApiExplorerSettings(IgnoreApi = true)] public class DynamicHlsController : BaseJellyfinApiController { private const EncoderPreset DefaultVodEncoderPreset = EncoderPreset.veryfast; diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index 456e643fd7..39c3f5abcf 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -25,6 +25,7 @@ namespace Jellyfin.Api.Controllers; /// The genres controller. /// </summary> [Authorize] +[Tags("Genre")] public class GenresController : BaseJellyfinApiController { private readonly IUserManager _userManager; diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 1927a332b2..b5365cd632 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -20,6 +20,7 @@ namespace Jellyfin.Api.Controllers; /// The hls segment controller. /// </summary> [Route("")] +[ApiExplorerSettings(IgnoreApi = true)] public class HlsSegmentController : BaseJellyfinApiController { private readonly IFileSystem _fileSystem; diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 301954561d..f80d32d149 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -320,6 +320,7 @@ public class InstantMixController : BaseJellyfinApiController [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Obsolete("Use GetInstantMixFromArtists")] + [ApiExplorerSettings(IgnoreApi = true)] public ActionResult<QueryResult<BaseItemDto>> GetInstantMixFromArtists2( [FromQuery, Required] Guid id, [FromQuery] Guid? userId, @@ -358,6 +359,7 @@ public class InstantMixController : BaseJellyfinApiController [HttpGet("MusicGenres/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [Obsolete("Use GetInstantMixFromMusicGenreByName")] public ActionResult<QueryResult<BaseItemDto>> GetInstantMixFromMusicGenreById( [FromQuery, Required] Guid id, [FromQuery] Guid? userId, diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 39760556a6..69cdba6afd 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -30,6 +30,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize] +[Tags("Item")] public class ItemsController : BaseJellyfinApiController { private readonly IUserManager _userManager; diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 558e1c6c80..6ef40a1898 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -114,20 +114,6 @@ public class LibraryController : BaseJellyfinApiController } /// <summary> - /// Gets critic review for an item. - /// </summary> - /// <response code="200">Critic reviews returned.</response> - /// <returns>The list of critic reviews.</returns> - [HttpGet("Items/{itemId}/CriticReviews")] - [Authorize] - [Obsolete("This endpoint is obsolete.")] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult<QueryResult<BaseItemDto>> GetCriticReviews() - { - return new QueryResult<BaseItemDto>(); - } - - /// <summary> /// Get theme songs for an item. /// </summary> /// <param name="itemId">The item id.</param> diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 4a8be58ddd..074cdb24e0 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -337,6 +337,7 @@ public class LiveTvController : BaseJellyfinApiController [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.LiveTvAccess)] [Obsolete("This endpoint is obsolete.")] + [ApiExplorerSettings(IgnoreApi = true)] public ActionResult<QueryResult<BaseItemDto>> GetRecordingsSeries( [FromQuery] string? channelId, [FromQuery] Guid? userId, @@ -366,6 +367,7 @@ public class LiveTvController : BaseJellyfinApiController [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.LiveTvAccess)] [Obsolete("This endpoint is obsolete.")] + [ApiExplorerSettings(IgnoreApi = true)] public ActionResult<QueryResult<BaseItemDto>> GetRecordingGroups([FromQuery] Guid? userId) { return new QueryResult<BaseItemDto>(); @@ -921,20 +923,6 @@ public class LiveTvController : BaseJellyfinApiController } /// <summary> - /// Get recording group. - /// </summary> - /// <param name="groupId">Group id.</param> - /// <returns>A <see cref="NotFoundResult"/>.</returns> - [HttpGet("Recordings/Groups/{groupId}")] - [Authorize(Policy = Policies.LiveTvAccess)] - [ProducesResponseType(StatusCodes.Status404NotFound)] - [Obsolete("This endpoint is obsolete.")] - public ActionResult<BaseItemDto> GetRecordingGroup([FromRoute, Required] Guid groupId) - { - return NotFound(); - } - - /// <summary> /// Get guide info. /// </summary> /// <response code="200">Guide info returned.</response> diff --git a/Jellyfin.Api/Controllers/LyricsController.cs b/Jellyfin.Api/Controllers/LyricsController.cs index 8eb4cadf88..5a27b2719e 100644 --- a/Jellyfin.Api/Controllers/LyricsController.cs +++ b/Jellyfin.Api/Controllers/LyricsController.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Extensions; using MediaBrowser.Common.Api; using MediaBrowser.Controller.Entities.Audio; @@ -27,6 +26,7 @@ namespace Jellyfin.Api.Controllers; /// Lyrics controller. /// </summary> [Route("")] +[Tags("Lyric")] public class LyricsController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/MediaSegmentsController.cs b/Jellyfin.Api/Controllers/MediaSegmentsController.cs index b8836d7cf1..65565826a4 100644 --- a/Jellyfin.Api/Controllers/MediaSegmentsController.cs +++ b/Jellyfin.Api/Controllers/MediaSegmentsController.cs @@ -20,6 +20,7 @@ namespace Jellyfin.Api.Controllers; /// Media Segments api. /// </summary> [Authorize] +[Tags("MediaSegment")] public class MediaSegmentsController : BaseJellyfinApiController { private readonly IMediaSegmentManager _mediaSegmentManager; diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index ace9a06395..50d34d0656 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/Jellyfin.Api/Controllers/MoviesController.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; @@ -18,6 +17,7 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers; @@ -26,6 +26,7 @@ namespace Jellyfin.Api.Controllers; /// Movies controller. /// </summary> [Authorize] +[Tags("Movie")] public class MoviesController : BaseJellyfinApiController { private readonly IUserManager _userManager; diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index a6427df67a..7af44f8bd6 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -25,6 +25,7 @@ namespace Jellyfin.Api.Controllers; /// The music genres controller. /// </summary> [Authorize] +[Tags("MusicGenre")] public class MusicGenresController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; @@ -72,6 +73,7 @@ public class MusicGenresController : BaseJellyfinApiController /// <returns>An <see cref="OkResult"/> containing the queryresult of music genres.</returns> [HttpGet] [Obsolete("Use GetGenres instead")] + [ApiExplorerSettings(IgnoreApi = true)] public ActionResult<QueryResult<BaseItemDto>> GetMusicGenres( [FromQuery] int? startIndex, [FromQuery] int? limit, @@ -144,6 +146,7 @@ public class MusicGenresController : BaseJellyfinApiController /// <returns>An <see cref="OkResult"/> containing a <see cref="BaseItemDto"/> with the music genre.</returns> [HttpGet("{genreName}")] [ProducesResponseType(StatusCodes.Status200OK)] + [Obsolete("Use GetGenre instead")] public ActionResult<BaseItemDto> GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { userId = RequestHelpers.GetUserId(User, userId); diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 274e94ee6d..1f8f963f70 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -using Jellyfin.Api.Constants; using MediaBrowser.Common.Api; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Configuration; @@ -19,6 +18,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize(Policy = Policies.RequiresElevation)] +[Tags("Plugin")] public class PackageController : BaseJellyfinApiController { private readonly IInstallationManager _installationManager; diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index 1811a219ac..8e7026341d 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -22,6 +22,7 @@ namespace Jellyfin.Api.Controllers; /// Persons controller. /// </summary> [Authorize] +[Tags("Person")] public class PersonsController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index 9679180937..048a49ffd4 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -29,6 +29,7 @@ namespace Jellyfin.Api.Controllers; /// Playlists controller. /// </summary> [Authorize] +[Tags("Playlist")] public class PlaylistsController : BaseJellyfinApiController { private readonly IPlaylistManager _playlistManager; diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index ade0906b34..aa22bdf6af 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -6,7 +6,6 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Database.Implementations.Entities; -using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; @@ -25,6 +24,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize] +[Tags("Session")] public class PlaystateController : BaseJellyfinApiController { private readonly IUserManager _userManager; @@ -273,6 +273,7 @@ public class PlaystateController : BaseJellyfinApiController [HttpPost("PlayingItems/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [Obsolete("This endpoint is obsolete. Use ReportPlaybackStart instead")] + [ApiExplorerSettings(IgnoreApi = true)] public async Task<ActionResult> OnPlaybackStart( [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, @@ -352,6 +353,7 @@ public class PlaystateController : BaseJellyfinApiController [HttpPost("PlayingItems/{itemId}/Progress")] [ProducesResponseType(StatusCodes.Status204NoContent)] [Obsolete("This endpoint is obsolete. Use ReportPlaybackProgress instead")] + [ApiExplorerSettings(IgnoreApi = true)] public async Task<ActionResult> OnPlaybackProgress( [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, @@ -441,6 +443,7 @@ public class PlaystateController : BaseJellyfinApiController [HttpDelete("PlayingItems/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [Obsolete("This endpoint is obsolete. Use ReportPlaybackStop instead")] + [ApiExplorerSettings(IgnoreApi = true)] public async Task<ActionResult> OnPlaybackStopped( [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 53b7349e7d..79e6536fb6 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Attributes; -using Jellyfin.Api.Constants; using Jellyfin.Extensions.Json; using MediaBrowser.Common.Api; using MediaBrowser.Common.Plugins; @@ -23,6 +22,7 @@ namespace Jellyfin.Api.Controllers; /// Plugins controller. /// </summary> [Authorize(Policy = Policies.RequiresElevation)] +[Tags("Plugin")] public class PluginsController : BaseJellyfinApiController { private readonly IInstallationManager _installationManager; @@ -136,7 +136,6 @@ public class PluginsController : BaseJellyfinApiController [HttpDelete("{pluginId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - [Obsolete("Please use the UninstallPluginByVersion API.")] public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId) { // If no version is given, return the current instance. diff --git a/Jellyfin.Api/Controllers/QuickConnectController.cs b/Jellyfin.Api/Controllers/QuickConnectController.cs index bdb2a4d20b..5c7b38e137 100644 --- a/Jellyfin.Api/Controllers/QuickConnectController.cs +++ b/Jellyfin.Api/Controllers/QuickConnectController.cs @@ -16,6 +16,7 @@ namespace Jellyfin.Api.Controllers; /// <summary> /// Quick connect controller. /// </summary> +[Tags("Authentication")] public class QuickConnectController : BaseJellyfinApiController { private readonly IQuickConnect _quickConnect; diff --git a/Jellyfin.Api/Controllers/ScheduledTasksController.cs b/Jellyfin.Api/Controllers/ScheduledTasksController.cs index 065466cbca..f122d0f5e5 100644 --- a/Jellyfin.Api/Controllers/ScheduledTasksController.cs +++ b/Jellyfin.Api/Controllers/ScheduledTasksController.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Jellyfin.Api.Constants; using MediaBrowser.Common.Api; using MediaBrowser.Model.Tasks; using Microsoft.AspNetCore.Authorization; @@ -15,6 +14,7 @@ namespace Jellyfin.Api.Controllers; /// Scheduled Tasks Controller. /// </summary> [Authorize(Policy = Policies.RequiresElevation)] +[Tags("ScheduledTask")] public class ScheduledTasksController : BaseJellyfinApiController { private readonly ITaskManager _taskManager; diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index ad08dc5f9b..a8feb206a4 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -22,6 +22,7 @@ namespace Jellyfin.Api.Controllers; /// Studios controller. /// </summary> [Authorize] +[Tags("Studio")] public class StudiosController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index e9e404076f..9c5515dd92 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -23,6 +23,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize] +[Tags("Suggestion")] public class SuggestionsController : BaseJellyfinApiController { private readonly IDtoService _dtoService; diff --git a/Jellyfin.Api/Controllers/TimeSyncController.cs b/Jellyfin.Api/Controllers/TimeSyncController.cs index d7304cf426..fe6e11f9e2 100644 --- a/Jellyfin.Api/Controllers/TimeSyncController.cs +++ b/Jellyfin.Api/Controllers/TimeSyncController.cs @@ -9,6 +9,7 @@ namespace Jellyfin.Api.Controllers; /// The time sync controller. /// </summary> [Route("")] +[Tags("System")] public class TimeSyncController : BaseJellyfinApiController { /// <summary> diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index 3e4bac89a5..f8c5bd4b87 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -15,6 +15,7 @@ namespace Jellyfin.Api.Controllers; /// The trailers controller. /// </summary> [Authorize] +[Tags("Trailer")] public class TrailersController : BaseJellyfinApiController { private readonly ItemsController _itemsController; diff --git a/Jellyfin.Api/Controllers/TrickplayController.cs b/Jellyfin.Api/Controllers/TrickplayController.cs index c9f8b36768..d7a10ce5f6 100644 --- a/Jellyfin.Api/Controllers/TrickplayController.cs +++ b/Jellyfin.Api/Controllers/TrickplayController.cs @@ -5,7 +5,6 @@ using System.Text; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Trickplay; @@ -21,6 +20,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize] +[Tags("TrickPlay")] public class TrickplayController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index c86c9b8f61..e45a100b77 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -27,6 +27,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("Shows")] [Authorize] +[Tags("Show")] public class TvShowsController : BaseJellyfinApiController { private readonly IUserManager _userManager; diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index f4e0c86143..d4e9b234c5 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -29,6 +29,7 @@ namespace Jellyfin.Api.Controllers; /// The universal audio controller. /// </summary> [Route("")] +[Tags("Audio")] public class UniversalAudioController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index ed4bba2bb1..c1d06bad36 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -26,6 +26,7 @@ namespace Jellyfin.Api.Controllers; /// </summary> [Route("")] [Authorize] +[Tags("UserView")] public class UserViewsController : BaseJellyfinApiController { private readonly IUserManager _userManager; diff --git a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs index b67c6fdb7b..2c8b452c35 100644 --- a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs +++ b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers; /// Attachments controller. /// </summary> [Route("Videos")] +[Tags("Video")] public class VideoAttachmentsController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 7854edc5ac..394a95ee5f 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -35,6 +35,7 @@ namespace Jellyfin.Api.Controllers; /// <summary> /// The videos controller. /// </summary> +[Tags("Video")] public class VideosController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 685334a9f0..aa6464ee7a 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -26,6 +26,7 @@ namespace Jellyfin.Api.Controllers; /// Years controller. /// </summary> [Authorize] +[Tags("Year")] public class YearsController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index c71c193e2e..a498901481 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -312,7 +312,7 @@ namespace Jellyfin.Server.Extensions return; } - if (prefixLength == NetworkConstants.MinimumIPv4PrefixSize) + if ((addr.AddressFamily == AddressFamily.InterNetwork && prefixLength == NetworkConstants.MinimumIPv4PrefixSize) || (addr.AddressFamily == AddressFamily.InterNetworkV6 && prefixLength == NetworkConstants.MinimumIPv6PrefixSize)) { options.KnownProxies.Add(addr); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 9f7e35d1ea..117f376724 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -420,7 +420,9 @@ namespace MediaBrowser.Controller.MediaEncoding } return state.VideoStream.VideoRange == VideoRange.HDR - && IsDoviWithHdr10Bl(state.VideoStream); + && (state.VideoStream.VideoRangeType == VideoRangeType.HDR10 + || IsHdr10Plus(state.VideoStream) + || IsDoviWithHdr10Bl(state.VideoStream)); } private bool IsVideoToolboxTonemapAvailable(EncodingJobInfo state, EncodingOptions options) @@ -435,8 +437,10 @@ namespace MediaBrowser.Controller.MediaEncoding // Certain DV profile 5 video works in Safari with direct playing, but the VideoToolBox does not produce correct mapping results with transcoding. // All other HDR formats working. return state.VideoStream.VideoRange == VideoRange.HDR - && (IsDoviWithHdr10Bl(state.VideoStream) - || state.VideoStream.VideoRangeType is VideoRangeType.HLG); + && (state.VideoStream.VideoRangeType == VideoRangeType.HDR10 + || IsHdr10Plus(state.VideoStream) + || IsDoviWithHdr10Bl(state.VideoStream) + || state.VideoStream.VideoRangeType == VideoRangeType.HLG); } private bool IsVideoStreamHevcRext(EncodingJobInfo state) diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 79f8675cbf..c0d1bc86e7 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -132,6 +132,7 @@ namespace MediaBrowser.Model.Net // Type image new("image/jpeg", ".jpg"), + new("image/jpg", ".jpg"), new("image/tiff", ".tiff"), new("image/x-png", ".png"), new("image/x-icon", ".ico"), diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index e0354dbdfa..727f481b65 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -255,7 +255,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError(ex, "Error in {Provider}", provider.Name); + _logger.LogError(ex, "Error in {Provider} for {Item}", provider.Name, item.Path ?? item.Name); } } @@ -339,7 +339,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError(ex, "Error in {Provider}", provider.Name); + _logger.LogError(ex, "Error in {Provider} for {Item}", provider.Name, item.Path ?? item.Name); } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index e9cb46eab5..abdfb1e3b7 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -820,7 +820,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - Logger.LogError(ex, "Error in {Provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider} for {Item}", provider.Name, logName); // If a local provider fails, consider that a failure refreshResult.ErrorMessage = ex.Message; @@ -886,7 +886,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { refreshResult.ErrorMessage = ex.Message; - Logger.LogError(ex, "Error in {Provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider} for {Item}", provider.Name, logName); } } @@ -935,7 +935,7 @@ namespace MediaBrowser.Providers.Manager { refreshResult.Failures++; refreshResult.ErrorMessage = ex.Message; - Logger.LogError(ex, "Error in {Provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider} for {Item}", provider.Name, logName); } } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 7188e9804e..f1582febf2 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Tasks; @@ -26,19 +27,24 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ISubtitleManager _subtitleManager; private readonly ILogger<SubtitleScheduledTask> _logger; private readonly ILocalizationManager _localization; + private readonly ISubtitleProvider[] _subtitleProviders; public SubtitleScheduledTask( ILibraryManager libraryManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger<SubtitleScheduledTask> logger, - ILocalizationManager localization) + ILocalizationManager localization, + IEnumerable<ISubtitleProvider> subtitleProviders) { _libraryManager = libraryManager; _config = config; _subtitleManager = subtitleManager; _logger = logger; _localization = localization; + _subtitleProviders = subtitleProviders + .OrderBy(i => i is IHasOrder hasOrder ? hasOrder.Order : 0) + .ToArray(); } public string Name => _localization.GetLocalizedString("TaskDownloadMissingSubtitles"); @@ -76,6 +82,12 @@ namespace MediaBrowser.Providers.MediaInfo continue; } + if (_subtitleProviders.All(provider => libraryOptions.DisabledSubtitleFetchers.Contains(provider.Name, StringComparer.OrdinalIgnoreCase))) + { + // Skip this library if all subtitle providers are disabled + continue; + } + subtitleDownloadLanguages = libraryOptions.SubtitleDownloadLanguages; skipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent; skipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs b/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs index 3eacc4f0f0..590cf795de 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Api/TmdbController.cs @@ -14,6 +14,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Api [Authorize] [Route("[controller]")] [Produces(MediaTypeNames.Application.Json)] + [ApiExplorerSettings(IgnoreApi = true)] public class TmdbController : ControllerBase { private readonly TmdbClientManager _tmdbClientManager; diff --git a/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs index e95df16354..60ed740609 100644 --- a/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -using AutoFixture.Xunit2; +using AutoFixture.Xunit3; using Jellyfin.Api.Controllers; using Jellyfin.Database.Implementations.Entities; using MediaBrowser.Common.Net; diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 6b84c4438f..253eab9d79 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -3,15 +3,16 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{A2FD0A10-8F62-4F9D-B171-FFDF9F0AFA9D}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> <PackageReference Include="AutoFixture" /> <PackageReference Include="AutoFixture.AutoMoq" /> - <PackageReference Include="AutoFixture.Xunit2" /> + <PackageReference Include="AutoFixture.Xunit3" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 8fef7fde05..f01d522e11 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -3,17 +3,18 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{DF194677-DFD3-42AF-9F75-D44D5A416478}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="coverlet.collector" /> - <PackageReference Include="FsCheck.Xunit" /> + <PackageReference Include="FsCheck.Xunit.v3" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 54d93b48cf..7db94f9c81 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -3,12 +3,13 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{462584F7-5023-4019-9EAC-B98CA458C0A0}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index 0364898298..6921fc8a97 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -1,8 +1,12 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> @@ -11,7 +15,7 @@ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> - <PackageReference Include="FsCheck.Xunit" /> + <PackageReference Include="FsCheck.Xunit.v3" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj b/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj index bdf6bc383a..a9b19e0104 100644 --- a/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj +++ b/tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj @@ -1,6 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net10.0</TargetFramework> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> @@ -14,12 +15,11 @@ <PackageReference Include="AutoFixture.AutoMoq" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Xunit.SkippableFact" /> <PackageReference Include="coverlet.collector" /> </ItemGroup> diff --git a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj index eab003715c..47a116ee42 100644 --- a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj @@ -1,8 +1,12 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj index 894bec6aa5..9a58c697f0 100644 --- a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj @@ -1,8 +1,12 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index 6b703e7416..c7065c670a 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -3,6 +3,7 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{28464062-0939-4AA7-9F7B-24DDDA61A7C0}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> @@ -14,11 +15,11 @@ <ItemGroup> <PackageReference Include="AutoFixture" /> <PackageReference Include="AutoFixture.AutoMoq" /> - <PackageReference Include="AutoFixture.Xunit2" /> + <PackageReference Include="AutoFixture.Xunit3" /> <PackageReference Include="coverlet.collector" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 8345b610e5..9e2a9a8873 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -1,15 +1,19 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="coverlet.collector" /> - <PackageReference Include="FsCheck.Xunit" /> + <PackageReference Include="FsCheck.Xunit.v3" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 7c26494487..1f3e42077f 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -3,12 +3,13 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{3998657B-1CCC-49DD-A19F-275DC8495F57}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 2d7f112109..09ba120a5e 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -3,17 +3,18 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="coverlet.collector" /> - <PackageReference Include="FsCheck.Xunit" /> + <PackageReference Include="FsCheck.Xunit.v3" /> <PackageReference Include="Moq" /> </ItemGroup> diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index 1263043a51..990544b5a8 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -1,5 +1,9 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <None Include="Test Data\**\*.*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> @@ -9,10 +13,10 @@ <ItemGroup> <PackageReference Include="AutoFixture" /> <PackageReference Include="AutoFixture.AutoMoq" /> - <PackageReference Include="AutoFixture.Xunit2" /> + <PackageReference Include="AutoFixture.Xunit3" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> diff --git a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs index 6997b51ac8..c06279af2d 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs @@ -25,12 +25,12 @@ public class ManagedFileSystemTests public void MoveDirectory_SameFileSystem_Correct() => MoveDirectoryInternal(); - [SkippableFact] + [Fact] public void MoveDirectory_DifferentFileSystem_Correct() { const string DestinationParent = "/dev/shm"; - Skip.IfNot(Directory.Exists(DestinationParent)); + Assert.SkipUnless(Directory.Exists(DestinationParent), $"{DestinationParent} is not available"); MoveDirectoryInternal(DestinationParent); } @@ -57,7 +57,7 @@ public class ManagedFileSystemTests Directory.Delete(destinationDir, true); } - [SkippableTheory] + [Theory] [InlineData("/Volumes/Library/Sample/Music/Playlists/", "../Beethoven/Misc/Moonlight Sonata.mp3", "/Volumes/Library/Sample/Music/Beethoven/Misc/Moonlight Sonata.mp3")] [InlineData("/Volumes/Library/Sample/Music/Playlists/", "../../Beethoven/Misc/Moonlight Sonata.mp3", "/Volumes/Library/Sample/Beethoven/Misc/Moonlight Sonata.mp3")] [InlineData("/Volumes/Library/Sample/Music/Playlists/", "Beethoven/Misc/Moonlight Sonata.mp3", "/Volumes/Library/Sample/Music/Playlists/Beethoven/Misc/Moonlight Sonata.mp3")] @@ -67,13 +67,13 @@ public class ManagedFileSystemTests string filePath, string expectedAbsolutePath) { - Skip.If(OperatingSystem.IsWindows()); + Assert.SkipWhen(OperatingSystem.IsWindows(), "Unix-only test"); var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath); Assert.Equal(expectedAbsolutePath, generatedPath); } - [SkippableTheory] + [Theory] [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"..\Beethoven\Misc\Moonlight Sonata.mp3", @"C:\Volumes\Library\Sample\Music\Beethoven\Misc\Moonlight Sonata.mp3")] [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"..\..\Beethoven\Misc\Moonlight Sonata.mp3", @"C:\Volumes\Library\Sample\Beethoven\Misc\Moonlight Sonata.mp3")] [InlineData(@"C:\\Volumes\Library\Sample\Music\Playlists\", @"Beethoven\Misc\Moonlight Sonata.mp3", @"C:\Volumes\Library\Sample\Music\Playlists\Beethoven\Misc\Moonlight Sonata.mp3")] @@ -83,7 +83,7 @@ public class ManagedFileSystemTests string filePath, string expectedAbsolutePath) { - Skip.IfNot(OperatingSystem.IsWindows()); + Assert.SkipUnless(OperatingSystem.IsWindows(), "Windows-only test"); var generatedPath = _sut.MakeAbsolutePath(folderPath, filePath); @@ -100,10 +100,10 @@ public class ManagedFileSystemTests Assert.Equal(expectedFileName, _sut.GetValidFilename(filename)); } - [SkippableFact] + [Fact] public void GetFileInfo_DanglingSymlink_ExistsFalse() { - Skip.If(OperatingSystem.IsWindows()); + Assert.SkipWhen(OperatingSystem.IsWindows(), "Unix-only test"); string testFileDir = Path.Combine(Path.GetTempPath(), "jellyfin-test-data"); string testFileName = Path.Combine(testFileDir, Path.GetRandomFileName() + "-danglingsym.link"); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 4e2604e6e1..958ffb8b6e 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -3,6 +3,7 @@ <!-- ProjectGuid is only included as a requirement for SonarQube analysis --> <PropertyGroup> <ProjectGuid>{2E3A1B4B-4225-4AAA-8B29-0181A84E7AEE}</ProjectGuid> + <OutputType>Exe</OutputType> </PropertyGroup> <ItemGroup> @@ -16,12 +17,11 @@ <PackageReference Include="AutoFixture.AutoMoq" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Xunit.SkippableFact" /> <PackageReference Include="coverlet.collector" /> </ItemGroup> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs index 3d8ea15a31..ede9e61536 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs @@ -192,13 +192,13 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins }; var metafilePath = Path.Combine(_pluginPath, "meta.json"); - await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options)); + await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options), TestContext.Current.CancellationToken); var pluginManager = new PluginManager(new NullLogger<PluginManager>(), null!, null!, _tempPath, new Version(1, 0)); await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); - var resultBytes = await File.ReadAllBytesAsync(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath, TestContext.Current.CancellationToken); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); @@ -232,7 +232,7 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); var metafilePath = Path.Combine(_pluginPath, "meta.json"); - var resultBytes = await File.ReadAllBytesAsync(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath, TestContext.Current.CancellationToken); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); @@ -252,13 +252,13 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins }; var metafilePath = Path.Combine(_pluginPath, "meta.json"); - await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options)); + await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options), TestContext.Current.CancellationToken); var pluginManager = new PluginManager(new NullLogger<PluginManager>(), null!, null!, _tempPath, new Version(1, 0)); await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); - var resultBytes = await File.ReadAllBytesAsync(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath, TestContext.Current.CancellationToken); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); @@ -278,13 +278,13 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins }; var metafilePath = Path.Combine(_pluginPath, "meta.json"); - await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options)); + await File.WriteAllTextAsync(metafilePath, JsonSerializer.Serialize(partial, _options), TestContext.Current.CancellationToken); var pluginManager = new PluginManager(new NullLogger<PluginManager>(), null!, null!, _tempPath, new Version(1, 0)); await pluginManager.PopulateManifest(packageInfo, new Version(1, 0), _pluginPath, PluginStatus.Active); - var resultBytes = await File.ReadAllBytesAsync(metafilePath); + var resultBytes = await File.ReadAllBytesAsync(metafilePath, TestContext.Current.CancellationToken); var result = JsonSerializer.Deserialize<PluginManifest>(resultBytes, _options); Assert.NotNull(result); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs index f58a3276ba..92e10c9f92 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs @@ -51,7 +51,8 @@ namespace Jellyfin.Server.Implementations.Tests.Updates PackageInfo[] packages = await _installationManager.GetPackages( "Jellyfin Stable", "https://repo.jellyfin.org/files/plugin/manifest.json", - false); + false, + TestContext.Current.CancellationToken); Assert.Equal(25, packages.Length); } @@ -62,7 +63,8 @@ namespace Jellyfin.Server.Implementations.Tests.Updates PackageInfo[] packages = await _installationManager.GetPackages( "Jellyfin Stable", "https://repo.jellyfin.org/files/plugin/manifest.json", - false); + false, + TestContext.Current.CancellationToken); packages = _installationManager.FilterPackages(packages, "Anime").ToArray(); Assert.Single(packages); @@ -74,7 +76,8 @@ namespace Jellyfin.Server.Implementations.Tests.Updates PackageInfo[] packages = await _installationManager.GetPackages( "Jellyfin Stable", "https://repo.jellyfin.org/files/plugin/manifest.json", - false); + false, + TestContext.Current.CancellationToken); packages = _installationManager.FilterPackages(packages, id: new Guid("a4df60c5-6ab4-412a-8f79-2cab93fb2bc5")).ToArray(); Assert.Single(packages); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs index 96ca96558d..ef084430e8 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs @@ -21,7 +21,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("System/ActivityLog/Entries"); + var response = await client.GetAsync("System/ActivityLog/Entries", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs index 8761cf69bc..1973af3f25 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs @@ -25,13 +25,13 @@ namespace Jellyfin.Server.Integration.Tests var client = _factory.CreateClient(); // Act - var response = await client.GetAsync("/Branding/Configuration"); + var response = await client.GetAsync("/Branding/Configuration", TestContext.Current.CancellationToken); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - await response.Content.ReadFromJsonAsync<BrandingOptions>(); + await response.Content.ReadFromJsonAsync<BrandingOptions>(TestContext.Current.CancellationToken); } [Theory] @@ -43,7 +43,7 @@ namespace Jellyfin.Server.Integration.Tests var client = _factory.CreateClient(); // Act - var response = await client.GetAsync(url); + var response = await client.GetAsync(url, TestContext.Current.CancellationToken); // Assert Assert.True(response.IsSuccessStatusCode); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index d92dbbd732..32bdc57265 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.GetAsync("web/ConfigurationPage?name=ThisPageDoesntExists"); + var response = await client.GetAsync("web/ConfigurationPage?name=ThisPageDoesntExists", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -37,12 +37,12 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.GetAsync("/web/ConfigurationPage?name=TestPlugin"); + var response = await client.GetAsync("/web/ConfigurationPage?name=TestPlugin", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Text.Html, response.Content.Headers.ContentType?.MediaType); StreamReader reader = new StreamReader(typeof(TestPlugin).Assembly.GetManifestResourceStream("Jellyfin.Server.Integration.Tests.TestPage.html")!); - Assert.Equal(await response.Content.ReadAsStringAsync(), await reader.ReadToEndAsync()); + Assert.Equal(await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken), await reader.ReadToEndAsync(TestContext.Current.CancellationToken)); } [Fact] @@ -50,7 +50,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.GetAsync("/web/ConfigurationPage?name=BrokenPage"); + var response = await client.GetAsync("/web/ConfigurationPage?name=BrokenPage", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -61,11 +61,11 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("/web/ConfigurationPages"); + var response = await client.GetAsync("/web/ConfigurationPages", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - _ = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOptions); + _ = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOptions, TestContext.Current.CancellationToken); // TODO: check content } @@ -75,13 +75,13 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("/web/ConfigurationPages?enableInMainMenu=true"); + var response = await client.GetAsync("/web/ConfigurationPages?enableInMainMenu=true", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var data = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOptions); + var data = await response.Content.ReadFromJsonAsync<ConfigurationPageInfo[]>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(data); Assert.Empty(data); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs index 64b9bd8e16..165e269814 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs @@ -28,7 +28,7 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Items"); + var response = await client.GetAsync("Items", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } @@ -40,7 +40,7 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid()), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -55,9 +55,9 @@ public sealed class ItemsControllerTests : IClassFixture<JellyfinApplicationFact var userDto = await AuthHelper.GetUserDtoAsync(client); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id)); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var items = await response.Content.ReadFromJsonAsync<QueryResult<BaseItemDto>>(_jsonOptions); + var items = await response.Content.ReadFromJsonAsync<QueryResult<BaseItemDto>>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(items); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs index 6881a92101..edbb46b34c 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs @@ -34,7 +34,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid()), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -45,7 +45,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa { var client = _factory.CreateClient(); - var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); + var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid()), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } @@ -57,7 +57,7 @@ public sealed class LibraryControllerTests : IClassFixture<JellyfinApplicationFa var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid())); + var response = await client.DeleteAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid()), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 36f1b726da..2de6408cc6 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -9,11 +9,11 @@ using Jellyfin.Extensions.Json; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using Xunit; -using Xunit.Priority; +using Xunit.v3.Priority; namespace Jellyfin.Server.Integration.Tests.Controllers; -[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] +[TestCaseOrderer(typeof(PriorityOrderer))] public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinApplicationFactory> { private readonly JellyfinApplicationFactory _factory; @@ -40,7 +40,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl } }; - using var response = await client.PostAsJsonAsync("Library/VirtualFolders?name=test&refreshLibrary=true", body, _jsonOptions); + using var response = await client.PostAsJsonAsync("Library/VirtualFolders?name=test&refreshLibrary=true", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } @@ -57,7 +57,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl LibraryOptions = new LibraryOptions() }; - using var response = await client.PostAsJsonAsync("Library/VirtualFolders/LibraryOptions", body, _jsonOptions); + using var response = await client.PostAsJsonAsync("Library/VirtualFolders/LibraryOptions", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -76,16 +76,16 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl } }; - using var createResponse = await client.PostAsJsonAsync("Library/VirtualFolders?name=test&refreshLibrary=true", createBody, _jsonOptions); + using var createResponse = await client.PostAsJsonAsync("Library/VirtualFolders?name=test&refreshLibrary=true", createBody, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, createResponse.StatusCode); - await Task.Delay(2000).ConfigureAwait(true); + await Task.Delay(2000, TestContext.Current.CancellationToken).ConfigureAwait(true); - using var response = await client.GetAsync("Library/VirtualFolders"); + using var response = await client.GetAsync("Library/VirtualFolders", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var library = await response.Content.ReadFromJsonAsAsyncEnumerable<VirtualFolderInfo>(_jsonOptions) - .FirstOrDefaultAsync(x => string.Equals(x?.Name, "test", StringComparison.Ordinal)); + var library = await response.Content.ReadFromJsonAsAsyncEnumerable<VirtualFolderInfo>(_jsonOptions, TestContext.Current.CancellationToken) + .FirstOrDefaultAsync(x => string.Equals(x?.Name, "test", StringComparison.Ordinal), TestContext.Current.CancellationToken); Assert.NotNull(library); var options = library.LibraryOptions; @@ -99,7 +99,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl LibraryOptions = options }; - using var response2 = await client.PostAsJsonAsync("Library/VirtualFolders/LibraryOptions", body, _jsonOptions); + using var response2 = await client.PostAsJsonAsync("Library/VirtualFolders/LibraryOptions", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, response2.StatusCode); } @@ -110,7 +110,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.DeleteAsync("Library/VirtualFolders?name=doesntExist"); + using var response = await client.DeleteAsync("Library/VirtualFolders?name=doesntExist", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -121,7 +121,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.DeleteAsync("Library/VirtualFolders?name=test&refreshLibrary=true"); + using var response = await client.DeleteAsync("Library/VirtualFolders?name=test&refreshLibrary=true", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LiveTvControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LiveTvControllerTests.cs index dd971fa87b..8ca9fb899e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LiveTvControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LiveTvControllerTests.cs @@ -32,7 +32,7 @@ public sealed class LiveTvControllerTests : IClassFixture<JellyfinApplicationFac Url = "Test Data/dummy.m3u8" }; - var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions); + var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } @@ -49,12 +49,12 @@ public sealed class LiveTvControllerTests : IClassFixture<JellyfinApplicationFac Url = "Test Data/dummy.m3u8" }; - var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions); + var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var responseBody = await response.Content.ReadFromJsonAsync<TunerHostInfo>(); + var responseBody = await response.Content.ReadFromJsonAsync<TunerHostInfo>(TestContext.Current.CancellationToken); Assert.NotNull(responseBody); Assert.Equal(body.Type, responseBody.Type); Assert.Equal(body.Url, responseBody.Url); @@ -72,7 +72,7 @@ public sealed class LiveTvControllerTests : IClassFixture<JellyfinApplicationFac Url = "Test Data/dummy.m3u8" }; - var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions); + var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -89,7 +89,7 @@ public sealed class LiveTvControllerTests : IClassFixture<JellyfinApplicationFac Url = "thisgoesnowhere" }; - var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions); + var response = await client.PostAsJsonAsync("/LiveTv/TunerHosts", body, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs index abc8b60099..194566bbf0 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs @@ -22,7 +22,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Playback/BitrateTest"); + var response = await client.GetAsync("Playback/BitrateTest", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); @@ -36,7 +36,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)); + var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Octet, response.Content.Headers.ContentType?.MediaType); @@ -53,7 +53,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture)); + var response = await client.GetAsync("Playback/BitrateTest?size=" + size.ToString(CultureInfo.InvariantCulture), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs index 6699c68346..82fdf715f8 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs @@ -29,7 +29,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); using var postContent = new ByteArrayContent(Array.Empty<byte>()); - var response = await client.PostAsync("Library/VirtualFolders/Name?name=+&newName=test", postContent); + var response = await client.PostAsync("Library/VirtualFolders/Name?name=+&newName=test", postContent, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -41,7 +41,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); using var postContent = new ByteArrayContent(Array.Empty<byte>()); - var response = await client.PostAsync("Library/VirtualFolders/Name?name=test&newName=+", postContent); + var response = await client.PostAsync("Library/VirtualFolders/Name?name=test&newName=+", postContent, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -53,7 +53,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); using var postContent = new ByteArrayContent(Array.Empty<byte>()); - var response = await client.PostAsync("Library/VirtualFolders/Name?name=doesnt+exist&newName=test", postContent); + var response = await client.PostAsync("Library/VirtualFolders/Name?name=doesnt+exist&newName=test", postContent, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -70,7 +70,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Path = "/this/path/doesnt/exist" }; - var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths", data, _jsonOptions); + var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths", data, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -87,7 +87,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers PathInfo = new MediaPathInfo("test") }; - var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths/Update", data, _jsonOptions); + var response = await client.PostAsJsonAsync("Library/VirtualFolders/Paths/Update", data, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -98,7 +98,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=+"); + var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=+", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode); } @@ -109,7 +109,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=none&path=%2Fthis%2Fpath%2Fdoesnt%2Fexist"); + var response = await client.DeleteAsync("Library/VirtualFolders/Paths?name=none&path=%2Fthis%2Fpath%2Fdoesnt%2Fexist", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs index f9982cf12b..3e14850613 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs @@ -20,7 +20,7 @@ public sealed class MusicGenreControllerTests : IClassFixture<JellyfinApplicatio var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("MusicGenres/Fake-MusicGenre"); + var response = await client.GetAsync("MusicGenres/Fake-MusicGenre", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs index c673773ffc..361edf3eb7 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs @@ -20,7 +20,7 @@ public class PersonsControllerTests : IClassFixture<JellyfinApplicationFactory> var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.GetAsync($"Persons/DoesntExist"); + using var response = await client.GetAsync($"Persons/DoesntExist", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs index 3b9ed17787..db271fc5cd 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs @@ -21,7 +21,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.DeleteAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}"); + using var response = await client.DeleteAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -31,7 +31,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.PostAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}", null); + using var response = await client.PostAsync($"Users/{Guid.NewGuid()}/PlayedItems/{Guid.NewGuid()}", null, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -43,7 +43,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory var userDto = await AuthHelper.GetUserDtoAsync(client); - using var response = await client.DeleteAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}"); + using var response = await client.DeleteAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -55,7 +55,7 @@ public class PlaystateControllerTests : IClassFixture<JellyfinApplicationFactory var userDto = await AuthHelper.GetUserDtoAsync(client); - using var response = await client.PostAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}", null); + using var response = await client.PostAsync($"Users/{userDto.Id}/PlayedItems/{Guid.NewGuid()}", null, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/PluginsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/PluginsControllerTests.cs index 547bfcc0ff..c982b9804d 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/PluginsControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/PluginsControllerTests.cs @@ -24,7 +24,7 @@ public sealed class PluginsControllerTests : IClassFixture<JellyfinApplicationFa { var client = _factory.CreateClient(); - var response = await client.GetAsync("/Plugins"); + var response = await client.GetAsync("/Plugins", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } @@ -35,11 +35,11 @@ public sealed class PluginsControllerTests : IClassFixture<JellyfinApplicationFa var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync("/Plugins"); + var response = await client.GetAsync("/Plugins", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - _ = await response.Content.ReadFromJsonAsync<PluginInfo[]>(JsonDefaults.Options); + _ = await response.Content.ReadFromJsonAsync<PluginInfo[]>(JsonDefaults.Options, TestContext.Current.CancellationToken); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs index c8ae2a88af..0e5d81a4d6 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs @@ -8,11 +8,11 @@ using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; using Jellyfin.Extensions.Json; using Xunit; -using Xunit.Priority; +using Xunit.v3.Priority; namespace Jellyfin.Server.Integration.Tests.Controllers { - [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] + [TestCaseOrderer(typeof(PriorityOrderer))] public sealed class StartupControllerTests : IClassFixture<JellyfinApplicationFactory> { private readonly JellyfinApplicationFactory _factory; @@ -37,14 +37,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers PreferredMetadataLanguage = "nl" }; - using var postResponse = await client.PostAsJsonAsync("/Startup/Configuration", config, _jsonOptions); + using var postResponse = await client.PostAsJsonAsync("/Startup/Configuration", config, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode); - using var getResponse = await client.GetAsync("/Startup/Configuration"); + using var getResponse = await client.GetAsync("/Startup/Configuration", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, getResponse.Content.Headers.ContentType?.MediaType); - var newConfig = await getResponse.Content.ReadFromJsonAsync<StartupConfigurationDto>(_jsonOptions); + var newConfig = await getResponse.Content.ReadFromJsonAsync<StartupConfigurationDto>(_jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(config.ServerName, newConfig!.ServerName); Assert.Equal(config.UICulture, newConfig.UICulture); Assert.Equal(config.MetadataCountryCode, newConfig.MetadataCountryCode); @@ -57,11 +57,11 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - using var response = await client.GetAsync("/Startup/User"); + using var response = await client.GetAsync("/Startup/User", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); - var user = await response.Content.ReadFromJsonAsync<StartupUserDto>(_jsonOptions); + var user = await response.Content.ReadFromJsonAsync<StartupUserDto>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(user); Assert.NotNull(user.Name); Assert.NotEmpty(user.Name); @@ -80,14 +80,14 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Password = "NewPassword" }; - var postResponse = await client.PostAsJsonAsync("/Startup/User", user, _jsonOptions); + var postResponse = await client.PostAsJsonAsync("/Startup/User", user, _jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, postResponse.StatusCode); - var getResponse = await client.GetAsync("/Startup/User"); + var getResponse = await client.GetAsync("/Startup/User", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, getResponse.Content.Headers.ContentType?.MediaType); - var newUser = await getResponse.Content.ReadFromJsonAsync<StartupUserDto>(_jsonOptions); + var newUser = await getResponse.Content.ReadFromJsonAsync<StartupUserDto>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(newUser); Assert.Equal(user.Name, newUser.Name); Assert.Null(newUser.Password); @@ -99,7 +99,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - var response = await client.PostAsync("/Startup/Complete", new ByteArrayContent(Array.Empty<byte>())); + var response = await client.PostAsync("/Startup/Complete", new ByteArrayContent(Array.Empty<byte>()), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NoContent, response.StatusCode); } @@ -109,7 +109,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - using var response = await client.GetAsync("/Startup/User"); + using var response = await client.GetAsync("/Startup/User", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index 04d1b3dc27..7ea56be731 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -10,11 +10,11 @@ using Jellyfin.Api.Models.UserDtos; using Jellyfin.Extensions.Json; using MediaBrowser.Model.Dto; using Xunit; -using Xunit.Priority; +using Xunit.v3.Priority; namespace Jellyfin.Server.Integration.Tests.Controllers { - [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] + [TestCaseOrderer(typeof(PriorityOrderer))] public sealed class UserControllerTests : IClassFixture<JellyfinApplicationFactory> { private const string TestUsername = "testUser01"; @@ -41,9 +41,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers { var client = _factory.CreateClient(); - using var response = await client.GetAsync("Users/Public"); + using var response = await client.GetAsync("Users/Public", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOptions); + var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOptions, TestContext.Current.CancellationToken); // User are hidden by default Assert.NotNull(users); Assert.Empty(users); @@ -56,9 +56,9 @@ namespace Jellyfin.Server.Integration.Tests.Controllers var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - using var response = await client.GetAsync("Users"); + using var response = await client.GetAsync("Users", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOptions); + var users = await response.Content.ReadFromJsonAsync<UserDto[]>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(users); Assert.Single(users); } @@ -89,7 +89,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await CreateUserByName(client, createRequest); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var user = await response.Content.ReadFromJsonAsync<UserDto>(_jsonOptions); + var user = await response.Content.ReadFromJsonAsync<UserDto>(_jsonOptions, TestContext.Current.CancellationToken); Assert.Equal(TestUsername, user!.Name); _testUserId = user.Id; @@ -128,7 +128,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers // access token can't be null here as the previous test populated it client.DefaultRequestHeaders.AddAuthHeader(_accessToken!); - using var response = await client.DeleteAsync($"User/{Guid.NewGuid()}"); + using var response = await client.DeleteAsync($"User/{Guid.NewGuid()}", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs index 98ad28f5bd..6e4fccd735 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs @@ -28,7 +28,7 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.GetAsync($"Users/{Guid.NewGuid()}/Items/Root"); + var response = await client.GetAsync($"Users/{Guid.NewGuid()}/Items/Root", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -54,7 +54,7 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid(), rootFolderDto.Id)); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, Guid.NewGuid(), rootFolderDto.Id), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -71,7 +71,7 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati var userDto = await AuthHelper.GetUserDtoAsync(client); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, Guid.NewGuid())); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, Guid.NewGuid()), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } @@ -84,9 +84,9 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati var userDto = await AuthHelper.GetUserDtoAsync(client); var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id); - var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}"); + var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto>(_jsonOptions); + var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(rootDto); } @@ -99,9 +99,9 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati var userDto = await AuthHelper.GetUserDtoAsync(client); var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id); - var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}/Intros"); + var response = await client.GetAsync($"Users/{userDto.Id}/Items/{rootFolderDto.Id}/Intros", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await response.Content.ReadFromJsonAsync<QueryResult<BaseItemDto>>(_jsonOptions); + var rootDto = await response.Content.ReadFromJsonAsync<QueryResult<BaseItemDto>>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(rootDto); } @@ -116,9 +116,9 @@ public sealed class UserLibraryControllerTests : IClassFixture<JellyfinApplicati var userDto = await AuthHelper.GetUserDtoAsync(client); var rootFolderDto = await AuthHelper.GetRootFolderDtoAsync(client, userDto.Id); - var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, rootFolderDto.Id)); + var response = await client.GetAsync(string.Format(CultureInfo.InvariantCulture, format, userDto.Id, rootFolderDto.Id), TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto[]>(_jsonOptions); + var rootDto = await response.Content.ReadFromJsonAsync<BaseItemDto[]>(_jsonOptions, TestContext.Current.CancellationToken); Assert.NotNull(rootDto); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs index 1916ced12c..e0630ff443 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs @@ -21,7 +21,7 @@ public sealed class VideosControllerTests : IClassFixture<JellyfinApplicationFac var client = _factory.CreateClient(); client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - var response = await client.DeleteAsync($"Videos/{Guid.NewGuid()}"); + var response = await client.DeleteAsync($"Videos/{Guid.NewGuid()}", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs index d2249cdc3b..a343423b4d 100644 --- a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs +++ b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs @@ -27,9 +27,9 @@ namespace Jellyfin.Server.Integration.Tests { var client = _factory.CreateClient(); - var response = await client.GetAsync("Encoder/UrlDecode?" + sourceUrl); + var response = await client.GetAsync("Encoder/UrlDecode?" + sourceUrl, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string reply = await response.Content.ReadAsStringAsync(); + string reply = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Equal(unencodedUrl, reply); } @@ -40,9 +40,9 @@ namespace Jellyfin.Server.Integration.Tests { var client = _factory.CreateClient(); - var response = await client.GetAsync("Encoder/UrlArrayDecode?" + sourceUrl); + var response = await client.GetAsync("Encoder/UrlArrayDecode?" + sourceUrl, TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - string reply = await response.Content.ReadAsStringAsync(); + string reply = await response.Content.ReadAsStringAsync(TestContext.Current.CancellationToken); Assert.Equal(unencodedUrl, reply); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 7b0e23788b..7abad8bb84 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -1,17 +1,21 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <PackageReference Include="AutoFixture" /> <PackageReference Include="AutoFixture.AutoMoq" /> - <PackageReference Include="AutoFixture.Xunit2" /> + <PackageReference Include="AutoFixture.Xunit3" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> - <PackageReference Include="Xunit.Priority" /> + <PackageReference Include="Xunit.v3.Priority" /> <PackageReference Include="coverlet.collector" /> <PackageReference Include="Moq" /> </ItemGroup> diff --git a/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs index 1ea79f7deb..baeaf4d0cb 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Server.Integration.Tests.Middleware AllowAutoRedirect = false }); - var response = await client.GetAsync("robots.txt"); + var response = await client.GetAsync("robots.txt", TestContext.Current.CancellationToken); Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); Assert.Equal("web/robots.txt", response.Headers.Location?.ToString()); diff --git a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs index 62cdd25aec..17a8a55222 100644 --- a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs @@ -3,7 +3,6 @@ using System.Reflection; using System.Threading.Tasks; using MediaBrowser.Model.IO; using Xunit; -using Xunit.Abstractions; namespace Jellyfin.Server.Integration.Tests { @@ -25,7 +24,7 @@ namespace Jellyfin.Server.Integration.Tests var client = _factory.CreateClient(); // Act - var response = await client.GetAsync("/api-docs/openapi.json"); + var response = await client.GetAsync("/api-docs/openapi.json", TestContext.Current.CancellationToken); // Assert response.EnsureSuccessStatusCode(); @@ -35,7 +34,7 @@ namespace Jellyfin.Server.Integration.Tests string outputPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "openapi.json")); _outputHelper.WriteLine("Writing OpenAPI Spec JSON to '{0}'.", outputPath); await using var fs = AsyncFile.Create(outputPath); - await response.Content.CopyToAsync(fs); + await response.Content.CopyToAsync(fs, TestContext.Current.CancellationToken); } } } diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 21596e0ed2..3ad5310c6b 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -1,12 +1,16 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <PackageReference Include="AutoFixture" /> <PackageReference Include="AutoFixture.AutoMoq" /> - <PackageReference Include="AutoFixture.Xunit2" /> + <PackageReference Include="AutoFixture.Xunit3" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" /> <PackageReference Include="Microsoft.NET.Test.Sdk" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> diff --git a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs index 14f4c33b6b..e788f43b86 100644 --- a/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs +++ b/tests/Jellyfin.Server.Tests/ParseNetworkTests.cs @@ -23,8 +23,8 @@ namespace Jellyfin.Server.Tests true, true, new string[] { "192.168.t", "127.0.0.1", "::1", "1234.1232.12.1234" }, - new IPAddress[] { IPAddress.Loopback }, - new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) }); + new IPAddress[] { IPAddress.Loopback, IPAddress.IPv6Loopback }, + Array.Empty<IPNetwork>()); data.Add( true, @@ -37,8 +37,8 @@ namespace Jellyfin.Server.Tests true, true, new string[] { "::1" }, - Array.Empty<IPAddress>(), - new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) }); + new IPAddress[] { IPAddress.IPv6Loopback }, + Array.Empty<IPNetwork>()); data.Add( false, @@ -58,15 +58,15 @@ namespace Jellyfin.Server.Tests false, true, new string[] { "localhost" }, - Array.Empty<IPAddress>(), - new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) }); + new IPAddress[] { IPAddress.IPv6Loopback }, + Array.Empty<IPNetwork>()); data.Add( true, true, new string[] { "localhost" }, - new IPAddress[] { IPAddress.Loopback }, - new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) }); + new IPAddress[] { IPAddress.Loopback, IPAddress.IPv6Loopback }, + Array.Empty<IPNetwork>()); return data; } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index 9fe0744de1..3b39fe72d6 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -1,5 +1,9 @@ <Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <OutputType>Exe</OutputType> + </PropertyGroup> + <ItemGroup> <None Include="Test Data\**\*.*"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> @@ -9,7 +13,7 @@ <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" /> <PackageReference Include="Moq" /> - <PackageReference Include="xunit" /> + <PackageReference Include="xunit.v3" /> <PackageReference Include="xunit.runner.visualstudio"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> |
