Einzelne Server-Titel offline nehmen und wieder entfernen
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:melo/library/database.dart';
|
||||
import 'package:melo/downloads/server_titel_screen.dart';
|
||||
import 'package:melo/player/audio_handler.dart';
|
||||
import 'package:melo/services/download_service.dart';
|
||||
import 'package:melo/services/navidrome_service.dart';
|
||||
|
||||
/// Merkt sich nur, was verlangt wurde — echte Downloads brauchen einen
|
||||
/// Server, und darum geht es hier nicht.
|
||||
class _FakeDownloads extends DownloadService {
|
||||
_FakeDownloads(MeloDb db) : super(db: db, navidrome: NavidromeService());
|
||||
|
||||
final geladen = <String>[];
|
||||
final entfernt = <String>[];
|
||||
|
||||
@override
|
||||
bool get laeuft => false;
|
||||
|
||||
@override
|
||||
Future<bool> ladeEinzelnenTitel(SubsonicSong song) async {
|
||||
geladen.add(song.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> entferne(String navidromeId) async {
|
||||
entfernt.add(navidromeId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
final titel = [
|
||||
const SubsonicSong(
|
||||
id: 'nav-1',
|
||||
titel: 'Nachtpuls',
|
||||
kuenstler: 'Rotklang',
|
||||
album: 'Nacht',
|
||||
dauerSekunden: 200,
|
||||
),
|
||||
];
|
||||
|
||||
Future<({_FakeDownloads dienst, MeloAudioHandler handler})> pumpe(
|
||||
WidgetTester tester,
|
||||
{bool schonGeladen = false}) async {
|
||||
final db = MeloDb(NativeDatabase.memory());
|
||||
addTearDown(db.close);
|
||||
if (schonGeladen) {
|
||||
// Der Bildschirm liest den Zustand einmal per db.downloadIds().
|
||||
await db.merkeDownload(DownloadsCompanion.insert(
|
||||
navidromeId: 'nav-1',
|
||||
titel: 'Nachtpuls',
|
||||
groesseBytes: 1,
|
||||
geladenAmMs: 0,
|
||||
));
|
||||
}
|
||||
final dienst = _FakeDownloads(db);
|
||||
// MeloAudioHandler startet einen periodischen Timer (Positions-
|
||||
// Buchführung). Ohne handler.dispose() meldet der Testrahmen ihn als
|
||||
// „pending" — dasselbe etablierte Muster wie in
|
||||
// test/library/my_music_screen_test.dart: handler.dispose() explizit am
|
||||
// Testende aufrufen (addTearDown greift zu spät, außerhalb der
|
||||
// FakeAsync-Zone, in der der Timer geprüft wird).
|
||||
final handler = MeloAudioHandler(db: db);
|
||||
await tester.pumpWidget(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
Provider<MeloDb>.value(value: db),
|
||||
ChangeNotifierProvider<DownloadService>.value(value: dienst),
|
||||
Provider<MeloAudioHandler>.value(value: handler),
|
||||
],
|
||||
child: MaterialApp(
|
||||
home: ServerTitelScreen(
|
||||
titel: 'Nacht',
|
||||
navidrome: NavidromeService(),
|
||||
holeTitel: () async => titel,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle(
|
||||
const Duration(milliseconds: 100),
|
||||
EnginePhase.sendSemanticsUpdate,
|
||||
const Duration(seconds: 5),
|
||||
);
|
||||
return (dienst: dienst, handler: handler);
|
||||
}
|
||||
|
||||
testWidgets('ein einzelner Titel lässt sich offline nehmen', (tester) async {
|
||||
final (:dienst, :handler) = await pumpe(tester);
|
||||
|
||||
await tester.tap(find.byTooltip('Offline nehmen'));
|
||||
await tester.pumpAndSettle(
|
||||
const Duration(milliseconds: 100),
|
||||
EnginePhase.sendSemanticsUpdate,
|
||||
const Duration(seconds: 5),
|
||||
);
|
||||
|
||||
expect(dienst.geladen, ['nav-1']);
|
||||
expect(dienst.entfernt, isEmpty);
|
||||
|
||||
handler.dispose();
|
||||
});
|
||||
|
||||
testWidgets('ein schon geladener Titel bietet den Gegenweg an',
|
||||
(tester) async {
|
||||
final (:dienst, :handler) =
|
||||
await pumpe(tester, schonGeladen: true);
|
||||
|
||||
// Zustand „schon offline": statt „Offline nehmen" steht dort das
|
||||
// Entfernen — ohne diesen Test wäre der halbe Knopf ungeprüft.
|
||||
expect(find.byTooltip('Offline nehmen'), findsNothing);
|
||||
|
||||
await tester.tap(find.byTooltip('Vom Gerät entfernen'));
|
||||
await tester.pumpAndSettle(
|
||||
const Duration(milliseconds: 100),
|
||||
EnginePhase.sendSemanticsUpdate,
|
||||
const Duration(seconds: 5),
|
||||
);
|
||||
|
||||
expect(dienst.entfernt, ['nav-1']);
|
||||
expect(dienst.geladen, isEmpty);
|
||||
|
||||
handler.dispose();
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user