Files
Melo/test/library/my_music_screen_test.dart
dustinandClaude Opus 5 7aa98864aa Kategorien (mehrere je Song), Metadaten-Ansicht mit Expertenmodus
- DB-Schema 4: Tabelle song_categories + Spalte categories_edited
- Kategorien kommen aus dem Genre-Tag (Trennung an ; , | /), manuell
  bearbeitbar; von Hand gesetzte Kategorien ueberlebt der naechste Scan
- Songzeile zeigt "Kuenstler | Kategorie1 - Kategorie2"
- Einstellung "Gleiche Kategorie = gleiches Coverbild" (Standard an)
- Metadaten-Sheet mit ausklappbarem Expertenmodus
- Neu: categories.dart, category_service.dart, song_detail_sheet.dart,
  app_settings.dart

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011snPXPafPC5i87o68H14W7
2026-08-20 18:29:45 +02:00

154 lines
5.2 KiB
Dart
Raw Permalink 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:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:melo/library/category_service.dart';
import 'package:melo/library/database.dart';
import 'package:melo/library/favorites_screen.dart';
import 'package:melo/library/library_service.dart';
import 'package:melo/library/my_music_screen.dart';
import 'package:melo/library/playlist_service.dart';
import 'package:melo/player/audio_handler.dart';
import 'package:melo/settings/app_settings.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
Widget _wrap(MeloDb db, LibraryService lib, PlaylistService playlists,
MeloAudioHandler handler, Widget child) {
return MultiProvider(
providers: [
Provider<MeloDb>.value(value: db),
ChangeNotifierProvider<LibraryService>.value(value: lib),
ChangeNotifierProvider<PlaylistService>.value(value: playlists),
Provider<MeloAudioHandler>.value(value: handler),
ChangeNotifierProvider<CategoryService>(create: (_) => CategoryService(db)),
ChangeNotifierProvider<AppSettings>(create: (_) => AppSettings()),
],
child: MaterialApp(home: Scaffold(body: child)),
);
}
Future<void> _insert(
MeloDb db, {
required String id,
required String title,
int dateAddedMs = 0,
int playCount = 0,
}) {
return db.into(db.songs).insert(SongsCompanion.insert(
id: id,
path: '/$id.mp3',
title: title,
dateAddedMs: dateAddedMs,
updatedAtMs: 0,
playCount: Value(playCount),
));
}
void main() {
setUp(() => SharedPreferences.setMockInitialValues({}));
testWidgets('Meine Musik zeigt Kopfzeile, Schnellzugriffe und Shuffle',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db);
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
await _insert(db, id: '1', title: 'Song A');
await tester.pumpWidget(
_wrap(db, lib, playlists, handler, const MyMusicScreen()));
await tester.pumpAndSettle();
expect(find.text('Titel, Künstler und Alben suchen'), findsOneWidget);
expect(find.text('Favoriten'), findsOneWidget);
expect(find.text('Wiedergabelisten'), findsOneWidget);
expect(find.text('Shuffle-Wiedergabe'), findsOneWidget);
expect(find.text('Song A'), findsOneWidget);
handler.dispose();
await db.close();
});
testWidgets('Sortier-Menü bietet alle drei Kriterien und sortiert die Liste',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db);
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
await _insert(db, id: '1', title: 'Zenit', dateAddedMs: 300, playCount: 9);
await _insert(db, id: '2', title: 'Anfang', dateAddedMs: 100, playCount: 1);
await tester.pumpWidget(
_wrap(db, lib, playlists, handler, const MyMusicScreen()));
await tester.pumpAndSettle();
// Standard: zuletzt hinzugefügt zuerst.
var titles = tester.widgetList<Text>(find.byType(Text))
.map((t) => t.data)
.where((t) => t == 'Zenit' || t == 'Anfang')
.toList();
expect(titles.first, 'Zenit');
await tester.tap(find.byIcon(Icons.swap_vert));
await tester.pumpAndSettle();
expect(find.text('Zuletzt hinzugefügt'), findsOneWidget);
expect(find.text('Name (AZ#)'), findsOneWidget);
expect(find.text('Wie oft abgespielt'), findsOneWidget);
await tester.tap(find.text('Name (AZ#)'));
await tester.pumpAndSettle();
await tester.tap(find.text('Übernehmen'));
await tester.pumpAndSettle();
titles = tester.widgetList<Text>(find.byType(Text))
.map((t) => t.data)
.where((t) => t == 'Zenit' || t == 'Anfang')
.toList();
expect(titles.first, 'Anfang');
handler.dispose();
await db.close();
});
testWidgets('Favoriten-Tab zeigt nur favorisierte Songs mit Shuffle',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db);
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
await _insert(db, id: '1', title: 'Geliebt');
await _insert(db, id: '2', title: 'Egal');
await db.setFavorite('1', true);
await tester.pumpWidget(
_wrap(db, lib, playlists, handler, const FavoritesScreen()));
await tester.pumpAndSettle();
expect(find.text('Shuffle-Wiedergabe'), findsOneWidget);
expect(find.text('Geliebt'), findsOneWidget);
expect(find.text('Egal'), findsNothing);
handler.dispose();
await db.close();
});
testWidgets('Favoriten-Tab zeigt einen Hinweis, wenn nichts favorisiert ist',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db);
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
await tester.pumpWidget(
_wrap(db, lib, playlists, handler, const FavoritesScreen()));
await tester.pumpAndSettle();
expect(find.text('Noch keine Favoriten'), findsOneWidget);
handler.dispose();
await db.close();
});
}