import pytest from datetime import datetime from lintunes.models import Track, Playlist, PlaylistSettings, PlaylistType, Library class TestTrack: def test_to_dict_omits_defaults(self): track = Track(track_id=1, name="Test Song") d = track.to_dict() assert d == {"track_id": 1, "name": "Test Song"} assert "genre" not in d assert "play_count" not in d def test_from_dict_round_trip(self): track = Track( track_id=42, name="My Song", artist="The Artist", album="The Album", genre="Rock", total_time=180000, play_count=5, rating=80, loved=True, date_added="2020-01-15T10:30:00", ) d = track.to_dict() restored = Track.from_dict(d) assert restored.track_id == 42 assert restored.name == "My Song" assert restored.artist == "The Artist" assert restored.play_count == 5 assert restored.rating == 80 assert restored.loved is True def test_from_dict_ignores_unknown_fields(self): d = {"track_id": 1, "name": "Test", "unknown_field": "ignored"} track = Track.from_dict(d) assert track.track_id == 1 assert track.name == "Test" def test_from_itunes_dict(self): itunes_data = { "Track ID": 100, "Name": "iTunes Song", "Artist": "iTunes Artist", "Album": "iTunes Album", "Genre": "Pop", "Total Time": 240000, "Play Count": 10, "Play Date UTC": datetime(2023, 6, 15, 12, 0, 0), "Date Added": datetime(2020, 3, 1, 8, 0, 0), "Rating": 100, "Loved": True, "Persistent ID": "ABC123", "Location": "file://localhost/Users/me/Music/Artist/Album/Song.mp3", } track = Track.from_itunes_dict(itunes_data) assert track.track_id == 100 assert track.name == "iTunes Song" assert track.total_time == 240000 assert track.play_count == 10 assert track.rating == 100 assert track.loved is True assert track.play_date_utc == "2023-06-15T12:00:00" assert track.location == "/Users/me/Music/Artist/Album/Song.mp3" def test_location_decoding(self): itunes_data = { "Track ID": 1, "Location": "file://localhost/Users/me/Music/The%20Artist/My%20Album/01%20Song.mp3", } track = Track.from_itunes_dict(itunes_data) assert track.location == "/Users/me/Music/The Artist/My Album/01 Song.mp3" def test_location_decoding_volumes_form(self): # Modern iTunes XML uses file:///Volumes/... URLs itunes_data = { "Track ID": 1, "Location": "file:///Volumes/Lucia/iTunes/iTunes%20Media/Music/A/B/C.m4a", } track = Track.from_itunes_dict(itunes_data) assert track.location == "/Volumes/Lucia/iTunes/iTunes Media/Music/A/B/C.m4a" class TestPlaylist: def test_to_dict_from_dict_round_trip(self): playlist = Playlist( name="My Favorites", persistent_id="ABCD1234", playlist_type=PlaylistType.REGULAR, track_ids=[1, 2, 3, 4, 5], ) d = playlist.to_dict() restored = Playlist.from_dict(d) assert restored.name == "My Favorites" assert restored.persistent_id == "ABCD1234" assert restored.playlist_type == PlaylistType.REGULAR assert restored.track_ids == [1, 2, 3, 4, 5] def test_from_itunes_dict_regular(self): itunes_data = { "Name": "Party Mix", "Playlist Persistent ID": "XYZ789", "Playlist Items": [ {"Track ID": 10}, {"Track ID": 20}, {"Track ID": 30}, ], } playlist = Playlist.from_itunes_dict(itunes_data) assert playlist.name == "Party Mix" assert playlist.persistent_id == "XYZ789" assert playlist.playlist_type == PlaylistType.REGULAR assert playlist.track_ids == [10, 20, 30] assert playlist.is_system is False def test_from_itunes_dict_system(self): itunes_data = { "Name": "Library", "Master": True, "Playlist Persistent ID": "MASTER1", "Playlist Items": [{"Track ID": 1}], } playlist = Playlist.from_itunes_dict(itunes_data) assert playlist.is_system is True assert playlist.playlist_type == PlaylistType.SYSTEM def test_from_itunes_dict_folder(self): itunes_data = { "Name": "My Folder", "Folder": True, "Playlist Persistent ID": "FOLDER1", } playlist = Playlist.from_itunes_dict(itunes_data) assert playlist.playlist_type == PlaylistType.FOLDER def test_from_itunes_dict_smart(self): itunes_data = { "Name": "Recently Added", "Smart Info": b"...", "Smart Criteria": b"...", "Playlist Persistent ID": "SMART1", } playlist = Playlist.from_itunes_dict(itunes_data) assert playlist.playlist_type == PlaylistType.SMART class TestPlaylistSettings: def test_default_settings(self): settings = PlaylistSettings() assert "name" in settings.visible_columns assert settings.sort_ascending is True def test_round_trip(self): settings = PlaylistSettings( visible_columns=["name", "artist"], sort_column="artist", sort_ascending=False, column_widths={"name": 300}, ) d = settings.to_dict() restored = PlaylistSettings.from_dict(d) assert restored.visible_columns == ["name", "artist"] assert restored.sort_column == "artist" assert restored.sort_ascending is False assert restored.column_widths == {"name": 300} class TestLibrary: def test_empty_library(self): lib = Library() assert len(lib.tracks) == 0 assert len(lib.playlists) == 0