This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
melo-app/test/player_service_test.dart
T
Dustin b97914699e v2.48.5 — Tests für Player-Kern (Shuffle/Repeat/Queue/Sleep-Timer)
## test/player_service_test.dart (neu, 17 Tests)
- Warteschlange: setWarteschlange, unveränderliche Kopie, spieleAlsNaechstes,
  amEndeHinzufuegen, verschiebeInWarteschlange (Index-Anpassung)
- Repeat: aus (Ende → null), titel (immer aktuell), playlist (Wrap von vorn)
- Shuffle: alle anderen Songs genau einmal ohne Wiederholung, kein aktueller
  Song; shuffle+playlist mischt nach Durchlauf neu; Einzel-Song-Queue;
  Ausschluss des aktuellen Index nach Umsortieren
- Sleep-Timer: aktivieren, Restzeit, abbrechen, Ersetzen

flutter analyze 0 Issues, Tests 21/21
2026-08-04 16:27:36 +02:00

188 lines
6.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter_test/flutter_test.dart';
import 'package:melo_app/models/song.dart';
import 'package:melo_app/services/player_service.dart';
Song _song(int id, String titel) => Song(
id: id,
titel: titel,
kuenstler: 'Künstler $id',
dauerSekunden: 100,
dateiPfad: '',
);
void main() {
// PlayerService ist ein Singleton — Zustand vor jedem Test zurücksetzen
setUp(() {
final p = PlayerService();
p.setZufallsmodus(false);
p.setWiederholmodus(Wiederholmodus.aus);
p.cancelSleepTimer();
p.setWarteschlange([]);
});
group('Warteschlange', () {
test('setWarteschlange + Getter', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')]);
expect(p.warteschlange.length, 3);
expect(p.aktuellerIndex, 0);
expect(p.aktuellerSong?.titel, 'A');
});
test('warteschlange ist eine unveränderliche Kopie', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B')]);
expect(() => p.warteschlange.add(_song(3, 'C')), throwsUnsupportedError);
expect(p.warteschlange.length, 2);
});
test('spieleAlsNaechstes fügt nach dem aktuellen Song ein', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')]);
p.spieleAlsNaechstes(_song(9, 'X'));
expect(p.warteschlange.map((s) => s.id).toList(), [1, 9, 2, 3]);
expect(p.aktuellerIndex, 0);
});
test('spieleAlsNaechstes ohne Warteschlange hängt an', () {
final p = PlayerService();
p.spieleAlsNaechstes(_song(1, 'A'));
expect(p.warteschlange.length, 1);
expect(p.aktuellerIndex, -1);
});
test('amEndeHinzufuegen hängt ans Ende an', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A')]);
p.amEndeHinzufuegen(_song(2, 'B'));
expect(p.warteschlange.map((s) => s.id).toList(), [1, 2]);
});
test('verschiebeInWarteschlange passt aktuellen Index an (Song danach)', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')]);
p.verschiebeInWarteschlange(2, 0); // C nach vorne
expect(p.warteschlange.map((s) => s.id).toList(), [3, 1, 2]);
expect(p.aktuellerIndex, 1); // aktuell A (war 0, ist jetzt 1)
});
test('verschiebeInWarteschlange passt aktuellen Index an (Song davor)', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')]);
p.verschiebeInWarteschlange(0, 2); // aktueller Song selbst wandert
expect(p.warteschlange.map((s) => s.id).toList(), [2, 3, 1]);
expect(p.aktuellerIndex, 2);
});
});
group('Repeat (Wiederholmodus)', () {
test('aus: naechsterIndex null am Ende der Warteschlange', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')], startIndex: 2);
p.setWiederholmodus(Wiederholmodus.aus);
expect(p.naechsterIndex(), isNull);
});
test('titel: immer der aktuelle Song', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')], startIndex: 1);
p.setWiederholmodus(Wiederholmodus.titel);
expect(p.naechsterIndex(), 1);
expect(p.naechsterIndex(), 1);
});
test('playlist: nach dem letzten Song wieder von vorn', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')]);
p.setWiederholmodus(Wiederholmodus.playlist);
// Mittendrin: nächster ist der Folgesong
expect(p.naechsterIndex(), 1);
// Am Ende (letzter Song): wieder von vorn
p.setWarteschlange([_song(1, 'A'), _song(2, 'B'), _song(3, 'C')], startIndex: 2);
expect(p.naechsterIndex(), 0);
});
});
group('Shuffle (Zufallsmodus)', () {
test('spielt alle anderen Songs genau einmal, ohne den aktuellen', () {
final p = PlayerService();
p.setWarteschlange([for (var i = 1; i <= 5; i++) _song(i, 'S$i')]);
p.setZufallsmodus(true);
final folge = <int>[];
int? idx;
while ((idx = p.naechsterIndex()) != null) {
folge.add(idx!);
if (folge.length > 10) break; // Schutz vor Endlosschleife
}
expect(folge.length, 4); // 5 Songs aktueller
expect(folge.toSet(), {1, 2, 3, 4}); // keine Wiederholung, kein aktueller
});
test('shuffle + playlist: mischt nach Durchlauf neu weiter', () {
final p = PlayerService();
p.setWarteschlange([for (var i = 1; i <= 5; i++) _song(i, 'S$i')]);
p.setZufallsmodus(true);
p.setWiederholmodus(Wiederholmodus.playlist);
final folge = <int>[];
for (var i = 0; i < 12; i++) {
final idx = p.naechsterIndex();
expect(idx, isNotNull);
folge.add(idx!);
}
// Nie der aktuelle Song (Index 0), alle anderen kommen vor
expect(folge.every((i) => i >= 1 && i <= 4), isTrue);
expect(folge.toSet(), {1, 2, 3, 4});
});
test('shuffle mit einzelner Warteschlange: playlist wiederholt den Song', () {
final p = PlayerService();
p.setWarteschlange([_song(1, 'A')]);
p.setZufallsmodus(true);
p.setWiederholmodus(Wiederholmodus.playlist);
expect(p.naechsterIndex(), 0);
expect(p.naechsterIndex(), 0);
});
test('shuffle schließt neuen aktuellen Index nach Umsortieren aus', () {
final p = PlayerService();
p.setWarteschlange([for (var i = 1; i <= 5; i++) _song(i, 'S$i')]);
p.setZufallsmodus(true);
p.verschiebeInWarteschlange(0, 2); // aktueller Song wandert auf Index 2
expect(p.aktuellerIndex, 2);
final folge = <int>[];
int? idx;
while ((idx = p.naechsterIndex()) != null) {
folge.add(idx!);
if (folge.length > 10) break;
}
expect(folge.toSet(), {0, 1, 3, 4}); // Index 2 (aktuell) nie dabei
});
});
group('Sleep-Timer', () {
test('setSleepTimer aktiviert + Restzeit vorhanden', () {
final p = PlayerService();
p.setSleepTimer(const Duration(minutes: 30));
expect(p.sleepTimerAktiv, isTrue);
expect(p.sleepRestzeit, isNotNull);
expect(p.sleepRestzeit!.inMinutes, greaterThanOrEqualTo(29));
});
test('cancelSleepTimer deaktiviert', () {
final p = PlayerService();
p.setSleepTimer(const Duration(minutes: 15));
p.cancelSleepTimer();
expect(p.sleepTimerAktiv, isFalse);
expect(p.sleepRestzeit, isNull);
});
test('setSleepTimer ersetzt einen laufenden Timer', () {
final p = PlayerService();
p.setSleepTimer(const Duration(minutes: 15));
p.setSleepTimer(const Duration(minutes: 60));
expect(p.sleepTimerAktiv, isTrue);
expect(p.sleepRestzeit!.inMinutes, greaterThanOrEqualTo(59));
});
});
}