using System.Net;
using Flaro.Core.Metadata;
using Microsoft.Extensions.Logging.Abstractions;
namespace Flaro.Metadata.Tests;
/// Plakate von fanart.tv — der Quelle, bei der die Sprache mitsteht.
///
///
/// Der Anlass. „365 Tage" stand mit polnischem Plakat da. Nachgesehen:
/// TMDB hat zu diesem Film 26 Plakate und kein einziges deutsches. Die
/// Auswahl im TMDB-Client nimmt seither das sprachlose statt des polnischen
/// — erfinden kann sie ein deutsches nicht. Genau dafür gibt es diese zweite
/// Quelle.
///
public class FanartTests
{
private static FanartClient Client(Attrappe attrappe, string? schluessel = "ein-schluessel") =>
new(new HttpClient(attrappe) { BaseAddress = new Uri(FanartClient.BaseAddress) },
new FesterFanartSchluessel(schluessel),
NullLogger.Instance);
private const string Antwort = """
{"name":"Probe","tmdb_id":"500",
"movieposter":[
{"id":"1","url":"https://assets.fanart.tv/de.jpg","lang":"de","likes":"3"},
{"id":"2","url":"https://assets.fanart.tv/en.jpg","lang":"en","likes":"9"},
{"id":"3","url":"https://assets.fanart.tv/ohne.jpg","lang":"00","likes":"5"}],
"moviebackground":[
{"id":"4","url":"https://assets.fanart.tv/hg.jpg","lang":"","likes":"2"}]}
""";
[Test]
public async Task Ohne_Schluessel_geht_keine_Anfrage_hinaus()
{
var attrappe = Attrappe.MitJson(Antwort);
var bilder = await Client(attrappe, schluessel: null).BilderAsync("500");
Assert.Multiple(() =>
{
Assert.That(bilder, Is.Empty);
Assert.That(attrappe.Aufrufe, Is.Empty,
"fanart.tv verlangt einen persönlichen Schlüssel — ohne ihn wird nicht gefragt");
});
}
[Test]
public async Task Die_Plakate_kommen_mit_ihrer_Sprache()
{
var bilder = await Client(Attrappe.MitJson(Antwort)).BilderAsync("500");
var plakate = bilder.Where(b => b.Kind == "poster").ToList();
Assert.Multiple(() =>
{
Assert.That(plakate, Has.Count.EqualTo(3));
Assert.That(plakate.Select(p => p.Language), Is.EquivalentTo(new[] { "de", "en", null }));
Assert.That(plakate.All(p => p.Quelle == "fanart"), Is.True);
});
}
/// „00" ist bei fanart.tv die Schreibweise für „ohne Sprache".
///
///
/// Sie durchzureichen hiesse, ein sprachloses Plakat als Sprache „00" zu
/// führen — und die gemeinsame Rangfolge setzte es damit hinter Englisch
/// statt davor.
///
[Test]
public async Task Die_Null_Null_wird_zu_sprachlos()
{
var bilder = await Client(Attrappe.MitJson(Antwort)).BilderAsync("500");
Assert.That(bilder.Any(b => b.Language == "00"), Is.False);
}
/// Zu den meisten Filmen hat fanart.tv nichts — das ist kein Fehler.
[Test]
public async Task Ein_unbekannter_Film_ergibt_eine_leere_Liste()
{
var bilder = await Client(Attrappe.MitStatus(HttpStatusCode.NotFound)).BilderAsync("500");
Assert.That(bilder, Is.Empty);
}
/// Eine hakende fremde Quelle darf keinen Scan anhalten.
[Test]
public async Task Kein_Netz_ergibt_nichts_statt_eines_Absturzes()
{
var bilder = await Client(Attrappe.DieWirft(new HttpRequestException("weg"))).BilderAsync("500");
Assert.That(bilder, Is.Empty);
}
[Test]
public async Task Der_Schluessel_steht_in_der_Anfrage()
{
var attrappe = Attrappe.MitJson(Antwort);
await Client(attrappe).BilderAsync("500");
Assert.That(attrappe.Aufrufe[0], Does.Contain("movies/500").And.Contain("api_key=ein-schluessel"));
}
/// Ein deutsches Plakat von fanart.tv sticht ein sprachloses von TMDB.
///
///
/// Das ist der ganze Zweck der zweiten Quelle, und die Rangfolge dafür
/// liegt im Kern — sie muss für beide Quellen dieselbe sein, sonst kämen
/// die Bilder zweier Anbieter in zwei Reihenfolgen zusammen.
///
[Test]
public async Task Die_gemeinsame_Rangfolge_stellt_das_deutsche_nach_vorn()
{
var vonFanart = await Client(Attrappe.MitJson(Antwort)).BilderAsync("500");
var vonTmdb = new[]
{
new Bildkandidat("poster", "tmdb-ohne.jpg", "t", null, 9.5),
new Bildkandidat("poster", "tmdb-en.jpg", "t", "en", 9.9),
};
var geordnet = Bildrang
.Geordnet(vonTmdb.Concat(vonFanart.Where(b => b.Kind == "poster")), "de")
.ToList();
Assert.Multiple(() =>
{
Assert.That(geordnet[0].Url, Does.EndWith("de.jpg"));
Assert.That(geordnet[0].Quelle, Is.EqualTo("fanart"));
Assert.That(geordnet[1].Url, Does.Contain("ohne"), "dann das sprachlose, egal von wem");
});
}
}
public sealed record FesterFanartSchluessel(string? Wert) : IFanartSettingsSource
{
public Task SchluesselAsync(CancellationToken ct = default) => Task.FromResult(Wert);
}