146 lines
5.1 KiB
Python
146 lines
5.1 KiB
Python
import csv
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.management import call_command
|
|
from music.models import Album, Artist, Track
|
|
from scrobbles.models import Scrobble
|
|
|
|
|
|
def _write_fix_csv(path, track_ids):
|
|
with open(path, "w", newline="") as f:
|
|
writer = csv.writer(f)
|
|
writer.writerow(
|
|
[
|
|
"track_id",
|
|
"track_artist_name",
|
|
"track_album_name",
|
|
"raw_artist",
|
|
"raw_album",
|
|
"source",
|
|
"mismatch",
|
|
]
|
|
)
|
|
for track_id in track_ids:
|
|
writer.writerow([track_id, "", "", "", "", "", ""])
|
|
|
|
|
|
def _scrobble(user, track, raw_data):
|
|
return Scrobble.objects.create(
|
|
track=track,
|
|
media_type="Track",
|
|
user=user,
|
|
log={"raw_data": raw_data},
|
|
)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_report_writes_mismatch_csv(tmp_path):
|
|
user = get_user_model().objects.create(email="report@example.com")
|
|
wrong = Artist.objects.create(name="Wrong Artist")
|
|
track = Track.objects.create(title="Song", artist_fk=wrong)
|
|
track.artists.add(wrong)
|
|
_scrobble(user, track, {"artist": "Right Artist", "musicbrainz_artist_id": "mb-1"})
|
|
|
|
out = tmp_path / "report.csv"
|
|
call_command("report_mismatched_metadata", file_path=str(out))
|
|
|
|
with open(out) as f:
|
|
rows = list(csv.DictReader(f))
|
|
assert len(rows) == 1
|
|
assert rows[0]["track_id"] == str(track.id)
|
|
assert "artist" in rows[0]["mismatch"]
|
|
assert rows[0]["raw_artist"] == "Right Artist"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_fix_file_commits_resolved_artists(tmp_path):
|
|
user = get_user_model().objects.create(email="fix@example.com")
|
|
wrong = Artist.objects.create(name="Wrong Artist")
|
|
right = Artist.objects.create(name="Right Artist")
|
|
track = Track.objects.create(title="Song", artist_fk=wrong)
|
|
track.artists.add(wrong)
|
|
_scrobble(user, track, {"artist": "Right Artist", "musicbrainz_artist_id": "mb-1"})
|
|
|
|
fix = tmp_path / "fix.csv"
|
|
_write_fix_csv(fix, [track.id])
|
|
call_command("report_mismatched_metadata", fix_file=str(fix), commit=True)
|
|
|
|
track.refresh_from_db()
|
|
assert list(track.artists.all().values_list("name", flat=True)) == ["Right Artist"]
|
|
assert track.artist_fk.name == "Right Artist"
|
|
assert "metadata-fixed" in track.tags.names()
|
|
assert not Artist.objects.filter(name="Wrong Artist").exists()
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_fix_file_dry_run_makes_no_changes(tmp_path):
|
|
user = get_user_model().objects.create(email="dry-fix@example.com")
|
|
wrong = Artist.objects.create(name="Wrong Artist")
|
|
right = Artist.objects.create(name="Right Artist")
|
|
track = Track.objects.create(title="Song", artist_fk=wrong)
|
|
track.artists.add(wrong)
|
|
_scrobble(user, track, {"artist": "Right Artist", "musicbrainz_artist_id": "mb-1"})
|
|
|
|
fix = tmp_path / "fix.csv"
|
|
_write_fix_csv(fix, [track.id])
|
|
call_command("report_mismatched_metadata", fix_file=str(fix))
|
|
|
|
track.refresh_from_db()
|
|
assert sorted(track.artists.all().values_list("name", flat=True)) == [
|
|
"Wrong Artist"
|
|
]
|
|
assert not track.tags.filter(name="metadata-fixed").exists()
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_fix_file_only_touches_listed_tracks(tmp_path):
|
|
user = get_user_model().objects.create(email="subset@example.com")
|
|
wrong = Artist.objects.create(name="Wrong Artist")
|
|
keep = Artist.objects.create(name="Keep Artist")
|
|
track_a = Track.objects.create(title="Song A", artist_fk=wrong)
|
|
track_a.artists.add(wrong)
|
|
track_b = Track.objects.create(title="Song B", artist_fk=wrong)
|
|
track_b.artists.add(wrong)
|
|
_scrobble(
|
|
user, track_a, {"artist": "Right Artist", "musicbrainz_artist_id": "mb-1"}
|
|
)
|
|
_scrobble(
|
|
user, track_b, {"artist": "Right Artist", "musicbrainz_artist_id": "mb-1"}
|
|
)
|
|
|
|
fix = tmp_path / "fix.csv"
|
|
_write_fix_csv(fix, [track_a.id])
|
|
call_command("report_mismatched_metadata", fix_file=str(fix), commit=True)
|
|
|
|
track_a.refresh_from_db()
|
|
track_b.refresh_from_db()
|
|
assert list(track_a.artists.all().values_list("name", flat=True)) == [
|
|
"Right Artist"
|
|
]
|
|
assert sorted(track_b.artists.all().values_list("name", flat=True)) == [
|
|
"Wrong Artist"
|
|
]
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Album.find_or_create")
|
|
def test_fix_file_fixes_album(mock_album, tmp_path):
|
|
user = get_user_model().objects.create(email="album@example.com")
|
|
artist = Artist.objects.create(name="Right Artist")
|
|
old_album = Album.objects.create(name="Old Album", album_artist=artist)
|
|
new_album = Album.objects.create(name="New Album", album_artist=artist)
|
|
mock_album.return_value = new_album
|
|
track = Track.objects.create(title="Song", artist_fk=artist, album=old_album)
|
|
track.artists.add(artist)
|
|
_scrobble(user, track, {"Artist": "Right Artist", "Album": "New Album"})
|
|
|
|
fix = tmp_path / "fix.csv"
|
|
_write_fix_csv(fix, [track.id])
|
|
call_command("report_mismatched_metadata", fix_file=str(fix), commit=True)
|
|
|
|
track.refresh_from_db()
|
|
assert track.album == new_album
|
|
mock_album.assert_called_once_with("New Album", "Right Artist")
|