Files
Melo/test/shared/cover_test.dart
Hermes (Server)andClaude Opus 5 0d76d8cc58 Album-Ansicht, mitlaufender Songtext, Cover-Cache, Server-Favoriten
Die letzten vier Punkte aus dem Review-Bericht.

G2 — Server-Bereich: Ein Tipp auf ein Album spielte sofort alles ab;
hineinsehen ging nicht. Jetzt Album- und Kuenstler-Ansicht mit Cover,
Kuenstler, Titelzahl, Gesamtdauer, "Abspielen"/"Zufaellig" und der
Titelliste; Antippen startet an dieser Stelle. Dazu "Mehr Alben laden" —
die Liste hoerte bei 50 auf, ohne dass etwas darauf hinwies.
NICHT umgesetzt: den Server-Bereich aus dem Download-Tab loesen (das
widerspricht Commit 34d6d8e, "Auf Wunsch von Dustin") und eine
Server-Suche (die Suche bleibt ausdruecklich rein lokal).

G8 — Songtext: Traegt der Text Zeitmarken, laeuft er mit; die aktive Zeile
ist hervorgehoben, Antippen springt an die Stelle. Ohne Zeitmarken bleibt
es eine Textwand — die App schaut nach, statt zu raten.

G10 — Cover bleiben liegen. Eigener Ordner, einmal geholt. Der Schluessel
haengt an der Album-Kennung, nicht an der Adresse: die traegt bei jedem
App-Start ein neues Token, und der Ordner waere sonst gewachsen, ohne je
einen Treffer zu liefern. Keine neue Abhaengigkeit.

G3 — Das Herz ist bei Server-Titeln nicht mehr ausgegraut, sondern
favorisiert am Server (star/unstar) — dort, wo der Favoriten-Abgleich sie
auch wieder abholt. Offen bleibt der schwere Teil: Wiedergabezaehler,
Historie und Kategorien braeuchten fuer Server-Titel eine Zeile in der
Bibliothek.

Aus dem Code-Review nachgebessert (sieben Punkte): das Herz behielt beim
Titelwechsel seinen Zustand; recycelte Listenzeilen zeigten kurz das Cover
der vorherigen; der neue Songtext bekam bei Server-Titeln die
Abspiel-Adresse statt der Server-Kennung und fand deshalb nie einen Text;
ein einmal fehlgeschlagenes Cover blieb die ganze Sitzung grau; "Server
nicht erreichbar" sah aus wie "Album hat keine Titel", womit der
Wiederholen-Knopf unerreichbar war; die Kuenstler-Ansicht waere immer leer
geblieben, weil getArtist die Titel gar nicht mitliefert; und zwei
gleichzeitige Cover-Abrufe konnten ein zerschnittenes Bild hinterlassen.

Selbst gefunden: das Haekchen "schon geladen" fragte pro Zeile die Platte
ab, bei jedem Positionswechsel neu. Jetzt einmal je Bildschirm.

457 Tests gruen (vorher 433), flutter analyze ohne Befund, Release-APK
gebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xAHJTJM6UUqmjUgk1PUEd
2026-08-23 21:53:31 +02:00

57 lines
1.9 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:melo/shared/cover.dart';
/// Server-Titel trugen nie ein Coverbild: [CoverImage] kannte nur `file://`
/// und zeigte für alles andere den Noten-Platzhalter.
void main() {
Future<void> pumpe(WidgetTester tester, Uri? artUri) => tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Center(child: CoverImage(artUri: artUri, size: 48)),
),
),
);
testWidgets('ohne Adresse bleibt der Noten-Platzhalter', (tester) async {
await pumpe(tester, null);
expect(find.byIcon(Icons.music_note), findsOneWidget);
expect(find.byType(Image), findsNothing);
});
testWidgets('eine Datei-Adresse wird als Bild geladen', (tester) async {
await pumpe(tester, Uri.file('/tmp/gibtesnicht.jpg'));
expect(find.byType(Image), findsOneWidget);
});
testWidgets('eine Server-Adresse geht über den Cover-Ordner', (tester) async {
// Server-Cover werden nicht direkt geladen, sondern erst auf die Platte
// gelegt (siehe CoverCache) — sonst wären sie nach jedem Neustart weg.
await pumpe(
tester, Uri.parse('https://musik.example/getCoverArt.view?id=1'));
expect(find.byType(FutureBuilder<File?>), findsOneWidget);
});
testWidgets('solange das Cover unterwegs ist, steht der Platzhalter',
(tester) async {
// Ohne Netz kommt nichts an. Die Zeile muss trotzdem stehen, statt
// leer zu bleiben oder zu springen.
await pumpe(tester, Uri.parse('http://musik.example/getCoverArt.view?id=1'));
expect(find.byIcon(Icons.music_note), findsOneWidget);
});
testWidgets('ein unbekanntes Schema fällt auf den Platzhalter zurück',
(tester) async {
await pumpe(tester, Uri.parse('content://media/external/audio/42'));
expect(find.byIcon(Icons.music_note), findsOneWidget);
expect(find.byType(Image), findsNothing);
});
}