using System.Net;
using System.Text;
namespace Flaro.Metadata.Tests;
/// Ein HTTP-Gegenüber, das antwortet, was der Test vorgibt.
///
///
/// Damit die Prüfungen ohne Netz und ohne Schlüssel laufen. Ein
/// Projekt, dessen Tests einen fremden Dienst brauchen, hat am Ende keine
/// Tests: sie scheitern, wenn das WLAN hakt, und irgendwann schaltet sie
/// jemand ab.
///
public sealed class Attrappe(Func antwort) : HttpMessageHandler
{
public List Aufrufe { get; } = [];
/// Die Authorization-Kopfzeile je Aufruf — oder null.
public List Kopfzeilen { get; } = [];
protected override Task SendAsync(HttpRequestMessage anfrage, CancellationToken ct)
{
// AbsoluteUri und nicht ToString(): Letzteres entschlüsselt zur
// Anzeige wieder, und dann sähe eine richtig kodierte Anfrage falsch
// aus — der Test prüfte eine Darstellung statt dessen, was hinausgeht.
Aufrufe.Add(anfrage.RequestUri!.AbsoluteUri);
Kopfzeilen.Add(anfrage.Headers.Authorization?.ToString());
return Task.FromResult(antwort(anfrage));
}
public static Attrappe MitJson(string json, HttpStatusCode code = HttpStatusCode.OK) =>
new(_ => new HttpResponseMessage(code)
{
Content = new StringContent(json, Encoding.UTF8, "application/json"),
});
/// Antwortet je nach Pfad verschieden.
///
///
/// Nötig, seit ein Treffer zwei Anfragen kostet. Die Suche liefert
/// nur eine Kennung; Laufzeit, Genres, Besetzung und Schriftzug stehen
/// erst im Einzelabruf. Eine Attrappe mit einer Antwort für alles gäbe
/// dem Einzelabruf die Trefferliste zurück — und der läse daraus eine
/// Kennung von null.
///
/// Der erste Eintrag, dessen Schlüssel im Pfad vorkommt, gewinnt.
///
public static Attrappe NachPfad(params (string Teil, string Json)[] antworten) =>
new(anfrage =>
{
var pfad = anfrage.RequestUri!.AbsoluteUri;
var treffer = antworten.FirstOrDefault(a => pfad.Contains(a.Teil, StringComparison.Ordinal));
return new HttpResponseMessage(treffer.Json is null ? HttpStatusCode.NotFound : HttpStatusCode.OK)
{
Content = new StringContent(treffer.Json ?? "{}", Encoding.UTF8, "application/json"),
};
});
public static Attrappe MitStatus(HttpStatusCode code) => new(_ => new HttpResponseMessage(code));
public static Attrappe DieWirft(Exception fehler) => new(_ => throw fehler);
}
public sealed record FesteEinstellungen(TmdbSettings Werte) : ITmdbSettingsSource
{
public Task GetAsync(CancellationToken ct = default) => Task.FromResult(Werte);
public static FesteEinstellungen MitSchluessel(string sprache = "de-DE") =>
new(new TmdbSettings("ein-schluessel", sprache));
public static readonly FesteEinstellungen Ohne = new(TmdbSettings.Unconfigured);
}