Files
Melo/test/library/my_music_screen_test.dart
T
Hermes (Server)andClaude Sonnet 5 da012a3dca Tab-Reihenfolge, konfigurierbare Meine-Musik-Sektionen, Berechtigungen beim Start, schärferes Sperrbildschirm-Cover
- Tabs: Meine Musik, Suchen, Download, Favoriten (vorher Download vor Suchen)
- "Meine Musik": Schnellzugriffe (Favoriten/Wiedergabelisten/Zuletzt) einzeln
  über die Einstellungen abschaltbar
- Audio- und Benachrichtigungs-Berechtigung werden jetzt beim ersten Start
  gemeinsam angefragt statt erst bei Bedarf; Hinweisbanner + Einstellungen-
  Button bei dauerhafter Verweigerung (auch für Benachrichtigungen neu)
- Cover-Extraktion beim Android-Scan von 512px auf 1024px erhöht, für ein
  schärferes Cover im Sperrbildschirm
- Fix: notifyListeners() in LibraryService nur noch bei echter Wertänderung
  (verhinderte einen Test-Hang durch den neuen Start-Berechtigungs-Aufruf)

557 Tests grün, flutter analyze ohne Befund.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VM2JK5mV7AL1g2Rt6H6h9w
2026-08-25 14:17:13 +02:00

203 lines
6.8 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: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, {AppSettings? settings}) {
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)),
settings == null
? ChangeNotifierProvider<AppSettings>(create: (_) => AppSettings())
: ChangeNotifierProvider<AppSettings>.value(value: settings),
],
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(
'abgewählte Sektionen fehlen in den Schnellzugriffen, aktive bleiben',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db);
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
final settings = AppSettings();
await settings.init();
await settings.setMeineMusikSektionAktiv(
AppSettings.sektionWiedergabelisten, false);
await tester.pumpWidget(_wrap(
db, lib, playlists, handler, const MyMusicScreen(),
settings: settings));
await tester.pumpAndSettle();
expect(find.text('Favoriten'), findsOneWidget);
expect(find.text('Zuletzt'), findsOneWidget);
expect(find.text('Wiedergabelisten'), findsNothing);
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();
});
testWidgets(
'Banner mit "Einstellungen"-Button, wenn die Benachrichtigung verweigert ist',
(tester) async {
final db = MeloDb(NativeDatabase.memory());
final lib = LibraryService(db)..notificationPermissionDenied = true;
final playlists = PlaylistService(db);
final handler = MeloAudioHandler(db: db);
await tester.pumpWidget(
_wrap(db, lib, playlists, handler, const MyMusicScreen()));
await tester.pumpAndSettle();
expect(
find.textContaining('Benachrichtigungen für die Wiedergabe'),
findsOneWidget,
);
expect(find.text('Einstellungen'), findsOneWidget);
handler.dispose();
await db.close();
});
}