from pathlib import Path import pytest from lintunes import tagging from lintunes.models import Library from lintunes.library_manager import LibraryManager from lintunes.importers import file_importer @pytest.fixture def manager(qapp, tmp_path): return LibraryManager(Library(), tmp_path / "data") class TestOrganizedDestination: def test_artist_album_layout(self): dest = file_importer.organized_destination( Path("/music"), {"artist": "The Band", "album": "Hits"}, "song.mp3") assert dest == Path("/music/The Band/Hits/song.mp3") def test_album_artist_preferred(self): dest = file_importer.organized_destination( Path("/music"), {"artist": "Feat Guy", "album_artist": "Main Act", "album": "LP"}, "song.mp3") assert dest == Path("/music/Main Act/LP/song.mp3") def test_missing_tags(self): dest = file_importer.organized_destination(Path("/music"), {}, "song.mp3") assert dest == Path("/music/Unknown Artist/Unknown Album/song.mp3") def test_sanitizes_separators(self): dest = file_importer.organized_destination( Path("/music"), {"artist": "AC/DC", "album": "Back: In Black?"}, "song.mp3") assert dest == Path("/music/AC_DC/Back_ In Black_/song.mp3") class TestImportFile: def test_copies_and_adds_track(self, manager, mp3_file, tmp_path): tagging.write_tags(mp3_file, {"name": "My Song", "artist": "Artist X", "album": "Album Y"}) music_dir = tmp_path / "music" track = file_importer.import_file(mp3_file, music_dir, manager) assert track is not None expected = music_dir / "Artist X" / "Album Y" / "test.mp3" assert Path(track.location) == expected assert expected.exists() assert track.name == "My Song" assert track.date_added assert track.track_id in manager.library.tracks def test_reimport_same_file_is_deduped(self, manager, mp3_file, tmp_path): music_dir = tmp_path / "music" track1 = file_importer.import_file(mp3_file, music_dir, manager) track2 = file_importer.import_file(mp3_file, music_dir, manager) assert track1.track_id == track2.track_id assert len(manager.library.tracks) == 1 def test_name_collision_gets_suffix(self, manager, mp3_file, tmp_path): music_dir = tmp_path / "music" dest = music_dir / "Unknown Artist" / "Unknown Album" / "test.mp3" dest.parent.mkdir(parents=True) dest.write_bytes(b"placeholder different file") track = file_importer.import_file(mp3_file, music_dir, manager) assert Path(track.location) == dest.with_stem("test 1") def test_rejects_non_audio(self, manager, tmp_path): text = tmp_path / "notes.txt" text.write_text("hello") assert file_importer.import_file(text, tmp_path / "music", manager) is None def test_import_paths_adds_to_playlist(self, manager, mp3_file, tmp_path): playlist = manager.create_playlist("Drops") imported = file_importer.import_paths( [mp3_file], tmp_path / "music", manager, playlist.persistent_id) assert len(imported) == 1 assert playlist.track_ids == [imported[0].track_id] class TestLibraryManager: def test_playlist_crud_and_persistence(self, manager): folder = manager.create_folder("F") playlist = manager.create_playlist("P", folder.persistent_id) manager.rename_playlist(playlist.persistent_id, "P2") assert manager.library.playlists[playlist.persistent_id].name == "P2" manager.flush() path = manager.data_dir / "playlists" / f"{playlist.persistent_id}.json" assert path.exists() manager.delete_playlist(folder.persistent_id) # recursive assert manager.library.playlists == {} manager.flush() assert not path.exists() def test_move_tracks_in_playlist(self, manager): from lintunes.models import Track for i in range(1, 6): manager.add_track(Track(track_id=i, name=f"t{i}")) playlist = manager.create_playlist("P") manager.add_tracks_to_playlist(playlist.persistent_id, [1, 2, 3, 4, 5]) # Move rows 0,1 (tracks 1,2) so the block starts at manual row 4 manager.move_tracks_in_playlist(playlist.persistent_id, [0, 1], 4) assert playlist.track_ids == [3, 4, 1, 2, 5] # Move last row (track 5) to the top manager.move_tracks_in_playlist(playlist.persistent_id, [4], 0) assert playlist.track_ids == [5, 3, 4, 1, 2] def test_record_play(self, manager): from lintunes.models import Track manager.add_track(Track(track_id=7, name="x", play_count=3)) manager.record_play(7) track = manager.library.tracks[7] assert track.play_count == 4 assert track.play_date_utc is not None