Files
Melo/test/library/database_playlists_test.dart
T
Hermes (Server)andClaude Haiku 4.5 d09a677315 feat(database): add Playlists, Favorites, PlaybackHistory tables
- Playlists + PlaylistSongs tables with position-ordered join query
- Favorites table with toggle + watch (reactive heart icon support)
- PlaybackHistory table for resume-position tracking
- Schema v2 with migration from v1
- Follows existing Songs/Folders sync-ready pattern (uuid id, updatedAtMs, deleted)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-18 15:13:44 +02:00

111 lines
3.4 KiB
Dart

import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:melo/library/database.dart';
void main() {
late MeloDb db;
setUp(() {
db = MeloDb(NativeDatabase.memory());
});
tearDown(() async {
await db.close();
});
group('Playlists', () {
test('createPlaylist inserts and watchPlaylists emits it', () async {
await db.createPlaylist('Workout');
final playlists = await db.watchPlaylists().first;
expect(playlists.length, 1);
expect(playlists.first.name, 'Workout');
});
test('deletePlaylist removes it', () async {
final id = await db.createPlaylist('Temp');
await db.deletePlaylist(id);
final playlists = await db.watchPlaylists().first;
expect(playlists, isEmpty);
});
});
group('PlaylistSongs', () {
test('addSongToPlaylist + watchPlaylistSongs returns song in order', () async {
final playlistId = await db.createPlaylist('My List');
await db.into(db.songs).insert(SongsCompanion.insert(
id: 'song-1',
path: '/a.mp3',
title: 'Song A',
dateAddedMs: 0,
updatedAtMs: 0,
));
await db.addSongToPlaylist(playlistId, 'song-1', 0);
final songs = await db.watchPlaylistSongs(playlistId).first;
expect(songs.length, 1);
expect(songs.first.title, 'Song A');
});
test('removeSongFromPlaylist removes it', () async {
final playlistId = await db.createPlaylist('My List');
await db.into(db.songs).insert(SongsCompanion.insert(
id: 'song-1',
path: '/a.mp3',
title: 'Song A',
dateAddedMs: 0,
updatedAtMs: 0,
));
await db.addSongToPlaylist(playlistId, 'song-1', 0);
await db.removeSongFromPlaylist(playlistId, 'song-1');
final songs = await db.watchPlaylistSongs(playlistId).first;
expect(songs, isEmpty);
});
});
group('Favorites', () {
test('toggleFavorite marks then unmarks a song', () async {
await db.into(db.songs).insert(SongsCompanion.insert(
id: 'song-1',
path: '/a.mp3',
title: 'Song A',
dateAddedMs: 0,
updatedAtMs: 0,
));
await db.toggleFavorite('song-1');
expect(await db.watchIsFavorite('song-1').first, true);
await db.toggleFavorite('song-1');
expect(await db.watchIsFavorite('song-1').first, false);
});
test('watchFavorites returns favorited songs only', () async {
await db.into(db.songs).insert(SongsCompanion.insert(
id: 'song-1', path: '/a.mp3', title: 'Fav', dateAddedMs: 0, updatedAtMs: 0,
));
await db.into(db.songs).insert(SongsCompanion.insert(
id: 'song-2', path: '/b.mp3', title: 'NotFav', dateAddedMs: 0, updatedAtMs: 0,
));
await db.toggleFavorite('song-1');
final favs = await db.watchFavorites().first;
expect(favs.length, 1);
expect(favs.first.title, 'Fav');
});
});
group('PlaybackHistory', () {
test('recordPlayback + lastPosition roundtrip', () async {
await db.into(db.songs).insert(SongsCompanion.insert(
id: 'song-1', path: '/a.mp3', title: 'A', dateAddedMs: 0, updatedAtMs: 0,
));
await db.recordPlayback('song-1', 45000);
expect(await db.lastPosition('song-1'), 45000);
});
test('lastPosition returns null when never played', () async {
expect(await db.lastPosition('unknown'), isNull);
});
});
}