aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Api.Tests/Controllers/UserControllerTests.cs2
-rw-r--r--tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj5
-rw-r--r--tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj5
-rw-r--r--tests/Jellyfin.Controller.Tests/Entities/InternalItemsQueryTests.cs26
-rw-r--r--tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj3
-rw-r--r--tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj8
-rw-r--r--tests/Jellyfin.LiveTv.Tests/Jellyfin.LiveTv.Tests.csproj4
-rw-r--r--tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj6
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj6
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj5
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs4
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Subtitles/FilterEventsTests.cs282
-rw-r--r--tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs55
-rw-r--r--tests/Jellyfin.Model.Tests/Extensions/EnumerableExtensionsTests.cs116
-rw-r--r--tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj8
-rw-r--r--tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj3
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs2
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs44
-rw-r--r--tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj5
-rw-r--r--tests/Jellyfin.Networking.Tests/NetworkParseTests.cs2
-rw-r--r--tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj8
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/IO/ManagedFileSystemTests.cs16
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj4
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs23
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs14
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs9
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/ActivityLogControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs6
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs16
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs8
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryControllerTests.cs6
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs24
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/LiveTvControllerTests.cs10
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/MediaInfoControllerTests.cs6
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs14
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/MusicGenreControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/PersonsControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/PlaystateControllerTests.cs8
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/PluginsControllerTests.cs6
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs24
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs16
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs18
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/VideosControllerTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs8
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj10
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Middleware/RobotsRedirectionMiddlewareTests.cs2
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs5
-rw-r--r--tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj8
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj6
49 files changed, 728 insertions, 146 deletions
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/Entities/InternalItemsQueryTests.cs b/tests/Jellyfin.Controller.Tests/Entities/InternalItemsQueryTests.cs
new file mode 100644
index 0000000000..7093b25006
--- /dev/null
+++ b/tests/Jellyfin.Controller.Tests/Entities/InternalItemsQueryTests.cs
@@ -0,0 +1,26 @@
+using System;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Querying;
+using Xunit;
+
+namespace Jellyfin.Controller.Tests.Entities;
+
+public class InternalItemsQueryTests
+{
+ public static TheoryData<ItemFilter[]> ApplyFilters_Invalid()
+ {
+ var data = new TheoryData<ItemFilter[]>();
+ data.Add([ItemFilter.IsFolder, ItemFilter.IsNotFolder]);
+ data.Add([ItemFilter.IsPlayed, ItemFilter.IsUnplayed]);
+ data.Add([ItemFilter.Likes, ItemFilter.Dislikes]);
+ return data;
+ }
+
+ [Theory]
+ [MemberData(nameof(ApplyFilters_Invalid))]
+ public void ApplyFilters_Invalid_ThrowsArgumentException(ItemFilter[] filters)
+ {
+ var query = new InternalItemsQuery();
+ Assert.Throws<ArgumentException>(() => query.ApplyFilters(filters));
+ }
+}
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.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
index 8ebbd029ac..3369af0e84 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
@@ -209,8 +209,8 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
Assert.Equal("mkv,webm", res.Container);
Assert.Equal(2, res.MediaStreams.Count);
-
- Assert.False(res.MediaStreams[0].IsAVC);
+ Assert.Equal(540, res.MediaStreams[0].Width);
+ Assert.Equal(360, res.MediaStreams[0].Height);
}
[Fact]
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/FilterEventsTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/FilterEventsTests.cs
new file mode 100644
index 0000000000..5f84e85592
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/FilterEventsTests.cs
@@ -0,0 +1,282 @@
+using System;
+using AutoFixture;
+using AutoFixture.AutoMoq;
+using MediaBrowser.MediaEncoding.Subtitles;
+using MediaBrowser.Model.MediaInfo;
+using Xunit;
+
+namespace Jellyfin.MediaEncoding.Subtitles.Tests
+{
+ public class FilterEventsTests
+ {
+ private readonly SubtitleEncoder _encoder;
+
+ public FilterEventsTests()
+ {
+ var fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
+ _encoder = fixture.Create<SubtitleEncoder>();
+ }
+
+ [Fact]
+ public void FilterEvents_SubtitleSpanningSegmentBoundary_IsRetained()
+ {
+ // Subtitle starts at 5s, ends at 15s.
+ // Segment requested from 10s to 20s.
+ // The subtitle is still on screen at 10s and should NOT be dropped.
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Still on screen")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(5).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(15).Ticks
+ },
+ new SubtitleTrackEvent("2", "Next subtitle")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(12).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(17).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(20).Ticks,
+ preserveTimestamps: true);
+
+ Assert.Equal(2, track.TrackEvents.Count);
+ Assert.Equal("1", track.TrackEvents[0].Id);
+ Assert.Equal("2", track.TrackEvents[1].Id);
+ }
+
+ [Fact]
+ public void FilterEvents_SubtitleFullyBeforeSegment_IsDropped()
+ {
+ // Subtitle starts at 2s, ends at 5s.
+ // Segment requested from 10s.
+ // The subtitle ended before the segment — should be dropped.
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Already gone")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(2).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(5).Ticks
+ },
+ new SubtitleTrackEvent("2", "Visible")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(12).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(17).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(20).Ticks,
+ preserveTimestamps: true);
+
+ Assert.Single(track.TrackEvents);
+ Assert.Equal("2", track.TrackEvents[0].Id);
+ }
+
+ [Fact]
+ public void FilterEvents_SubtitleAfterSegment_IsDropped()
+ {
+ // Segment is 10s-20s, subtitle starts at 25s.
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "In range")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(12).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(15).Ticks
+ },
+ new SubtitleTrackEvent("2", "After segment")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(25).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(30).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(20).Ticks,
+ preserveTimestamps: true);
+
+ Assert.Single(track.TrackEvents);
+ Assert.Equal("1", track.TrackEvents[0].Id);
+ }
+
+ [Fact]
+ public void FilterEvents_PreserveTimestampsFalse_AdjustsTimestamps()
+ {
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Subtitle")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(15).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(20).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(30).Ticks,
+ preserveTimestamps: false);
+
+ Assert.Single(track.TrackEvents);
+ // Timestamps should be shifted back by 10s
+ Assert.Equal(TimeSpan.FromSeconds(5).Ticks, track.TrackEvents[0].StartPositionTicks);
+ Assert.Equal(TimeSpan.FromSeconds(10).Ticks, track.TrackEvents[0].EndPositionTicks);
+ }
+
+ [Fact]
+ public void FilterEvents_PreserveTimestampsTrue_KeepsOriginalTimestamps()
+ {
+ var startTicks = TimeSpan.FromSeconds(15).Ticks;
+ var endTicks = TimeSpan.FromSeconds(20).Ticks;
+
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Subtitle")
+ {
+ StartPositionTicks = startTicks,
+ EndPositionTicks = endTicks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(30).Ticks,
+ preserveTimestamps: true);
+
+ Assert.Single(track.TrackEvents);
+ Assert.Equal(startTicks, track.TrackEvents[0].StartPositionTicks);
+ Assert.Equal(endTicks, track.TrackEvents[0].EndPositionTicks);
+ }
+
+ [Fact]
+ public void FilterEvents_SubtitleEndingExactlyAtSegmentStart_IsRetained()
+ {
+ // Subtitle ends exactly when the segment begins.
+ // EndPositionTicks == startPositionTicks means (end - start) == 0, not < 0,
+ // so SkipWhile stops and the subtitle is retained.
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Boundary subtitle")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(5).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(10).Ticks
+ },
+ new SubtitleTrackEvent("2", "In range")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(12).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(15).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(20).Ticks,
+ preserveTimestamps: true);
+
+ Assert.Equal(2, track.TrackEvents.Count);
+ Assert.Equal("1", track.TrackEvents[0].Id);
+ }
+
+ [Fact]
+ public void FilterEvents_SpanningBoundaryWithTimestampAdjustment_DoesNotProduceNegativeTimestamps()
+ {
+ // Subtitle starts at 5s, ends at 15s.
+ // Segment requested from 10s to 20s, preserveTimestamps = false.
+ // The subtitle spans the boundary and is retained, but shifting
+ // StartPositionTicks by -10s would produce -5s (negative).
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Spans boundary")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(5).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(15).Ticks
+ },
+ new SubtitleTrackEvent("2", "Fully in range")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(12).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(17).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: TimeSpan.FromSeconds(20).Ticks,
+ preserveTimestamps: false);
+
+ Assert.Equal(2, track.TrackEvents.Count);
+ // Subtitle 1: start should be clamped to 0, not -5s
+ Assert.True(track.TrackEvents[0].StartPositionTicks >= 0, "StartPositionTicks must not be negative");
+ Assert.Equal(TimeSpan.FromSeconds(5).Ticks, track.TrackEvents[0].EndPositionTicks);
+ // Subtitle 2: normal shift (12s - 10s = 2s, 17s - 10s = 7s)
+ Assert.Equal(TimeSpan.FromSeconds(2).Ticks, track.TrackEvents[1].StartPositionTicks);
+ Assert.Equal(TimeSpan.FromSeconds(7).Ticks, track.TrackEvents[1].EndPositionTicks);
+ }
+
+ [Fact]
+ public void FilterEvents_NoEndTimeTicks_ReturnsAllFromStartPosition()
+ {
+ var track = new SubtitleTrackInfo
+ {
+ TrackEvents = new[]
+ {
+ new SubtitleTrackEvent("1", "Before")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(2).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(4).Ticks
+ },
+ new SubtitleTrackEvent("2", "After")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(12).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(15).Ticks
+ },
+ new SubtitleTrackEvent("3", "Much later")
+ {
+ StartPositionTicks = TimeSpan.FromSeconds(500).Ticks,
+ EndPositionTicks = TimeSpan.FromSeconds(505).Ticks
+ }
+ }
+ };
+
+ _encoder.FilterEvents(
+ track,
+ startPositionTicks: TimeSpan.FromSeconds(10).Ticks,
+ endTimeTicks: 0,
+ preserveTimestamps: true);
+
+ Assert.Equal(2, track.TrackEvents.Count);
+ Assert.Equal("2", track.TrackEvents[0].Id);
+ Assert.Equal("3", track.TrackEvents[1].Id);
+ }
+ }
+}
diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
index 2c1080ffe3..8269ae58cd 100644
--- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
+++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs
@@ -617,5 +617,60 @@ namespace Jellyfin.Model.Tests
return (path, query, filename, extension);
}
+
+ [Theory]
+ // EnableSubtitleExtraction = false, internal subtitles
+ [InlineData("srt", "srt", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)]
+ [InlineData("srt", "srt", false, false, PlayMethod.DirectPlay, SubtitleDeliveryMethod.External)]
+ [InlineData("pgssub", "pgssub", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)]
+ [InlineData("pgssub", "pgssub", false, false, PlayMethod.DirectPlay, SubtitleDeliveryMethod.External)]
+ [InlineData("pgssub", "srt", false, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)]
+ // EnableSubtitleExtraction = false, external subtitles
+ [InlineData("srt", "srt", false, true, PlayMethod.Transcode, SubtitleDeliveryMethod.External)]
+ // EnableSubtitleExtraction = true, internal subtitles
+ [InlineData("srt", "srt", true, false, PlayMethod.Transcode, SubtitleDeliveryMethod.External)]
+ [InlineData("pgssub", "pgssub", true, false, PlayMethod.Transcode, SubtitleDeliveryMethod.External)]
+ [InlineData("pgssub", "pgssub", true, false, PlayMethod.DirectPlay, SubtitleDeliveryMethod.External)]
+ [InlineData("pgssub", "srt", true, false, PlayMethod.Transcode, SubtitleDeliveryMethod.Encode)]
+ // EnableSubtitleExtraction = true, external subtitles
+ [InlineData("srt", "srt", true, true, PlayMethod.Transcode, SubtitleDeliveryMethod.External)]
+ public void GetSubtitleProfile_RespectsExtractionSetting(
+ string codec,
+ string profileFormat,
+ bool enableSubtitleExtraction,
+ bool isExternal,
+ PlayMethod playMethod,
+ SubtitleDeliveryMethod expectedMethod)
+ {
+ var mediaSource = new MediaSourceInfo();
+ var subtitleStream = new MediaStream
+ {
+ Type = MediaStreamType.Subtitle,
+ Index = 0,
+ IsExternal = isExternal,
+ Path = isExternal ? "/media/sub." + codec : null,
+ Codec = codec,
+ SupportsExternalStream = MediaStream.IsTextFormat(codec)
+ };
+
+ var subtitleProfiles = new[]
+ {
+ new SubtitleProfile { Format = profileFormat, Method = SubtitleDeliveryMethod.External }
+ };
+
+ var transcoderSupport = new Mock<ITranscoderSupport>();
+ transcoderSupport.Setup(t => t.CanExtractSubtitles(It.IsAny<string>())).Returns(enableSubtitleExtraction);
+
+ var result = StreamBuilder.GetSubtitleProfile(
+ mediaSource,
+ subtitleStream,
+ subtitleProfiles,
+ playMethod,
+ transcoderSupport.Object,
+ null,
+ null);
+
+ Assert.Equal(expectedMethod, result.Method);
+ }
}
}
diff --git a/tests/Jellyfin.Model.Tests/Extensions/EnumerableExtensionsTests.cs b/tests/Jellyfin.Model.Tests/Extensions/EnumerableExtensionsTests.cs
new file mode 100644
index 0000000000..135a139cdf
--- /dev/null
+++ b/tests/Jellyfin.Model.Tests/Extensions/EnumerableExtensionsTests.cs
@@ -0,0 +1,116 @@
+using System.Linq;
+using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Providers;
+using Xunit;
+
+namespace Jellyfin.Model.Tests.Extensions;
+
+public class EnumerableExtensionsTests
+{
+ [Fact]
+ public void OrderByLanguageDescending_PreferredLanguageFirst()
+ {
+ var images = new[]
+ {
+ new RemoteImageInfo { Language = "en", CommunityRating = 5.0, VoteCount = 100 },
+ new RemoteImageInfo { Language = "de", CommunityRating = 9.0, VoteCount = 200 },
+ new RemoteImageInfo { Language = null, CommunityRating = 7.0, VoteCount = 50 },
+ new RemoteImageInfo { Language = "fr", CommunityRating = 8.0, VoteCount = 150 },
+ };
+
+ var result = images.OrderByLanguageDescending("de").ToList();
+
+ Assert.Equal("de", result[0].Language);
+ Assert.Equal("en", result[1].Language);
+ Assert.Null(result[2].Language);
+ Assert.Equal("fr", result[3].Language);
+ }
+
+ [Fact]
+ public void OrderByLanguageDescending_EnglishBeforeNoLanguage()
+ {
+ var images = new[]
+ {
+ new RemoteImageInfo { Language = null, CommunityRating = 9.0, VoteCount = 500 },
+ new RemoteImageInfo { Language = "en", CommunityRating = 3.0, VoteCount = 10 },
+ };
+
+ var result = images.OrderByLanguageDescending("de").ToList();
+
+ // English should come before no-language, even with lower rating
+ Assert.Equal("en", result[0].Language);
+ Assert.Null(result[1].Language);
+ }
+
+ [Fact]
+ public void OrderByLanguageDescending_SameLanguageSortedByRatingThenVoteCount()
+ {
+ var images = new[]
+ {
+ new RemoteImageInfo { Language = "de", CommunityRating = 5.0, VoteCount = 100 },
+ new RemoteImageInfo { Language = "de", CommunityRating = 9.0, VoteCount = 50 },
+ new RemoteImageInfo { Language = "de", CommunityRating = 9.0, VoteCount = 200 },
+ };
+
+ var result = images.OrderByLanguageDescending("de").ToList();
+
+ Assert.Equal(200, result[0].VoteCount);
+ Assert.Equal(50, result[1].VoteCount);
+ Assert.Equal(100, result[2].VoteCount);
+ }
+
+ [Fact]
+ public void OrderByLanguageDescending_NullRequestedLanguage_DefaultsToEnglish()
+ {
+ var images = new[]
+ {
+ new RemoteImageInfo { Language = "fr", CommunityRating = 9.0, VoteCount = 500 },
+ new RemoteImageInfo { Language = "en", CommunityRating = 5.0, VoteCount = 10 },
+ };
+
+ var result = images.OrderByLanguageDescending(null!).ToList();
+
+ // With null requested language, English becomes the preferred language (score 4)
+ Assert.Equal("en", result[0].Language);
+ Assert.Equal("fr", result[1].Language);
+ }
+
+ [Fact]
+ public void OrderByLanguageDescending_EnglishRequested_NoDoubleBoost()
+ {
+ // When requested language IS English, "en" gets score 4 (requested match),
+ // no-language gets score 2, others get score 0
+ var images = new[]
+ {
+ new RemoteImageInfo { Language = null, CommunityRating = 9.0, VoteCount = 500 },
+ new RemoteImageInfo { Language = "en", CommunityRating = 3.0, VoteCount = 10 },
+ new RemoteImageInfo { Language = "fr", CommunityRating = 8.0, VoteCount = 300 },
+ };
+
+ var result = images.OrderByLanguageDescending("en").ToList();
+
+ Assert.Equal("en", result[0].Language);
+ Assert.Null(result[1].Language);
+ Assert.Equal("fr", result[2].Language);
+ }
+
+ [Fact]
+ public void OrderByLanguageDescending_FullPriorityOrder()
+ {
+ var images = new[]
+ {
+ new RemoteImageInfo { Language = "fr", CommunityRating = 9.0, VoteCount = 500 },
+ new RemoteImageInfo { Language = null, CommunityRating = 8.0, VoteCount = 400 },
+ new RemoteImageInfo { Language = "en", CommunityRating = 7.0, VoteCount = 300 },
+ new RemoteImageInfo { Language = "de", CommunityRating = 6.0, VoteCount = 200 },
+ };
+
+ var result = images.OrderByLanguageDescending("de").ToList();
+
+ // Expected order: de (requested) > en > no-language > fr (other)
+ Assert.Equal("de", result[0].Language);
+ Assert.Equal("en", result[1].Language);
+ Assert.Null(result[2].Language);
+ Assert.Equal("fr", result[3].Language);
+ }
+}
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.Naming.Tests/Video/CleanStringTests.cs b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs
index 6c9c98cbe8..df5819d747 100644
--- a/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/CleanStringTests.cs
@@ -29,6 +29,7 @@ namespace Jellyfin.Naming.Tests.Video
[InlineData("[OCN] 애타는 로맨스 720p-NEXT", "애타는 로맨스")]
[InlineData("[tvN] 혼술남녀.E01-E16.720p-NEXT", "혼술남녀")]
[InlineData("[tvN] 연애말고 결혼 E01~E16 END HDTV.H264.720p-WITH", "연애말고 결혼")]
+ [InlineData("2026年01月10日23時00分00秒-[新]TRIGUN STARGAZE[字].mp4", "2026年01月10日23時00分00秒-[新]TRIGUN STARGAZE")]
// FIXME: [InlineData("After The Sunset - [0004].mkv", "After The Sunset")]
public void CleanStringTest_NeedsCleaning_Success(string input, string expectedName)
{
@@ -44,6 +45,7 @@ namespace Jellyfin.Naming.Tests.Video
[InlineData("American.Psycho.mkv")]
[InlineData("American Psycho.mkv")]
[InlineData("Run lola run (lola rennt) (2009).mp4")]
+ [InlineData("2026年01月05日00時55分00秒-[新]違国日記【ANiMiDNiGHT!!!】#1.mp4")]
public void CleanStringTest_DoesntNeedCleaning_False(string? input)
{
Assert.False(VideoResolver.TryCleanString(input, _namingOptions, out var newName));
diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
index 6b13986957..2fb45600b1 100644
--- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
+++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using Emby.Naming.Common;
@@ -269,8 +270,13 @@ namespace Jellyfin.Naming.Tests.Video
files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
_namingOptions).ToList();
- Assert.Equal(7, result.Count);
- Assert.Empty(result[0].AlternateVersions);
+ Assert.Single(result);
+ Assert.Equal(6, result[0].AlternateVersions.Count);
+
+ // Verify 3D recognition is preserved on alternate versions
+ var hsbs = result[0].AlternateVersions.First(v => v.Path.Contains("3d-hsbs", StringComparison.Ordinal));
+ Assert.True(hsbs.Is3D);
+ Assert.Equal("hsbs", hsbs.Format3D);
}
[Fact]
@@ -435,5 +441,39 @@ namespace Jellyfin.Naming.Tests.Video
Assert.Empty(result);
}
+
+ [Fact]
+ public void Resolve_GivenUnderscoreSeparator_GroupsVersions()
+ {
+ var files = new[]
+ {
+ "/movies/Movie (2020)/Movie (2020)_4K.mkv",
+ "/movies/Movie (2020)/Movie (2020)_1080p.mkv"
+ };
+
+ var result = VideoListResolver.Resolve(
+ files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
+ _namingOptions).ToList();
+
+ Assert.Single(result);
+ Assert.Single(result[0].AlternateVersions);
+ }
+
+ [Fact]
+ public void Resolve_GivenDotSeparator_GroupsVersions()
+ {
+ var files = new[]
+ {
+ "/movies/Movie (2020)/Movie (2020).UHD.mkv",
+ "/movies/Movie (2020)/Movie (2020).1080p.mkv"
+ };
+
+ var result = VideoListResolver.Resolve(
+ files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(),
+ _namingOptions).ToList();
+
+ Assert.Single(result);
+ Assert.Single(result[0].AlternateVersions);
+ }
}
}
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.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
index 871604514b..b63009d6a5 100644
--- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
+++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs
@@ -377,6 +377,8 @@ namespace Jellyfin.Networking.Tests
[InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209", "10.0.0.1")] // LAN not bound, so return external.
[InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "8.8.8.8", "10.0.0.1")] // return external bind address
[InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "192.168.1.210", "192.168.1.208")] // return LAN bind address
+ // Cross-subnet IPv4 request should return IPv4, not IPv6 (Issue #15898)
+ [InlineData("192.168.1.208/24,-16,eth16|fd00::1/64,10,eth7", "192.168.1.0/24", "", "192.168.2.100", "192.168.1.208")]
public void GetBindInterface_ValidSourceGiven_Success(string interfaces, string lan, string bind, string source, string result)
{
var conf = new NetworkConfiguration
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/Localization/LocalizationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs
index e60522bf78..5bcfc580ff 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Localization/LocalizationManagerTests.cs
@@ -22,7 +22,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
});
var countries = localizationManager.GetCountries().ToList();
- Assert.Equal(139, countries.Count);
+ Assert.Equal(140, countries.Count);
var germany = countries.FirstOrDefault(x => x.Name.Equals("DE", StringComparison.Ordinal));
Assert.NotNull(germany);
@@ -41,7 +41,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
await localizationManager.LoadAll();
var cultures = localizationManager.GetCultures().ToList();
- Assert.Equal(194, cultures.Count);
+ Assert.Equal(496, cultures.Count);
var germany = cultures.FirstOrDefault(x => x.TwoLetterISOLanguageName.Equals("de", StringComparison.Ordinal));
Assert.NotNull(germany);
@@ -99,6 +99,25 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
Assert.Contains("ger", germany.ThreeLetterISOLanguageNames);
}
+ [Theory]
+ [InlineData("mul", "Multiple languages")]
+ [InlineData("und", "Undetermined")]
+ [InlineData("mis", "Uncoded languages")]
+ [InlineData("zxx", "No linguistic content; Not applicable")]
+ public async Task FindLanguageInfo_ISO6392Only_Success(string code, string expectedDisplayName)
+ {
+ var localizationManager = Setup(new ServerConfiguration
+ {
+ UICulture = "en-US"
+ });
+ await localizationManager.LoadAll();
+
+ var culture = localizationManager.FindLanguageInfo(code);
+ Assert.NotNull(culture);
+ Assert.Equal(expectedDisplayName, culture.DisplayName);
+ Assert.Equal(code, culture.ThreeLetterISOLanguageName);
+ }
+
[Fact]
public async Task GetParentalRatings_Default_Success()
{
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.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>