using System.Net; using System.Net.Http.Json; using Flaro.Api.Endpoints; namespace Flaro.Api.Tests; /// Wer gerade was schaut. public class DashboardTests { private string _bestand = ""; [SetUp] public void Anlegen() => _bestand = Directory.CreateDirectory( Path.Combine(Path.GetTempPath(), "flaro-dash-" + Guid.CreateVersion7().ToString("N"))).FullName; [TearDown] public void Aufraeumen() { try { Directory.Delete(_bestand, recursive: true); } catch (IOException) { /* Kür */ } } private void Datei(string relativ) { var voll = Path.Combine(_bestand, relativ); Directory.CreateDirectory(Path.GetDirectoryName(voll)!); File.WriteAllBytes(voll, new byte[2048]); } private async Task Eingelesen(FlaroServer server, string art = "Movies") { var admin = await server.SetUpAndSignIn(); var client = server.AlsAngemeldeter(admin.Token); var angelegt = await client.PostAsJsonAsync("/api/v1/libraries", new CreateLibraryRequest("Prüfbestand", art, _bestand)); angelegt.EnsureSuccessStatusCode(); var bibliothek = (await angelegt.Content.ReadFromJsonAsync())!; (await client.PostAsync($"/api/v1/libraries/{bibliothek.Id}/scan", null)).EnsureSuccessStatusCode(); for (var versuch = 0; versuch < 100; versuch++) { var stand = await client.GetFromJsonAsync($"/api/v1/libraries/{bibliothek.Id}/scan"); if (stand!.State is "finished") return client; if (stand.State is "failed") Assert.Fail($"Der Scan ist gescheitert: {stand.Error}"); await Task.Delay(50); } Assert.Fail("Der Scan wurde in fünf Sekunden nicht fertig."); return null!; } private static async Task ErsterFilm(HttpClient client) => (await client.GetFromJsonAsync>("/api/v1/movies"))!.Items[0].Id; /// Die Fortschrittsmeldung ist zugleich das Lebenszeichen. /// /// /// Kein zweites Verfahren, das ein Client vergessen könnte: er meldet /// beim Abspielen ohnehin alle paar Sekunden, wo er steht. /// [Test] public async Task Eine_Fortschrittsmeldung_erscheint_im_Dashboard() { Datei("Matrix (1999)/Matrix (1999).mkv"); using var server = new FlaroServer(); var client = await Eingelesen(server); var film = await ErsterFilm(client); await client.PostAsJsonAsync($"/api/v1/items/{film}/progress", new ProgressRequest(600, 7200)); var laufend = await client.GetFromJsonAsync>("/api/v1/system/sessions"); Assert.Multiple(() => { Assert.That(laufend, Has.Count.EqualTo(1)); Assert.That(laufend![0].Title, Is.EqualTo("Matrix")); Assert.That(laufend[0].UserName, Is.EqualTo("guido")); Assert.That(laufend[0].DeviceName, Is.EqualTo("iPhone")); Assert.That(laufend[0].PositionSeconds, Is.EqualTo(600)); }); } /// Beendet heisst sofort weg, nicht erst nach einer Minute. /// /// /// Ohne das stünde ein beendeter Film noch eine Minute als „läuft" — und /// wer gerade den Spieler geschlossen hat, sähe sich selbst beim Schauen /// zu. /// [Test] public async Task Eine_beendete_Wiedergabe_verschwindet_sofort() { Datei("Matrix (1999)/Matrix (1999).mkv"); using var server = new FlaroServer(); var client = await Eingelesen(server); var film = await ErsterFilm(client); await client.PostAsJsonAsync($"/api/v1/items/{film}/progress", new ProgressRequest(600, 7200)); await client.PostAsJsonAsync($"/api/v1/items/{film}/progress", new ProgressRequest(900, 7200, Stopped: true)); var laufend = await client.GetFromJsonAsync>("/api/v1/system/sessions"); Assert.That(laufend, Is.Empty); // Der Fortschritt bleibt trotzdem erhalten — nur das „läuft gerade" // ist vorbei. var seite = await client.GetFromJsonAsync>("/api/v1/movies"); Assert.That(seite!.Items[0].State!.PositionSeconds, Is.EqualTo(900)); } /// Eine Folge nennt Serie und Nummer, nicht nur den Folgentitel. [Test] public async Task Eine_Folge_erscheint_mit_Serie_und_Nummer() { Datei("Dark/Season 01/Dark - S01E02 - Luegen.mkv"); using var server = new FlaroServer(); var client = await Eingelesen(server, "Shows"); var serien = await client.GetFromJsonAsync>("/api/v1/series"); var folgen = await client.GetFromJsonAsync>( $"/api/v1/series/{serien!.Items[0].Id}/episodes"); await client.PostAsJsonAsync($"/api/v1/items/{folgen!.Items[0].Id}/progress", new ProgressRequest(400, 2700)); var laufend = await client.GetFromJsonAsync>("/api/v1/system/sessions"); Assert.Multiple(() => { Assert.That(laufend![0].Title, Is.EqualTo("Dark")); Assert.That(laufend[0].SubTitle, Does.Contain("S1").And.Contain("F2")); }); } /// Wer wann was schaut, geht nicht jeden an. [Test] public async Task Nur_Administratoren_sehen_das_Dashboard() { using var server = new FlaroServer(); var admin = server.AlsAngemeldeter((await server.SetUpAndSignIn()).Token); (await admin.PostAsJsonAsync("/api/v1/users", new CreateUserRequest("mitbewohner", "ein-langes-passwort", false))).EnsureSuccessStatusCode(); var gast = server.AlsAngemeldeter( (await server.SignIn("mitbewohner", "ein-langes-passwort", "iPad", "geraet-2")).Token); Assert.Multiple(async () => { Assert.That((await gast.GetAsync("/api/v1/system/sessions")).StatusCode, Is.EqualTo(HttpStatusCode.Forbidden)); Assert.That((await gast.GetAsync("/api/v1/system/status")).StatusCode, Is.EqualTo(HttpStatusCode.Forbidden)); }); } /// Zwei Geräte desselben Menschen sind zwei Wiedergaben. /// /// /// Derselbe Mensch kann auf dem Fernseher und auf dem Telefon /// gleichzeitig etwas laufen lassen; beides gehört ins Dashboard. /// [Test] public async Task Zwei_Geraete_erscheinen_getrennt() { Datei("Matrix (1999)/Matrix (1999).mkv"); using var server = new FlaroServer(); var telefon = await Eingelesen(server); var film = await ErsterFilm(telefon); var fernseher = server.AlsAngemeldeter( (await server.SignIn("guido", "ein-langes-passwort", "Apple TV", "geraet-tv")).Token); await telefon.PostAsJsonAsync($"/api/v1/items/{film}/progress", new ProgressRequest(100, 7200)); await fernseher.PostAsJsonAsync($"/api/v1/items/{film}/progress", new ProgressRequest(3000, 7200)); var laufend = await telefon.GetFromJsonAsync>("/api/v1/system/sessions"); Assert.Multiple(() => { Assert.That(laufend, Has.Count.EqualTo(2)); Assert.That(laufend!.Select(w => w.DeviceName), Is.EquivalentTo(new[] { "iPhone", "Apple TV" })); }); } [Test] public async Task Der_Serverzustand_zaehlt_was_gerade_laeuft() { Datei("Matrix (1999)/Matrix (1999).mkv"); using var server = new FlaroServer(); var client = await Eingelesen(server); var film = await ErsterFilm(client); await client.PostAsJsonAsync($"/api/v1/items/{film}/progress", new ProgressRequest(60, 7200)); var stand = await client.GetFromJsonAsync("/api/v1/system/status"); Assert.Multiple(() => { Assert.That(stand!.Playing, Is.EqualTo(1)); Assert.That(stand.Scanning, Is.Zero, "der Scan ist längst durch"); Assert.That(stand.Uptime, Is.GreaterThan(0)); }); } }