diff options
Diffstat (limited to 'tests')
24 files changed, 1036 insertions, 27 deletions
diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 45c93987b..07972bb42 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -21,7 +21,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> <PackageReference Include="Moq" Version="4.15.2" /> </ItemGroup> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index 19c5612c0..fdeeda5a3 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -16,7 +16,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> </ItemGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs index efc0c4af9..22bc7afb9 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs +++ b/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs @@ -39,18 +39,30 @@ namespace Jellyfin.Common.Tests.Json } [Fact] - public void Deserialize_Null_EmptyGuid() + public void Deserialize_Null_Null() { Assert.Null(JsonSerializer.Deserialize<Guid?>("null", _options)); } [Fact] - public void Serialize_EmptyGuid_EmptyGuid() + public void Deserialize_EmptyGuid_EmptyGuid() + { + Assert.Equal(Guid.Empty, JsonSerializer.Deserialize<Guid?>(@"""00000000-0000-0000-0000-000000000000""", _options)); + } + + [Fact] + public void Serialize_EmptyGuid_Null() { Assert.Equal("null", JsonSerializer.Serialize((Guid?)Guid.Empty, _options)); } [Fact] + public void Serialize_Null_Null() + { + Assert.Equal("null", JsonSerializer.Serialize((Guid?)null, _options)); + } + + [Fact] public void Serialize_Valid_NoDash_Success() { var guid = (Guid?)new Guid("531797E9-9457-40E0-88BC-B1D6D38752FA"); diff --git a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs b/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs index 6f85fe092..faed086a1 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs +++ b/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Common.Tests.Json { _options = new JsonSerializerOptions(); _options.Converters.Add(new JsonOmdbNotAvailableStringConverter()); - _options.Converters.Add(new JsonOmdbNotAvailableStructConverter<int>()); + _options.Converters.Add(new JsonOmdbNotAvailableInt32Converter()); _options.NumberHandling = JsonNumberHandling.AllowReadingFromString; } @@ -64,5 +64,25 @@ namespace Jellyfin.Common.Tests.Json var result = JsonSerializer.Deserialize<string>(Input, _options); Assert.Equal(Expected, result); } + + [Fact] + public void Roundtrip_Valid_Success() + { + const string Input = "{\"Title\":\"Chapter 1\",\"Year\":\"2013\",\"Rated\":\"TV-MA\",\"Released\":\"01 Feb 2013\",\"Season\":\"N/A\",\"Episode\":\"N/A\",\"Runtime\":\"55 min\",\"Genre\":\"Drama\",\"Director\":\"David Fincher\",\"Writer\":\"Michael Dobbs (based on the novels by), Andrew Davies (based on the mini-series by), Beau Willimon (created for television by), Beau Willimon, Sam Forman (staff writer)\",\"Actors\":\"Kevin Spacey, Robin Wright, Kate Mara, Corey Stoll\",\"Plot\":\"Congressman Francis Underwood has been declined the chair for Secretary of State. He's now gathering his own team to plot his revenge. Zoe Barnes, a reporter for the Washington Herald, will do anything to get her big break.\",\"Language\":\"English\",\"Country\":\"USA\",\"Awards\":\"N/A\",\"Poster\":\"https://m.media-amazon.com/images/M/MV5BMTY5MTU4NDQzNV5BMl5BanBnXkFtZTgwMzk2ODcxMzE@._V1_SX300.jpg\",\"Ratings\":[{\"Source\":\"Internet Movie Database\",\"Value\":\"8.7/10\"}],\"Metascore\":\"N/A\",\"imdbRating\":\"8.7\",\"imdbVotes\":\"6736\",\"imdbID\":\"tt2161930\",\"seriesID\":\"N/A\",\"Type\":\"episode\",\"Response\":\"True\"}"; + var trip1 = JsonSerializer.Deserialize<OmdbProvider.RootObject>(Input, _options); + Assert.NotNull(trip1); + Assert.NotNull(trip1?.Title); + Assert.Null(trip1?.Awards); + Assert.Null(trip1?.Episode); + Assert.Null(trip1?.Metascore); + + var serializedTrip1 = JsonSerializer.Serialize(trip1!, _options); + var trip2 = JsonSerializer.Deserialize<OmdbProvider.RootObject>(serializedTrip1, _options); + Assert.NotNull(trip2); + Assert.NotNull(trip2?.Title); + Assert.Null(trip2?.Awards); + Assert.Null(trip2?.Episode); + Assert.Null(trip2?.Metascore); + } } } diff --git a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs b/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs index 929bb92aa..0adf098c3 100644 --- a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs +++ b/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Sorting; using Xunit; @@ -8,8 +7,6 @@ namespace Jellyfin.Controller.Tests { public class AlphanumComparatorTests { - private readonly Random _rng = new Random(42); - // InlineData is pre-sorted [Theory] [InlineData(null, "", "1", "9", "10", "a", "z")] @@ -25,18 +22,7 @@ namespace Jellyfin.Controller.Tests [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")] public void AlphanumComparatorTest(params string?[] strings) { - var copy = (string?[])strings.Clone(); - if (strings.Length == 2) - { - var tmp = copy[0]; - copy[0] = copy[1]; - copy[1] = tmp; - } - else - { - copy.Shuffle(_rng); - } - + var copy = strings.Reverse().ToArray(); Array.Sort(copy, new AlphanumComparator()); Assert.True(strings.SequenceEqual(copy)); } diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 1ec88dada..84655db24 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -16,7 +16,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> </ItemGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 8c9dc4820..c5b01f4db 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -11,7 +11,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> </ItemGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index c934ea1c2..ed788bab8 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -22,7 +22,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> </ItemGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs new file mode 100644 index 000000000..d11cb242c --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/SsaParserTests.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using MediaBrowser.MediaEncoding.Subtitles; +using MediaBrowser.Model.MediaInfo; +using Xunit; + +namespace Jellyfin.MediaEncoding.Tests +{ + public class SsaParserTests + { + // commonly shared invariant value between tests, assumes default format order + private const string InvariantDialoguePrefix = "[Events]\nDialogue: ,0:00:00.00,0:00:00.01,,,,,,,"; + + private SsaParser parser = new SsaParser(); + + [Theory] + [InlineData("[EvEnTs]\nDialogue: ,0:00:00.00,0:00:00.01,,,,,,,text", "text")] // label casing insensitivity + [InlineData("[Events]\n,0:00:00.00,0:00:00.01,,,,,,,labelless dialogue", "labelless dialogue")] // no "Dialogue:" label, it is optional + [InlineData("[Events]\nFormat: Text, Start, End, Layer, Effect, Style\nDialogue: reordered text,0:00:00.00,0:00:00.01", "reordered text")] // reordered formats + [InlineData(InvariantDialoguePrefix + "Cased TEXT", "Cased TEXT")] // preserve text casing + [InlineData(InvariantDialoguePrefix + " text ", " text ")] // do not trim text + [InlineData(InvariantDialoguePrefix + "text, more text", "text, more text")] // append excess dialogue values (> 10) to text + [InlineData(InvariantDialoguePrefix + "start {\\fnFont Name}text{\\fn} end", "start <font face=\"Font Name\">text</font> end")] // font name + [InlineData(InvariantDialoguePrefix + "start {\\fs10}text{\\fs} end", "start <font size=\"10\">text</font> end")] // font size + [InlineData(InvariantDialoguePrefix + "start {\\c&H112233}text{\\c} end", "start <font color=\"#332211\">text</font> end")] // color + [InlineData(InvariantDialoguePrefix + "start {\\1c&H112233}text{\\1c} end", "start <font color=\"#332211\">text</font> end")] // primay color + [InlineData(InvariantDialoguePrefix + "start {\\fnFont Name}text1 {\\fs10}text2{\\fs}{\\fn} {\\1c&H112233}text3{\\1c} end", "start <font face=\"Font Name\">text1 <font size=\"10\">text2</font></font> <font color=\"#332211\">text3</font> end")] // nested formatting + public void Parse(string ssa, string expectedText) + { + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa))) + { + SubtitleTrackInfo subtitleTrackInfo = parser.Parse(stream, CancellationToken.None); + SubtitleTrackEvent actual = subtitleTrackInfo.TrackEvents[0]; + Assert.Equal(expectedText, actual.Text); + } + } + + [Theory] + [MemberData(nameof(Parse_MultipleDialogues_TestData))] + public void Parse_MultipleDialogues(string ssa, IReadOnlyList<SubtitleTrackEvent> expectedSubtitleTrackEvents) + { + using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(ssa))) + { + SubtitleTrackInfo subtitleTrackInfo = parser.Parse(stream, CancellationToken.None); + + Assert.Equal(expectedSubtitleTrackEvents.Count, subtitleTrackInfo.TrackEvents.Count); + + for (int i = 0; i < expectedSubtitleTrackEvents.Count; ++i) + { + SubtitleTrackEvent expected = expectedSubtitleTrackEvents[i]; + SubtitleTrackEvent actual = subtitleTrackInfo.TrackEvents[i]; + + Assert.Equal(expected.StartPositionTicks, actual.StartPositionTicks); + Assert.Equal(expected.EndPositionTicks, actual.EndPositionTicks); + Assert.Equal(expected.Text, actual.Text); + } + } + } + + public static IEnumerable<object[]> Parse_MultipleDialogues_TestData() + { + yield return new object[] + { + @"[Events] + Format: Layer, Start, End, Text + Dialogue: ,0:00:01.18,0:00:01.85,dialogue1 + Dialogue: ,0:00:02.18,0:00:02.85,dialogue2 + Dialogue: ,0:00:03.18,0:00:03.85,dialogue3 + ", + new List<SubtitleTrackEvent> + { + new SubtitleTrackEvent + { + StartPositionTicks = 11800000, + EndPositionTicks = 18500000, + Text = "dialogue1" + }, + new SubtitleTrackEvent + { + StartPositionTicks = 21800000, + EndPositionTicks = 28500000, + Text = "dialogue2" + }, + new SubtitleTrackEvent + { + StartPositionTicks = 31800000, + EndPositionTicks = 38500000, + Text = "dialogue3" + } + } + }; + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs new file mode 100644 index 000000000..14ad49839 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -0,0 +1,38 @@ +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using MediaBrowser.MediaEncoding.Subtitles; +using Xunit; + +namespace Jellyfin.MediaEncoding.Subtitles.Tests +{ + public class AssParserTests + { + [Fact] + public void Parse_Valid_Success() + { + using (var stream = File.OpenRead("Test Data/example.ass")) + { + var parsed = new AssParser().Parse(stream, CancellationToken.None); + Assert.Single(parsed.TrackEvents); + var trackEvent = parsed.TrackEvents[0]; + + Assert.Equal("1", trackEvent.Id); + Assert.Equal(TimeSpan.Parse("00:00:01.18", CultureInfo.InvariantCulture).Ticks, trackEvent.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:00:06.85", CultureInfo.InvariantCulture).Ticks, trackEvent.EndPositionTicks); + Assert.Equal("Like an Angel with pity on nobody\r\nThe second line in subtitle", trackEvent.Text); + } + } + + [Fact] + public void ParseFieldHeaders_Valid_Success() + { + const string Line = "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"; + var headers = AssParser.ParseFieldHeaders(Line); + Assert.Equal(1, headers["Start"]); + Assert.Equal(2, headers["End"]); + Assert.Equal(9, headers["Text"]); + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs new file mode 100644 index 000000000..3e2d2de10 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -0,0 +1,35 @@ +using System; +using System.Globalization; +using System.IO; +using System.Threading; +using MediaBrowser.MediaEncoding.Subtitles; +using Microsoft.Extensions.Logging.Abstractions; +using Xunit; + +namespace Jellyfin.MediaEncoding.Subtitles.Tests +{ + public class SrtParserTests + { + [Fact] + public void Parse_Valid_Success() + { + using (var stream = File.OpenRead("Test Data/example.srt")) + { + var parsed = new SrtParser(new NullLogger<SrtParser>()).Parse(stream, CancellationToken.None); + Assert.Equal(2, parsed.TrackEvents.Count); + + var trackEvent1 = parsed.TrackEvents[0]; + Assert.Equal("1", trackEvent1.Id); + Assert.Equal(TimeSpan.Parse("00:02:17.440", CultureInfo.InvariantCulture).Ticks, trackEvent1.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:02:20.375", CultureInfo.InvariantCulture).Ticks, trackEvent1.EndPositionTicks); + Assert.Equal("Senator, we're making\r\nour final approach into Coruscant.", trackEvent1.Text); + + var trackEvent2 = parsed.TrackEvents[1]; + Assert.Equal("2", trackEvent2.Id); + Assert.Equal(TimeSpan.Parse("00:02:20.476", CultureInfo.InvariantCulture).Ticks, trackEvent2.StartPositionTicks); + Assert.Equal(TimeSpan.Parse("00:02:22.501", CultureInfo.InvariantCulture).Ticks, trackEvent2.EndPositionTicks); + Assert.Equal("Very good, Lieutenant.", trackEvent2.Text); + } + } + } +} diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ass b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ass new file mode 100644 index 000000000..d5ac31d70 --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.ass @@ -0,0 +1,22 @@ +[Script Info] +; Script generated by Aegisub +; http://www.aegisub.org +Title: Neon Genesis Evangelion - Episode 26 (neutral Spanish) +Original Script: RoRo +Script Updated By: version 2.8.01 +ScriptType: v4.00+ +Collisions: Normal +PlayResY: 600 +PlayDepth: 0 +Timer: 100,0000 +Video Aspect Ratio: 0 +Video Zoom: 6 +Video Position: 0 + +[V4+ Styles] +Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding +Style: DefaultVCD, Arial,28,&H00B4FCFC,&H00B4FCFC,&H00000008,&H80000008,-1,0,0,0,100,100,0.00,0.00,1,1.00,2.00,2,30,30,30,0 + +[Events] +Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text +Dialogue: 0,0:00:01.18,0:00:06.85,DefaultVCD, NTP,0000,0000,0000,,{\pos(400,570)}Like an Angel with pity on nobody\NThe second line in subtitle diff --git a/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt new file mode 100644 index 000000000..78d74014e --- /dev/null +++ b/tests/Jellyfin.MediaEncoding.Tests/Test Data/example.srt @@ -0,0 +1,8 @@ +1 +00:02:17,440 --> 00:02:20,375 +Senator, we're making +our final approach into Coruscant. + +2 +00:02:20,476 --> 00:02:22,501 +Very good, Lieutenant. diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 6118581e1..f3b00dcab 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -16,7 +16,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> </ItemGroup> <ItemGroup> diff --git a/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj index 90782f6bb..8d9c20de1 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/NetworkTesting/Jellyfin.Networking.Tests.csproj @@ -16,7 +16,7 @@ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> <PackageReference Include="Moq" Version="4.15.2" /> </ItemGroup> 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 80259a55f..5c4170514 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -20,7 +20,7 @@ <PackageReference Include="Moq" Version="4.15.2" /> <PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> - <PackageReference Include="coverlet.collector" Version="1.3.0" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> </ItemGroup> <!-- Code Analyzers --> diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs index fb7cf6a47..75939526d 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/HdHomerunHostTests.cs @@ -1,5 +1,4 @@ using System; -using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj new file mode 100644 index 000000000..f02ac03f7 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -0,0 +1,40 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net5.0</TargetFramework> + <IsPackable>false</IsPackable> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <Nullable>enable</Nullable> + </PropertyGroup> + + <ItemGroup> + <None Include="Test Data\**\*.*"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" /> + <PackageReference Include="Moq" Version="4.15.2" /> + <PackageReference Include="xunit" Version="2.4.1" /> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" /> + <PackageReference Include="coverlet.collector" Version="3.0.0" /> + </ItemGroup> + + <!-- Code Analyzers --> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" /> + <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="../../MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj" /> + </ItemGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + +</Project> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs new file mode 100644 index 000000000..7651653a1 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -0,0 +1,107 @@ +using System; +using System.Linq; +using System.Threading; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using MediaBrowser.XbmcMetadata.Parsers; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.XbmcMetadata.Parsers.Tests +{ + public class MovieNfoParserTests + { + private readonly MovieNfoParser _parser; + + public MovieNfoParserTests() + { + var providerManager = new Mock<IProviderManager>(); + providerManager.Setup(x => x.GetExternalIdInfos(It.IsAny<IHasProviderIds>())) + .Returns(Enumerable.Empty<ExternalIdInfo>()); + var config = new Mock<IConfigurationManager>(); + config.Setup(x => x.GetConfiguration(It.IsAny<string>())) + .Returns(new XbmcMetadataOptions()); + _parser = new MovieNfoParser(new NullLogger<MovieNfoParser>(), config.Object, providerManager.Object); + } + + [Fact] + public void Fetch_Valid_Succes() + { + var result = new MetadataResult<Video>() + { + Item = new Video() + }; + + _parser.Fetch(result, "Test Data/Justice League.nfo", CancellationToken.None); + var item = result.Item; + + Assert.Equal("Justice League", item.OriginalTitle); + Assert.Equal("Justice for all.", item.Tagline); + Assert.Equal("tt0974015", item.ProviderIds["imdb"]); + + Assert.Equal(4, item.Genres.Length); + Assert.Contains("Action", item.Genres); + Assert.Contains("Adventure", item.Genres); + Assert.Contains("Fantasy", item.Genres); + Assert.Contains("Sci-Fi", item.Genres); + + Assert.Equal(new DateTime(2017, 11, 15), item.PremiereDate); + Assert.Single(item.Studios); + Assert.Contains("DC Comics", item.Studios); + + Assert.Equal("1.777778", item.AspectRatio); + Assert.Equal(1920, item.Width); + Assert.Equal(1080, item.Height); + Assert.Equal(new TimeSpan(0, 0, 6268).Ticks, item.RunTimeTicks); + Assert.True(item.HasSubtitles); + + Assert.Equal(18, result.People.Count); + + var writers = result.People.Where(x => x.Type == PersonType.Writer).ToArray(); + Assert.Equal(2, writers.Length); + var writerNames = writers.Select(x => x.Name); + Assert.Contains("Jerry Siegel", writerNames); + Assert.Contains("Joe Shuster", writerNames); + + var directors = result.People.Where(x => x.Type == PersonType.Director).ToArray(); + Assert.Single(directors); + Assert.Equal("Zack Snyder", directors[0].Name); + + var actors = result.People.Where(x => x.Type == PersonType.Actor).ToArray(); + Assert.Equal(15, actors.Length); + + // Only test one actor + var aquaman = actors.FirstOrDefault(x => x.Role.Equals("Aquaman", StringComparison.Ordinal)); + Assert.NotNull(aquaman); + Assert.Equal("Jason Momoa", aquaman!.Name); + Assert.Equal(5, aquaman!.SortOrder); + Assert.Equal("https://m.media-amazon.com/images/M/MV5BMTI5MTU5NjM1MV5BMl5BanBnXkFtZTcwODc4MDk0Mw@@._V1_SX1024_SY1024_.jpg", aquaman!.ImageUrl); + + Assert.Equal(new DateTime(2019, 8, 6, 9, 1, 18), item.DateCreated); + } + + [Fact] + public void Fetch_WithNullItem_ThrowsArgumentException() + { + var result = new MetadataResult<Video>(); + + Assert.Throws<ArgumentException>(() => _parser.Fetch(result, "Test Data/Justice League.nfo", CancellationToken.None)); + } + + [Fact] + public void Fetch_NullResult_ThrowsArgumentException() + { + var result = new MetadataResult<Video>() + { + Item = new Video() + }; + + Assert.Throws<ArgumentException>(() => _parser.Fetch(result, string.Empty, CancellationToken.None)); + } + } +} diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs new file mode 100644 index 000000000..a8c6e5afd --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MusicArtistNfoParserTests.cs @@ -0,0 +1,70 @@ +using System; +using System.Linq; +using System.Threading; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using MediaBrowser.XbmcMetadata.Parsers; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.XbmcMetadata.Parsers.Tests +{ + public class MusicArtistNfoParserTests + { + private readonly BaseNfoParser<MusicArtist> _parser; + + public MusicArtistNfoParserTests() + { + var providerManager = new Mock<IProviderManager>(); + providerManager.Setup(x => x.GetExternalIdInfos(It.IsAny<IHasProviderIds>())) + .Returns(Enumerable.Empty<ExternalIdInfo>()); + var config = new Mock<IConfigurationManager>(); + config.Setup(x => x.GetConfiguration(It.IsAny<string>())) + .Returns(new XbmcMetadataOptions()); + _parser = new BaseNfoParser<MusicArtist>(new NullLogger<BaseNfoParser<MusicArtist>>(), config.Object, providerManager.Object); + } + + [Fact] + public void Fetch_Valid_Succes() + { + var result = new MetadataResult<MusicArtist>() + { + Item = new MusicArtist() + }; + + _parser.Fetch(result, "Test Data/U2.nfo", CancellationToken.None); + var item = result.Item; + + Assert.Equal("U2", item.Name); + Assert.Equal("U2", item.SortName); + Assert.Equal("a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432", item.ProviderIds[MetadataProvider.MusicBrainzArtist.ToString()]); + + Assert.Single(item.Genres); + Assert.Equal("Rock", item.Genres[0]); + } + + [Fact] + public void Fetch_WithNullItem_ThrowsArgumentException() + { + var result = new MetadataResult<MusicArtist>(); + + Assert.Throws<ArgumentException>(() => _parser.Fetch(result, "Test Data/U2.nfo", CancellationToken.None)); + } + + [Fact] + public void Fetch_NullResult_ThrowsArgumentException() + { + var result = new MetadataResult<MusicArtist>() + { + Item = new MusicArtist() + }; + + Assert.Throws<ArgumentException>(() => _parser.Fetch(result, string.Empty, CancellationToken.None)); + } + } +} diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs new file mode 100644 index 000000000..37ca0fd05 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/SeriesNfoParserTests.cs @@ -0,0 +1,91 @@ +using System; +using System.Linq; +using System.Threading; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using MediaBrowser.XbmcMetadata.Parsers; +using Microsoft.Extensions.Logging.Abstractions; +using Moq; +using Xunit; + +namespace Jellyfin.XbmcMetadata.Parsers.Tests +{ + public class SeriesNfoParserTests + { + private readonly SeriesNfoParser _parser; + + public SeriesNfoParserTests() + { + var providerManager = new Mock<IProviderManager>(); + providerManager.Setup(x => x.GetExternalIdInfos(It.IsAny<IHasProviderIds>())) + .Returns(Enumerable.Empty<ExternalIdInfo>()); + var config = new Mock<IConfigurationManager>(); + config.Setup(x => x.GetConfiguration(It.IsAny<string>())) + .Returns(new XbmcMetadataOptions()); + _parser = new SeriesNfoParser(new NullLogger<SeriesNfoParser>(), config.Object, providerManager.Object); + } + + [Fact] + public void Fetch_Valid_Succes() + { + var result = new MetadataResult<Series>() + { + Item = new Series() + }; + + _parser.Fetch(result, "Test Data/American Gods.nfo", CancellationToken.None); + var item = result.Item; + + Assert.Equal("American Gods", item.OriginalTitle); + Assert.Equal(string.Empty, item.Tagline); + Assert.Equal(0, item.RunTimeTicks); + Assert.Equal("46639", item.ProviderIds["tmdb"]); + Assert.Equal("253573", item.ProviderIds["tvdb"]); + + Assert.Equal(3, item.Genres.Length); + Assert.Contains("Drama", item.Genres); + Assert.Contains("Mystery", item.Genres); + Assert.Contains("Sci-Fi & Fantasy", item.Genres); + + Assert.Equal(new DateTime(2017, 4, 30), item.PremiereDate); + Assert.Single(item.Studios); + Assert.Contains("Starz", item.Studios); + + Assert.Equal(6, result.People.Count); + + Assert.True(result.People.All(x => x.Type == PersonType.Actor)); + + // Only test one actor + var sweeney = result.People.FirstOrDefault(x => x.Role.Equals("Mad Sweeney", StringComparison.Ordinal)); + Assert.NotNull(sweeney); + Assert.Equal("Pablo Schreiber", sweeney!.Name); + Assert.Equal(3, sweeney!.SortOrder); + Assert.Equal("http://image.tmdb.org/t/p/original/uo8YljeePz3pbj7gvWXdB4gOOW4.jpg", sweeney!.ImageUrl); + + Assert.Equal(new DateTime(2017, 10, 7, 14, 25, 47), item.DateCreated); + } + + [Fact] + public void Fetch_WithNullItem_ThrowsArgumentException() + { + var result = new MetadataResult<Series>(); + + Assert.Throws<ArgumentException>(() => _parser.Fetch(result, "Test Data/American Gods.nfo", CancellationToken.None)); + } + + [Fact] + public void Fetch_NullResult_ThrowsArgumentException() + { + var result = new MetadataResult<Series>() + { + Item = new Series() + }; + + Assert.Throws<ArgumentException>(() => _parser.Fetch(result, string.Empty, CancellationToken.None)); + } + } +} diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/American Gods.nfo b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/American Gods.nfo new file mode 100644 index 000000000..b9f31f2f6 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/American Gods.nfo @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<tvshow> + <title>American Gods</title> + <originaltitle>American Gods</originaltitle> + <showtitle>American Gods</showtitle> + <sorttitle>American Gods</sorttitle> + <ratings> + <rating name="themoviedb" max="10" default="true"> + <value>6.800000</value> + <votes>581</votes> + </rating> + <rating name="imdb" max="10" default="true"> + <value>5.500000</value> + <votes>86352</votes> + </rating> + <rating name="metacritic" max="10"> + <value>6.0</value> + <votes>22</votes> + </rating> + <rating name="tomatometerallcritics" max="10"> + <value>7.6</value> + <votes>71</votes> + </rating> + <rating name="tomatometerallaudience" max="10"> + <value>6.2</value> + <votes>119873</votes> + </rating> + </ratings> + <userrating>0</userrating> + <top250>0</top250> + <season>2</season> + <episode>16</episode> + <displayseason>-1</displayseason> + <displayepisode>-1</displayepisode> + <outline></outline> + <plot>An ex-con becomes the traveling partner of a conman who turns out to be one of the older gods trying to recruit troops to battle the upstart deities. Based on Neil Gaiman's fantasy novel.</plot> + <tagline></tagline> + <runtime>0</runtime> + <thumb aspect="poster" preview="https://assets.fanart.tv/preview/tv/253573/tvposter/american-gods-58b18cd8d667a.jpg">https://assets.fanart.tv/fanart/tv/253573/tvposter/american-gods-58b18cd8d667a.jpg</thumb> + <thumb aspect="poster" preview="https://assets.fanart.tv/preview/tv/253573/tvposter/american-gods-5c896dbee9d21.jpg">https://assets.fanart.tv/fanart/tv/253573/tvposter/american-gods-5c896dbee9d21.jpg</thumb> + <thumb aspect="poster" preview="https://assets.fanart.tv/preview/tv/253573/tvposter/american-gods-57dda913a44e0.jpg">https://assets.fanart.tv/fanart/tv/253573/tvposter/american-gods-57dda913a44e0.jpg</thumb> + <thumb aspect="poster" preview="https://assets.fanart.tv/preview/tv/253573/tvposter/american-gods-590c159dcbf3a.jpg">https://assets.fanart.tv/fanart/tv/253573/tvposter/american-gods-590c159dcbf3a.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/tv/253573/tvbanner/american-gods-5cbbdaa84298d.jpg">https://assets.fanart.tv/fanart/tv/253573/tvbanner/american-gods-5cbbdaa84298d.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/tv/253573/tvbanner/american-gods-5932b1ffb3522.jpg">https://assets.fanart.tv/fanart/tv/253573/tvbanner/american-gods-5932b1ffb3522.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/tv/253573/tvbanner/american-gods-5932b1ffb43e4.jpg">https://assets.fanart.tv/fanart/tv/253573/tvbanner/american-gods-5932b1ffb43e4.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/tv/253573/tvthumb/american-gods-58db45dc886f5.jpg">https://assets.fanart.tv/fanart/tv/253573/tvthumb/american-gods-58db45dc886f5.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/tv/253573/tvthumb/american-gods-5932aee79947a.jpg">https://assets.fanart.tv/fanart/tv/253573/tvthumb/american-gods-5932aee79947a.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/tv/253573/tvthumb/american-gods-5932aee799e5a.jpg">https://assets.fanart.tv/fanart/tv/253573/tvthumb/american-gods-5932aee799e5a.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/tv/253573/tvthumb/american-gods-5932aee79a2f2.jpg">https://assets.fanart.tv/fanart/tv/253573/tvthumb/american-gods-5932aee79a2f2.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/tv/253573/tvthumb/american-gods-5932aee79a7c9.jpg">https://assets.fanart.tv/fanart/tv/253573/tvthumb/american-gods-5932aee79a7c9.jpg</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/tv/253573/hdtvlogo/american-gods-58b04bdcecefd.png">https://assets.fanart.tv/fanart/tv/253573/hdtvlogo/american-gods-58b04bdcecefd.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/tv/253573/hdtvlogo/american-gods-58b04d78a7ffc.png">https://assets.fanart.tv/fanart/tv/253573/hdtvlogo/american-gods-58b04d78a7ffc.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/tv/253573/hdtvlogo/american-gods-59e6660cb7dbc.png">https://assets.fanart.tv/fanart/tv/253573/hdtvlogo/american-gods-59e6660cb7dbc.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/tv/253573/hdtvlogo/american-gods-59e6660cc0716.png">https://assets.fanart.tv/fanart/tv/253573/hdtvlogo/american-gods-59e6660cc0716.png</thumb> + <thumb aspect="clearart" preview="https://assets.fanart.tv/preview/tv/253573/hdclearart/american-gods-59177740ba6cd.png">https://assets.fanart.tv/fanart/tv/253573/hdclearart/american-gods-59177740ba6cd.png</thumb> + <thumb aspect="clearart" preview="https://assets.fanart.tv/preview/tv/253573/hdclearart/american-gods-5913b6b2ce91d.png">https://assets.fanart.tv/fanart/tv/253573/hdclearart/american-gods-5913b6b2ce91d.png</thumb> + <thumb aspect="clearart" preview="https://assets.fanart.tv/preview/tv/253573/hdclearart/american-gods-5913b6b2cfa64.png">https://assets.fanart.tv/fanart/tv/253573/hdclearart/american-gods-5913b6b2cfa64.png</thumb> + <thumb aspect="clearart" preview="https://assets.fanart.tv/preview/tv/253573/hdclearart/american-gods-5913b6b2cf502.png">https://assets.fanart.tv/fanart/tv/253573/hdclearart/american-gods-5913b6b2cf502.png</thumb> + <thumb aspect="clearart" preview="https://assets.fanart.tv/preview/tv/253573/hdclearart/american-gods-5a4805be0619f.png">https://assets.fanart.tv/fanart/tv/253573/hdclearart/american-gods-5a4805be0619f.png</thumb> + <thumb aspect="characterart" preview="https://assets.fanart.tv/preview/tv/253573/characterart/american-gods-5a4805af07a04.png">https://assets.fanart.tv/fanart/tv/253573/characterart/american-gods-5a4805af07a04.png</thumb> + <thumb aspect="characterart" preview="https://assets.fanart.tv/preview/tv/253573/characterart/american-gods-59e6b1c71b65a.png">https://assets.fanart.tv/fanart/tv/253573/characterart/american-gods-59e6b1c71b65a.png</thumb> + <thumb aspect="poster" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-5d1274a8c31cb.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-5d1274a8c31cb.jpg</thumb> + <thumb aspect="poster" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-59fea294b565f.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-59fea294b565f.jpg</thumb> + <thumb aspect="poster" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-5cacdf37068db.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-5cacdf37068db.jpg</thumb> + <thumb aspect="poster" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-5cacdf7783e04.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-5cacdf7783e04.jpg</thumb> + <thumb aspect="poster" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-5d1274a8c31cb.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-5d1274a8c31cb.jpg</thumb> + <thumb aspect="poster" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-59fea294b565f.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-59fea294b565f.jpg</thumb> + <thumb aspect="poster" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-5cacdf37068db.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-5cacdf37068db.jpg</thumb> + <thumb aspect="poster" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonposter/american-gods-5cacdf7783e04.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonposter/american-gods-5cacdf7783e04.jpg</thumb> + <thumb aspect="banner" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonbanner/american-gods-5cc6b35699d26.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonbanner/american-gods-5cc6b35699d26.jpg</thumb> + <thumb aspect="banner" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonbanner/american-gods-5cc6b36965b54.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonbanner/american-gods-5cc6b36965b54.jpg</thumb> + <thumb aspect="banner" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonbanner/american-gods-5cc6b35699d26.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonbanner/american-gods-5cc6b35699d26.jpg</thumb> + <thumb aspect="banner" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonbanner/american-gods-5cc6b36965b54.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonbanner/american-gods-5cc6b36965b54.jpg</thumb> + <thumb aspect="landscape" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonthumb/american-gods-5cc6b380d6c56.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonthumb/american-gods-5cc6b380d6c56.jpg</thumb> + <thumb aspect="landscape" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonthumb/american-gods-59e6b5a03e7aa.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonthumb/american-gods-59e6b5a03e7aa.jpg</thumb> + <thumb aspect="landscape" type="season" season="2" preview="https://assets.fanart.tv/preview/tv/253573/seasonthumb/american-gods-5cc6b380d6c56.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonthumb/american-gods-5cc6b380d6c56.jpg</thumb> + <thumb aspect="landscape" type="season" season="1" preview="https://assets.fanart.tv/preview/tv/253573/seasonthumb/american-gods-59e6b5a03e7aa.jpg">https://assets.fanart.tv/fanart/tv/253573/seasonthumb/american-gods-59e6b5a03e7aa.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/m6qf6lq3yARgbZwspvDLbUFtASh.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/gevw5nZRYz2kWj1PqW9pz4sgeeZ.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/btwTe5cQbGWGOErBiRqnjNP9cJl.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/loJ4sfr4zp995qMoeCHiIIGaOg8.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/dHo8Lw7ruIaQTdTTDZPCMyZxwy5.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/zfAXP4bG2G17VuLNU9cqRcVU0xj.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/oxYUbNpG2st2zXWzYRvewehmvuj.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/mwoQ6zynu2DBxKCBYi30qoM236N.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/8XEoXAMzgcf7m1KiUDZ9N1UGh4o.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/rWsayJB1grML2LdPjjKDC3g0Brr.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/8qRsj8uJ4zPARQmQ9FvejTY1lnV.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/acjnZP0GrwWDxCxV6QejKizbzOy.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/hN1sI57QILGfdrEOqpUfo0NtHjW.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/hz2jNy3DfseYzRSybGRlUtz4pTi.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/hLDgNDdrkB0oWiuClpxN4E3XadJ.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/4FiqawHsVz1mYCRudPtXKbfmP4M.jpg</thumb> + <thumb aspect="poster">http://image.tmdb.org/t/p/original/sKR8Q36YBtyRc19y4yGYuD1xBgA.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/4l8Vnbb7e5QA6bAItMqQIHXLRgc.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/ni0thXw5Zi5dQKBY6Oj0vcfIS2n.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/v17HfCzWKQKOBrww9RxZmN5R9tF.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/2ffvlgYsxbXGiWkc3V6Q8tgpiBo.jpg</thumb> + <thumb aspect="poster" type="season" season="1">http://image.tmdb.org/t/p/original/rASj7OUjWDhfhAeO2MaFOA3lJpQ.jpg</thumb> + <thumb aspect="poster" type="season" season="1">http://image.tmdb.org/t/p/original/67exRijfvN5RRmBCqFtk1bhJ7Uh.jpg</thumb> + <thumb aspect="poster" type="season" season="1">http://image.tmdb.org/t/p/original/59iE3xxP7H8rAiXW6TDR2HSoUUm.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/4l8Vnbb7e5QA6bAItMqQIHXLRgc.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/ni0thXw5Zi5dQKBY6Oj0vcfIS2n.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/v17HfCzWKQKOBrww9RxZmN5R9tF.jpg</thumb> + <thumb aspect="poster" type="season" season="2">http://image.tmdb.org/t/p/original/2ffvlgYsxbXGiWkc3V6Q8tgpiBo.jpg</thumb> + <thumb aspect="banner">https://thetvdb.com/banners/graphical/253573-g3.jpg</thumb> + <thumb aspect="banner">https://thetvdb.com/banners/graphical/253573-g4.jpg</thumb> + <thumb aspect="banner">https://thetvdb.com/banners/graphical/253573-g2.jpg</thumb> + <thumb aspect="banner">https://thetvdb.com/banners/graphical/253573-g.jpg</thumb> + <thumb aspect="banner">https://thetvdb.com/banners/graphical/253573-g5.jpg</thumb> + <fanart> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5c8965c58e778.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5c8965c58e778.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-59e6a8a495c2a.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-59e6a8a495c2a.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-59e6b13827ba2.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-59e6b13827ba2.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e07ad.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e07ad.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e2913.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e2913.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e0000.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e0000.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e0d3a.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e0d3a.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e1395.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e1395.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e1952.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e1952.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/tv/253573/showbackground/american-gods-5932b089e23ca.jpg">https://assets.fanart.tv/fanart/tv/253573/showbackground/american-gods-5932b089e23ca.jpg</thumb> + </fanart> + <mpaa>Australia:MA</mpaa> + <playcount>0</playcount> + <lastplayed></lastplayed> + <episodeguide> + <url cache="tmdb-46639-en.json">http://api.themoviedb.org/3/tv/46639?api_key=6a5be4999abf74eba1f9a8311294c267&language=en</url> + </episodeguide> + <id>46639</id> + <uniqueid type="tmdb" default="true">46639</uniqueid> + <uniqueid type="tvdb">253573</uniqueid> + <genre>Drama</genre> + <genre>Mystery</genre> + <genre>Sci-Fi & Fantasy</genre> + <premiered>2017-04-30</premiered> + <year>2017</year> + <status></status> + <code></code> + <aired></aired> + <studio>Starz</studio> + <trailer></trailer> + <actor> + <name>Ricky Whittle</name> + <role>Shadow Moon</role> + <order>0</order> + <thumb>http://image.tmdb.org/t/p/original/cjeDbVfBp6Qvb3C74Dfy7BKDTQN.jpg</thumb> + </actor> + <actor> + <name>Ian McShane</name> + <role>Mr. Wednesday</role> + <order>1</order> + <thumb>http://image.tmdb.org/t/p/original/pY9ud4BJwHekNiO4MMItPbgkdAy.jpg</thumb> + </actor> + <actor> + <name>Emily Browning</name> + <role>Laura Moon</role> + <order>2</order> + <thumb>http://image.tmdb.org/t/p/original/fa1Kyj02wxwcdS6EHb2i27TNXvU.jpg</thumb> + </actor> + <actor> + <name>Pablo Schreiber</name> + <role>Mad Sweeney</role> + <order>3</order> + <thumb>http://image.tmdb.org/t/p/original/uo8YljeePz3pbj7gvWXdB4gOOW4.jpg</thumb> + </actor> + <actor> + <name>Bruce Langley</name> + <role>Technical Boy</role> + <order>4</order> + <thumb>http://image.tmdb.org/t/p/original/f4EOWUmznLqboq8Ce7jnlkHVK3Y.jpg</thumb> + </actor> + <actor> + <name>Yetide Badaki</name> + <role>Bilquis</role> + <order>5</order> + <thumb>http://image.tmdb.org/t/p/original/qfzkREHuI1JvMxBteIAjKX8qMEr.jpg</thumb> + </actor> + <namedseason number="1">Season 1</namedseason> + <namedseason number="2">Season 2</namedseason> + <resume> + <position>0.000000</position> + <total>0.000000</total> + </resume> + <dateadded>2017-10-07 14:25:47</dateadded> +</tvshow> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo new file mode 100644 index 000000000..f838af8d0 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Justice League.nfo @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<movie> + <title>Justice League</title> + <originaltitle>Justice League</originaltitle> + <ratings> + <rating name="imdb" max="10" default="true"> + <value>6.400000</value> + <votes>335583</votes> + </rating> + <rating name="metacritic" max="10"> + <value>4.500000</value> + <votes>52</votes> + </rating> + <rating name="themoviedb" max="10"> + <value>6.200000</value> + <votes>7788</votes> + </rating> + <rating name="tomatometerallcritics" max="10"> + <value>7.6</value> + <votes>71</votes> + </rating> + <rating name="tomatometerallaudience" max="10"> + <value>6.2</value> + <votes>119873</votes> + </rating> + </ratings> + <userrating>0</userrating> + <top250>0</top250> + <outline>Fueled by his restored faith in humanity and inspired by Superman's selfless act, Bruce Wayne enlists the help of his new-found ally, Diana Prince, to face an even greater enemy.</outline> + <plot>Fueled by his restored faith in humanity and inspired by Superman's selfless act, Bruce Wayne enlists the help of his newfound ally, Diana Prince, to face an even greater enemy. Together, Batman and Wonder Woman work quickly to find and recruit a team of meta-humans to stand against this newly awakened threat. But despite the formation of this unprecedented league of heroes-Batman, Wonder Woman, Aquaman, Cyborg and The Flash-it may already be too late to save the planet from an assault of catastrophic proportions.</plot> + <tagline>Justice for all.</tagline> + <runtime>120</runtime> + <thumb aspect="set.poster" preview="https://assets.fanart.tv/preview/movies/468551/movieposter/justice-league-collection-5c24ea65591d3.jpg">https://assets.fanart.tv/fanart/movies/468551/movieposter/justice-league-collection-5c24ea65591d3.jpg</thumb> + <thumb aspect="set.poster" preview="https://assets.fanart.tv/preview/movies/468551/movieposter/justice-league-collection-5c24ea65591d3.jpg">https://assets.fanart.tv/fanart/movies/468551/movieposter/justice-league-collection-5c24ea65591d3.jpg</thumb> + <thumb aspect="set.clearlogo" preview="https://assets.fanart.tv/preview/movies/468551/hdmovielogo/justice-league-collection-5ba855ed4239a.png">https://assets.fanart.tv/fanart/movies/468551/hdmovielogo/justice-league-collection-5ba855ed4239a.png</thumb> + <thumb aspect="set.clearart" preview="https://assets.fanart.tv/preview/movies/468551/hdmovieclearart/justice-league-collection-5c24eae8d4d71.png">https://assets.fanart.tv/fanart/movies/468551/hdmovieclearart/justice-league-collection-5c24eae8d4d71.png</thumb> + <thumb aspect="set.landscape" preview="https://assets.fanart.tv/preview/movies/468551/moviethumb/justice-league-collection-5c24ebc7d0d2b.jpg">https://assets.fanart.tv/fanart/movies/468551/moviethumb/justice-league-collection-5c24ebc7d0d2b.jpg</thumb> + <thumb aspect="set.poster" preview="http://image.tmdb.org/t/p/w500/cigoYpXWgYYgsIsEPwMneVYpuwo.jpg">http://image.tmdb.org/t/p/original/cigoYpXWgYYgsIsEPwMneVYpuwo.jpg</thumb> + <thumb aspect="set.poster" preview="http://image.tmdb.org/t/p/w500/2ZOCiOdAOVSKsFjC1Vl2ZlANrPj.jpg">http://image.tmdb.org/t/p/original/2ZOCiOdAOVSKsFjC1Vl2ZlANrPj.jpg</thumb> + <thumb aspect="set.poster" preview="http://image.tmdb.org/t/p/w500/cigoYpXWgYYgsIsEPwMneVYpuwo.jpg">http://image.tmdb.org/t/p/original/cigoYpXWgYYgsIsEPwMneVYpuwo.jpg</thumb> + <thumb aspect="set.poster" preview="http://image.tmdb.org/t/p/w500/2ZOCiOdAOVSKsFjC1Vl2ZlANrPj.jpg">http://image.tmdb.org/t/p/original/2ZOCiOdAOVSKsFjC1Vl2ZlANrPj.jpg</thumb> + <thumb aspect="set.poster" preview="http://image.tmdb.org/t/p/w500/7iO1C4c5igXsB6AyxnqsCPv6fiq.jpg">http://image.tmdb.org/t/p/original/7iO1C4c5igXsB6AyxnqsCPv6fiq.jpg</thumb> + <thumb aspect="set.fanart" preview="http://image.tmdb.org/t/p/w500/vyxOJuk6cxrRcGzuMRbDTpwji1w.jpg">http://image.tmdb.org/t/p/original/vyxOJuk6cxrRcGzuMRbDTpwji1w.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/9rtrRGeRnL0JKtu9IMBWsmlmmZz.jpg">http://image.tmdb.org/t/p/original/9rtrRGeRnL0JKtu9IMBWsmlmmZz.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/eRoXqOzciHkSPs1Z8pGnJMZo0Zb.jpg">http://image.tmdb.org/t/p/original/eRoXqOzciHkSPs1Z8pGnJMZo0Zb.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/aQkEdqaXVxYObMLeoBSAUcgkxLs.jpg">http://image.tmdb.org/t/p/original/aQkEdqaXVxYObMLeoBSAUcgkxLs.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/4lo1fTexk2eNIeQx3Tp74kN7ASE.jpg">http://image.tmdb.org/t/p/original/4lo1fTexk2eNIeQx3Tp74kN7ASE.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/fF94rvT1kJpVzIE2aSYgYj9B3pc.jpg">http://image.tmdb.org/t/p/original/fF94rvT1kJpVzIE2aSYgYj9B3pc.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/uwegp70cWe16EtwsSjbL6ShPenG.jpg">http://image.tmdb.org/t/p/original/uwegp70cWe16EtwsSjbL6ShPenG.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/exLtrlI7JjKcfQVTccI7XdQRFMz.jpg">http://image.tmdb.org/t/p/original/exLtrlI7JjKcfQVTccI7XdQRFMz.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/paLcue01KpfQftorfjKqqD4qvlL.jpg">http://image.tmdb.org/t/p/original/paLcue01KpfQftorfjKqqD4qvlL.jpg</thumb> + <thumb aspect="poster" preview="http://image.tmdb.org/t/p/w500/yVDIfiKIsCbdFcgLXW34bAsnQvy.jpg">http://image.tmdb.org/t/p/original/yVDIfiKIsCbdFcgLXW34bAsnQvy.jpg</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-5865bf95cbadb.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5865bf95cbadb.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-585e9ca3bcf6a.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-585e9ca3bcf6a.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-57b476a831d74.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-57b476a831d74.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-57947e28cf10b.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-57947e28cf10b.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-5863d5c0cf0c9.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5863d5c0cf0c9.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-5a801747e5545.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5a801747e5545.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/movies/141052/hdmovielogo/justice-league-5cd75683df92b.png">https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5cd75683df92b.png</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/movies/141052/moviebanner/justice-league-586017e95adbd.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebanner/justice-league-586017e95adbd.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/movies/141052/moviebanner/justice-league-5934d45bc6592.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebanner/justice-league-5934d45bc6592.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/movies/141052/moviebanner/justice-league-5aa9289a379fa.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebanner/justice-league-5aa9289a379fa.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/movies/141052/moviethumb/justice-league-585fb155c3743.jpg">https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-585fb155c3743.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/movies/141052/moviethumb/justice-league-585edbda91d82.jpg">https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-585edbda91d82.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/movies/141052/moviethumb/justice-league-5b86588882c12.jpg">https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-5b86588882c12.jpg</thumb> + <thumb aspect="landscape" preview="https://assets.fanart.tv/preview/movies/141052/moviethumb/justice-league-5bbb9babe600c.jpg">https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-5bbb9babe600c.jpg</thumb> + <thumb aspect="clearart" preview="https://assets.fanart.tv/preview/movies/141052/hdmovieclearart/justice-league-5865c23193041.png">https://assets.fanart.tv/fanart/movies/141052/hdmovieclearart/justice-league-5865c23193041.png</thumb> + <thumb aspect="discart" preview="https://assets.fanart.tv/preview/movies/141052/moviedisc/justice-league-5a3af26360617.png">https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a3af26360617.png</thumb> + <thumb aspect="discart" preview="https://assets.fanart.tv/preview/movies/141052/moviedisc/justice-league-58690967b9765.png">https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-58690967b9765.png</thumb> + <thumb aspect="discart" preview="https://assets.fanart.tv/preview/movies/141052/moviedisc/justice-league-5a953ca4db6a6.png">https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a953ca4db6a6.png</thumb> + <thumb aspect="discart" preview="https://assets.fanart.tv/preview/movies/141052/moviedisc/justice-league-5a0b913c233be.png">https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a0b913c233be.png</thumb> + <thumb aspect="discart" preview="https://assets.fanart.tv/preview/movies/141052/moviedisc/justice-league-5a87e0cdb1209.png">https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a87e0cdb1209.png</thumb> + <thumb aspect="discart" preview="https://assets.fanart.tv/preview/movies/141052/moviedisc/justice-league-59dc595362ef1.png">https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-59dc595362ef1.png</thumb> + <fanart> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-5793f518c6d6e.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5793f518c6d6e.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-5a5332c7b5e77.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a5332c7b5e77.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-5a53cf2dac1c8.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a53cf2dac1c8.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-5976ba93eb5d3.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5976ba93eb5d3.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-58fa1f1932897.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-58fa1f1932897.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-5a14f5fd8dd16.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a14f5fd8dd16.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/movies/141052/moviebackground/justice-league-5a119394ea362.jpg">https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a119394ea362.jpg</thumb> + </fanart> + <mpaa>Australia:M</mpaa> + <playcount>0</playcount> + <lastplayed></lastplayed> + <id>tt0974015</id> + <uniqueid type="imdb" default="true">tt0974015</uniqueid> + <genre>Action</genre> + <genre>Adventure</genre> + <genre>Fantasy</genre> + <genre>Sci-Fi</genre> + <country>USA</country> + <country>Canada</country> + <country>UK</country> + <set> + <name>Justice League Collection</name> + <overview>Based on the DC Comics superhero team</overview> + </set> + <credits>Jerry Siegel</credits> + <credits>Joe Shuster</credits> + <director>Zack Snyder</director> + <premiered>2017-11-15</premiered> + <year>2017</year> + <status></status> + <code></code> + <aired></aired> + <studio>DC Comics</studio> + <trailer></trailer> + <fileinfo> + <streamdetails> + <video> + <codec>h264</codec> + <aspect>1.777778</aspect> + <width>1920</width> + <height>1080</height> + <durationinseconds>6268</durationinseconds> + <stereomode></stereomode> + </video> + <audio> + <codec>truehd</codec> + <language>eng</language> + <channels>8</channels> + </audio> + <audio> + <codec>ac3</codec> + <language></language> + <channels>6</channels> + </audio> + <subtitle> + <language>eng</language> + </subtitle> + </streamdetails> + </fileinfo> + <actor> + <name>Ben Affleck</name> + <role>Batman</role> + <order>0</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTI4MzIxMTk0Nl5BMl5BanBnXkFtZTcwOTU5NjA0Mg@@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Henry Cavill</name> + <role>Superman</role> + <order>1</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTUxNTExMzUzOF5BMl5BanBnXkFtZTgwOTI1MjA3OTE@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Amy Adams</name> + <role>Lois Lane</role> + <order>2</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTg2NTk2MTgxMV5BMl5BanBnXkFtZTgwNjcxMjAzMTI@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Gal Gadot</name> + <role>Wonder Woman</role> + <order>3</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMjUzZTJmZDItODRjYS00ZGRhLTg2NWQtOGE0YjJhNWVlMjNjXkEyXkFqcGdeQXVyMTg4NDI0NDM@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Ezra Miller</name> + <role>The Flash</role> + <order>4</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMjEwMjQ3ODgxOV5BMl5BanBnXkFtZTgwNzc4NjE4NTE@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Jason Momoa</name> + <role>Aquaman</role> + <order>5</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTI5MTU5NjM1MV5BMl5BanBnXkFtZTcwODc4MDk0Mw@@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Ray Fisher</name> + <role>Cyborg</role> + <order>6</order> + <thumb>https://m.media-amazon.com/images/M/MV5BYzdhMzkyYTgtMjQzMC00ODhmLWExZmItNTU4MDVlMzY2NzgwXkEyXkFqcGdeQXVyNzA5NjQ5MDk@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Jeremy Irons</name> + <role>Alfred</role> + <order>7</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTY5Mzg2NDY5OV5BMl5BanBnXkFtZTcwMDQwNzA0Mg@@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Diane Lane</name> + <role>Martha Kent</role> + <order>8</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMzM5ODM1ZWMtZjcyYy00MzgzLWJmMGQtZWY5OGQyNTRiODIxXkEyXkFqcGdeQXVyOTE0NjgwMjY@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Connie Nielsen</name> + <role>Queen Hippolyta</role> + <order>9</order> + <thumb>https://m.media-amazon.com/images/M/MV5BYzZiYTQ4YTAtMzRkMi00ZDZlLWFkZWItNGI2ZTIyODRiYTc4XkEyXkFqcGdeQXVyMjUzMjc2MjE@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>J.K. Simmons</name> + <role>Commissioner Gordon</role> + <order>10</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMzg2NTI5NzQ1MV5BMl5BanBnXkFtZTgwNjI1NDEwMDI@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Ciarán Hinds</name> + <role>Steppenwolf</role> + <order>11</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTIyNjM0MzU0NF5BMl5BanBnXkFtZTcwOTIxMzg1MQ@@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Amber Heard</name> + <role>Mera</role> + <order>12</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMjA4NDkyODA3M15BMl5BanBnXkFtZTgwMzUzMjYzNzM@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Joe Morton</name> + <role>Silas Stone</role> + <order>13</order> + <thumb>https://m.media-amazon.com/images/M/MV5BMTQ1MjYwMTQ2MF5BMl5BanBnXkFtZTgwNzI4MTA0NDE@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <actor> + <name>Lisa Loven Kongsli</name> + <role>Menalippe</role> + <order>14</order> + <thumb>https://m.media-amazon.com/images/M/MV5BOTFjOTFhNTgtZjk3Ny00MTNjLWE3MWUtMWI3ZWM5NDljZjQwXkEyXkFqcGdeQXVyMjQwMDg0Ng@@._V1_SX1024_SY1024_.jpg</thumb> + </actor> + <resume> + <position>0.000000</position> + <total>0.000000</total> + </resume> + <showlink>Justice League</showlink> + <dateadded>2019-08-06 09:01:18</dateadded> +</movie> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/U2.nfo b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/U2.nfo new file mode 100644 index 000000000..8c46fdeb8 --- /dev/null +++ b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/U2.nfo @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<artist> + <name>U2</name> + <musicBrainzArtistID>a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432</musicBrainzArtistID> + <sortname>U2</sortname> + <type></type> + <gender></gender> + <disambiguation>Irish rock band</disambiguation> + <genre>Rock</genre> + <style>Rock/Pop</style> + <mood>Political</mood> + <born></born> + <formed>Dublin, Ireland (1976)</formed> + <biography>U2 are an Irish rock band from Dublin. Formed in 1976, the group consists of Bono (vocals and rhythm guitar), the Edge (lead guitar, keyboards, and vocals), Adam Clayton (bass guitar), and Larry Mullen, Jr. (drums and percussion). U2's early sound was rooted in post-punk but eventually grew to incorporate influences from many genres of popular music. Throughout the group's musical pursuits, they have maintained a sound built on melodic instrumentals. Their lyrics, often embellished with spiritual imagery, focus on personal themes and sociopolitical concerns.
The band formed at Mount Temple Comprehensive School in 1976 when the members were teenagers with limited musical proficiency. Within four years, they signed with Island Records and released their debut album Boy. By the mid-1980s, U2 had become a top international act. They were more successful as a touring act than they were at selling records until their 1987 album The Joshua Tree which, according to Rolling Stone, elevated the band's stature "from heroes to superstars". Reacting to musical stagnation and criticism of their earnest image and musical direction in the late 1980s, U2 reinvented themselves with their 1991 album, Achtung Baby, and the accompanying Zoo TV Tour; they integrated dance, industrial, and alternative rock influences into their sound, and embraced a more ironic and self-deprecating image. They embraced similar experimentation for the remainder of the 1990s with varying levels of success. U2 regained critical and commercial favour in the 2000s with the records All That You Can't Leave Behind (2000) and How to Dismantle an Atomic Bomb (2004), which established a more conventional, mainstream sound for the group. Their U2 360° Tour of 2009–2011 is the highest-attended and highest-grossing concert tour in history.
U2 have released 13 studio albums and are one of the world's best-selling music artists of all time, having sold more than 170 million records worldwide. They have won 22 Grammy Awards, more than any other band; and, in 2005, were inducted into the Rock and Roll Hall of Fame in their first year of eligibility. Rolling Stone ranked U2 at number 22 in its list of the "100 Greatest Artists of All Time", and labelled them the "Biggest Band in the World". Throughout their career, as a band and as individuals, they have campaigned for human rights and philanthropic causes, including Amnesty International, the ONE/DATA campaigns, Product Red, War Child and the Edge's Music Rising.</biography> + <died></died> + <disbanded></disbanded> + <thumb aspect="poster" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistthumb/u2-50104c356fd2b.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistthumb/u2-50104c356fd2b.jpg</thumb> + <thumb aspect="poster" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistthumb/u2-4fdf7ab5bfa99.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistthumb/u2-4fdf7ab5bfa99.jpg</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-538b320283c98.png">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-538b320283c98.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-538b3268cc581.png">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-538b3268cc581.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-55b02a97170c7.png">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-55b02a97170c7.png</thumb> + <thumb aspect="clearlogo" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-538b39954caf1.png">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/hdmusiclogo/u2-538b39954caf1.png</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-59e65cba172de.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-59e65cba172de.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-54063da8ca135.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-54063da8ca135.jpg</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-503f9e062c802.JPG">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-503f9e062c802.JPG</thumb> + <thumb aspect="banner" preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-591ce819c91a5.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/musicbanner/u2-591ce819c91a5.jpg</thumb> + <thumb preview="https://www.theaudiodb.com/images/media/artist/thumb/qvuxvs1347997318.jpg/preview">https://www.theaudiodb.com/images/media/artist/thumb/qvuxvs1347997318.jpg</thumb> + <thumb aspect="clearlogo" preview="https://www.theaudiodb.com/images/media/artist/logo/qywsvv1347997327.png/preview">https://www.theaudiodb.com/images/media/artist/logo/qywsvv1347997327.png</thumb> + <thumb aspect="clearart" preview="https://www.theaudiodb.com/images/media/artist/clearart/vwpyxv1511531849.png/preview">https://www.theaudiodb.com/images/media/artist/clearart/vwpyxv1511531849.png</thumb> + <thumb aspect="landscape" preview="https://www.theaudiodb.com/images/media/artist/widethumb/wxsxwq1524669620.jpg/preview">https://www.theaudiodb.com/images/media/artist/widethumb/wxsxwq1524669620.jpg</thumb> + <thumb aspect="banner" preview="https://www.theaudiodb.com/images/media/artist/banner/rpqwpu1488384726.jpg/preview">https://www.theaudiodb.com/images/media/artist/banner/rpqwpu1488384726.jpg</thumb> + <path>E:\z-Music Artists\U2</path> + <fanart> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4f805e377b181.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4f805e377b181.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-5058bffb80200.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-5058bffb80200.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4f805e377b5a0.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4f805e377b5a0.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4df96804ad0f3.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4df96804ad0f3.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-5487022bd1524.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-5487022bd1524.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-50104bf699b84.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-50104bf699b84.jpg</thumb> + <thumb preview="https://assets.fanart.tv/preview/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4f805e377acdb.jpg">https://assets.fanart.tv/fanart/music/a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432/artistbackground/u2-4f805e377acdb.jpg</thumb> + </fanart> + <album> + <title>Pop</title> + <year>1997</year> + </album> + <album> + <title>How to Dismantle an Atomic Bomb</title> + <year>2004</year> + </album> + <album> + <title>Boy</title> + <year>1980</year> + </album> + <album> + <title>Pop</title> + <year>1997</year> + </album> + <album> + <title>The Joshua Tree</title> + <year>1987</year> + </album> + <album> + <title>Achtung Baby</title> + <year>1991</year> + </album> + <album> + <title>Zooropa</title> + <year>1993</year> + </album> +</artist> |
