import 'package:flutter_test/flutter_test.dart'; import 'package:melo/library/database.dart'; import 'package:melo/library/song_sort.dart'; Song _song( String title, { String? id, int dateAddedMs = 0, int playCount = 0, }) { return Song( id: id ?? title, path: '/$title.mp3', title: title, dateAddedMs: dateAddedMs, updatedAtMs: 0, deleted: false, playCount: playCount, categoriesEdited: false, metadataEdited: false, ); } void main() { group('SortMode.name — A-Z, Ziffern/Zeichen unter # ans Ende', () { test('sortiert Buchstaben alphabetisch, Ziffern und Zeichen danach', () { final songs = [ _song('9 Lives'), _song('Zenit'), _song('#Hashtag'), _song('Anfang'), ]; final sorted = sortSongs(songs, SortMode.name, ascending: true); expect(sorted.map((s) => s.title), ['Anfang', 'Zenit', '#Hashtag', '9 Lives']); }); test('ignoriert Groß-/Kleinschreibung', () { final songs = [_song('beta'), _song('Alpha'), _song('CHARLIE')]; final sorted = sortSongs(songs, SortMode.name, ascending: true); expect(sorted.map((s) => s.title), ['Alpha', 'beta', 'CHARLIE']); }); test('Umlaute sortieren wie ihr Grundbuchstabe', () { final songs = [_song('Zug'), _song('Ärger'), _song('Anfang'), _song('Öl')]; final sorted = sortSongs(songs, SortMode.name, ascending: true); expect(sorted.map((s) => s.title), ['Anfang', 'Ärger', 'Öl', 'Zug']); }); test('absteigend dreht die Reihenfolge um', () { final songs = [_song('Anfang'), _song('9 Lives'), _song('Zenit')]; final sorted = sortSongs(songs, SortMode.name, ascending: false); expect(sorted.map((s) => s.title), ['9 Lives', 'Zenit', 'Anfang']); }); }); group('SortMode.dateAdded', () { test('absteigend = zuletzt hinzugefügt zuerst', () { final songs = [ _song('Alt', dateAddedMs: 100), _song('Neu', dateAddedMs: 300), _song('Mittel', dateAddedMs: 200), ]; final sorted = sortSongs(songs, SortMode.dateAdded, ascending: false); expect(sorted.map((s) => s.title), ['Neu', 'Mittel', 'Alt']); }); test('aufsteigend = ältester zuerst', () { final songs = [ _song('Neu', dateAddedMs: 300), _song('Alt', dateAddedMs: 100), ]; final sorted = sortSongs(songs, SortMode.dateAdded, ascending: true); expect(sorted.map((s) => s.title), ['Alt', 'Neu']); }); }); group('SortMode.playCount', () { test('absteigend = meistgespielt zuerst', () { final songs = [ _song('Selten', playCount: 1), _song('Oft', playCount: 42), _song('Nie', playCount: 0), ]; final sorted = sortSongs(songs, SortMode.playCount, ascending: false); expect(sorted.map((s) => s.title), ['Oft', 'Selten', 'Nie']); }); }); group('Stabilität', () { test('gleiche Sortierwerte werden nach Titel entschieden', () { final songs = [ _song('Bravo', id: 'b', dateAddedMs: 5), _song('Alpha', id: 'a', dateAddedMs: 5), ]; final sorted = sortSongs(songs, SortMode.dateAdded, ascending: false); expect(sorted.map((s) => s.title), ['Alpha', 'Bravo']); }); test('verändert die Eingabeliste nicht', () { final songs = [_song('Zenit'), _song('Anfang')]; sortSongs(songs, SortMode.name, ascending: true); expect(songs.map((s) => s.title), ['Zenit', 'Anfang']); }); }); group('Standard-Richtung pro Modus', () { test('Datum und Wiedergaben starten absteigend, Name aufsteigend', () { expect(defaultAscending(SortMode.dateAdded), isFalse); expect(defaultAscending(SortMode.playCount), isFalse); expect(defaultAscending(SortMode.name), isTrue); }); }); group('Beschriftungen', () { test('jeder Modus hat ein deutsches Label', () { expect(SortMode.dateAdded.label, 'Zuletzt hinzugefügt'); expect(SortMode.name.label, 'Name (A–Z–#)'); expect(SortMode.playCount.label, 'Wie oft abgespielt'); }); }); group('indexBuchstabe', () { test('nimmt den ersten Buchstaben, groß geschrieben', () { expect(indexBuchstabe('anfang'), 'A'); expect(indexBuchstabe('Zenit'), 'Z'); }); test('Umlaute stehen unter ihrem Grundbuchstaben', () { // Genau wie in der Sortierung: "Ärger" gehört zu A, nicht ans Ende. expect(indexBuchstabe('Ärger'), 'A'); expect(indexBuchstabe('Über'), 'U'); }); test('Ziffern und Zeichen sammeln sich unter #', () { expect(indexBuchstabe('9 Lives'), '#'); expect(indexBuchstabe('#Hashtag'), '#'); expect(indexBuchstabe(' '), '#'); }); test('führender Leerraum zählt nicht', () { expect(indexBuchstabe(' Berg'), 'B'); }); }); group('buchstabenIndex', () { test('nennt je Buchstabe die erste Position', () { final sortiert = sortSongs( [_song('Anfang'), _song('Berg'), _song('Ärger'), _song('9 Lives')], SortMode.name, ascending: true, ); final index = buchstabenIndex(sortiert); // Sortiert: Anfang, Ärger, Berg, 9 Lives expect(index['A'], 0); expect(index['B'], 2); expect(index['#'], 3); }); test('ein Buchstabe ohne Titel kommt nicht vor', () { final index = buchstabenIndex([_song('Berg')]); expect(index.containsKey('A'), isFalse); expect(index['B'], 0); }); test('eine leere Liste ergibt keinen Index', () { expect(buchstabenIndex(const []), isEmpty); }); }); group('buchstabenIndex bei Z–A', () { test('nennt auch absteigend die erste Position des Buchstabens', () { // Der Sprung soll oben im Block landen, nicht unten — deshalb wird der // Index immer auf der angezeigten Reihenfolge gebaut. final sortiert = sortSongs( [_song('Anfang'), _song('Berg'), _song('Bogen'), _song('Zenit')], SortMode.name, ascending: false, ); // Angezeigt: Zenit, Bogen, Berg, Anfang final index = buchstabenIndex(sortiert); expect(index['Z'], 0); expect(index['B'], 1); expect(index['A'], 3); expect(index.keys.toList(), ['Z', 'B', 'A']); }); }); }