import 'package:flutter_test/flutter_test.dart'; import 'package:minstrel/models/album.dart'; import 'package:minstrel/models/artist.dart'; import 'package:minstrel/models/home_data.dart'; import 'package:minstrel/models/track.dart'; import 'package:minstrel/models/user.dart'; void main() { group('User.fromJson', () { test('parses canonical UserView shape', () { final u = User.fromJson({ 'id': 'usr-1', 'username': 'alice', 'is_admin': true, }); expect(u.id, 'usr-1'); expect(u.username, 'alice'); expect(u.isAdmin, isTrue); }); test('defaults is_admin to false when missing', () { final u = User.fromJson({'id': 'usr-2', 'username': 'bob'}); expect(u.isAdmin, isFalse); }); }); group('ArtistRef.fromJson', () { test('parses full payload using server cover_url field', () { final a = ArtistRef.fromJson({ 'id': 'art-1', 'name': 'Boards of Canada', 'sort_name': 'Boards of Canada', 'album_count': 7, 'cover_url': '/api/albums/al-1/cover', }); expect(a.name, 'Boards of Canada'); expect(a.sortName, 'Boards of Canada'); expect(a.albumCount, 7); expect(a.coverUrl, '/api/albums/al-1/cover'); }); test('tolerates missing optional fields', () { final a = ArtistRef.fromJson({'id': 'art-2', 'name': 'Aphex Twin'}); expect(a.sortName, ''); expect(a.albumCount, 0); expect(a.coverUrl, ''); }); }); group('AlbumRef.fromJson', () { test('parses full payload with year and duration_sec', () { final a = AlbumRef.fromJson({ 'id': 'al-1', 'title': 'Geogaddi', 'sort_title': 'Geogaddi', 'artist_id': 'art-1', 'artist_name': 'Boards of Canada', 'year': 2002, 'track_count': 23, 'duration_sec': 4020, 'cover_url': '/api/albums/al-1/cover', }); expect(a.title, 'Geogaddi'); expect(a.year, 2002); expect(a.trackCount, 23); expect(a.durationSec, 4020); expect(a.coverUrl, '/api/albums/al-1/cover'); }); test('leaves year null when absent', () { final a = AlbumRef.fromJson({ 'id': 'al-2', 'title': 'Untitled', 'artist_id': 'art-1', }); expect(a.year, isNull); expect(a.trackCount, 0); expect(a.durationSec, 0); }); }); group('TrackRef.fromJson', () { test('parses full payload including stream_url', () { final t = TrackRef.fromJson({ 'id': 'tr-1', 'title': 'Music Is Math', 'album_id': 'al-1', 'album_title': 'Geogaddi', 'artist_id': 'art-1', 'artist_name': 'Boards of Canada', 'track_number': 5, 'disc_number': 1, 'duration_sec': 379, 'stream_url': '/api/tracks/tr-1/stream', }); expect(t.title, 'Music Is Math'); expect(t.trackNumber, 5); expect(t.discNumber, 1); expect(t.durationSec, 379); expect(t.streamUrl, '/api/tracks/tr-1/stream'); }); test('leaves track_number and disc_number null when omitted', () { final t = TrackRef.fromJson({ 'id': 'tr-2', 'title': 'Hidden', 'album_id': 'al-1', 'artist_id': 'art-1', }); expect(t.trackNumber, isNull); expect(t.discNumber, isNull); }); }); group('HomeData.fromJson', () { test('handles missing sections as empty lists', () { final h = HomeData.fromJson({}); expect(h.recentlyAddedAlbums, isEmpty); expect(h.rediscoverAlbums, isEmpty); expect(h.rediscoverArtists, isEmpty); expect(h.mostPlayedTracks, isEmpty); expect(h.lastPlayedArtists, isEmpty); }); test('parses populated payload across all five sections', () { final h = HomeData.fromJson({ 'recently_added_albums': [ { 'id': 'al-1', 'title': 'Geogaddi', 'artist_id': 'art-1', 'artist_name': 'Boards of Canada', 'cover_url': '/api/albums/al-1/cover', } ], 'rediscover_albums': [ { 'id': 'al-2', 'title': 'Music Has the Right to Children', 'artist_id': 'art-1', 'artist_name': 'Boards of Canada', } ], 'rediscover_artists': [ {'id': 'art-2', 'name': 'Aphex Twin'} ], 'most_played_tracks': [ { 'id': 'tr-1', 'title': 'Roygbiv', 'album_id': 'al-2', 'artist_id': 'art-1', 'duration_sec': 150, } ], 'last_played_artists': [ {'id': 'art-3', 'name': 'Tycho'} ], }); expect(h.recentlyAddedAlbums.single.title, 'Geogaddi'); expect(h.recentlyAddedAlbums.single.coverUrl, '/api/albums/al-1/cover'); expect(h.rediscoverAlbums.single.id, 'al-2'); expect(h.rediscoverArtists.single.name, 'Aphex Twin'); expect(h.mostPlayedTracks.single.durationSec, 150); expect(h.lastPlayedArtists.single.name, 'Tycho'); }); }); }