Add audit tooling for scrobbled tracks data quality (#89)

This commit is contained in:
Copilot
2026-02-17 11:24:45 +00:00
committed by GitHub
parent e76e340671
commit 2faddbf0c6
6 changed files with 916 additions and 0 deletions
@@ -414,6 +414,172 @@ defmodule MusicLibrary.ScrobbleActivityTest do
|> Enum.map(fn r -> r.track end)
end
describe "count_tracks_missing_artist_musicbrainz_id/0" do
test "returns zero when no tracks exist" do
count = ScrobbleActivity.count_tracks_missing_artist_musicbrainz_id()
assert count == 0
end
test "returns count of tracks with empty artist musicbrainz_id" do
track_fixture(%{artist_musicbrainz_id: ""})
track_fixture(%{artist_musicbrainz_id: ""})
track_fixture(%{artist_musicbrainz_id: "valid-id"})
count = ScrobbleActivity.count_tracks_missing_artist_musicbrainz_id()
assert count == 2
end
end
describe "count_tracks_missing_album_musicbrainz_id/0" do
test "returns zero when no tracks exist" do
count = ScrobbleActivity.count_tracks_missing_album_musicbrainz_id()
assert count == 0
end
test "returns count of tracks with empty album musicbrainz_id" do
track_fixture(%{album_musicbrainz_id: ""})
track_fixture(%{album_musicbrainz_id: ""})
track_fixture(%{album_musicbrainz_id: "valid-id"})
count = ScrobbleActivity.count_tracks_missing_album_musicbrainz_id()
assert count == 2
end
end
describe "get_artists_missing_musicbrainz_id/1" do
test "returns empty list when no tracks exist" do
result = ScrobbleActivity.get_artists_missing_musicbrainz_id()
assert result == []
end
test "returns artists grouped by name with track counts" do
track_fixture(%{artist_name: "Artist A", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist A", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist B", artist_musicbrainz_id: ""})
result = ScrobbleActivity.get_artists_missing_musicbrainz_id()
assert length(result) == 2
artist_a = Enum.find(result, fn r -> r.artist_name == "Artist A" end)
artist_b = Enum.find(result, fn r -> r.artist_name == "Artist B" end)
assert artist_a.track_count == 2
assert artist_b.track_count == 1
end
test "orders artists by track count descending" do
track_fixture(%{artist_name: "Artist A", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist B", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist B", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist B", artist_musicbrainz_id: ""})
result = ScrobbleActivity.get_artists_missing_musicbrainz_id()
assert length(result) == 2
assert List.first(result).artist_name == "Artist B"
assert List.first(result).track_count == 3
end
test "limits results when limit option provided" do
track_fixture(%{artist_name: "Artist A", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist B", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist C", artist_musicbrainz_id: ""})
result = ScrobbleActivity.get_artists_missing_musicbrainz_id(limit: 2)
assert length(result) == 2
end
test "excludes artists with valid musicbrainz_id" do
track_fixture(%{artist_name: "Artist A", artist_musicbrainz_id: ""})
track_fixture(%{artist_name: "Artist B", artist_musicbrainz_id: "valid-id"})
result = ScrobbleActivity.get_artists_missing_musicbrainz_id()
assert length(result) == 1
assert List.first(result).artist_name == "Artist A"
end
end
describe "get_albums_missing_musicbrainz_id/1" do
test "returns empty list when no tracks exist" do
result = ScrobbleActivity.get_albums_missing_musicbrainz_id()
assert result == []
end
test "returns albums grouped by title and artist with track counts" do
track_fixture(%{
album_title: "Album A",
artist_name: "Artist X",
album_musicbrainz_id: ""
})
track_fixture(%{
album_title: "Album A",
artist_name: "Artist X",
album_musicbrainz_id: ""
})
track_fixture(%{
album_title: "Album B",
artist_name: "Artist Y",
album_musicbrainz_id: ""
})
result = ScrobbleActivity.get_albums_missing_musicbrainz_id()
assert length(result) == 2
album_a = Enum.find(result, fn r -> r.album_title == "Album A" end)
album_b = Enum.find(result, fn r -> r.album_title == "Album B" end)
assert album_a.track_count == 2
assert album_a.artist_name == "Artist X"
assert album_b.track_count == 1
assert album_b.artist_name == "Artist Y"
end
test "orders albums by track count descending" do
track_fixture(%{album_title: "Album A", album_musicbrainz_id: ""})
track_fixture(%{album_title: "Album B", album_musicbrainz_id: ""})
track_fixture(%{album_title: "Album B", album_musicbrainz_id: ""})
track_fixture(%{album_title: "Album B", album_musicbrainz_id: ""})
result = ScrobbleActivity.get_albums_missing_musicbrainz_id()
assert length(result) == 2
assert List.first(result).album_title == "Album B"
assert List.first(result).track_count == 3
end
test "limits results when limit option provided" do
track_fixture(%{album_title: "Album A", album_musicbrainz_id: ""})
track_fixture(%{album_title: "Album B", album_musicbrainz_id: ""})
track_fixture(%{album_title: "Album C", album_musicbrainz_id: ""})
result = ScrobbleActivity.get_albums_missing_musicbrainz_id(limit: 2)
assert length(result) == 2
end
test "excludes albums with valid musicbrainz_id" do
track_fixture(%{album_title: "Album A", album_musicbrainz_id: ""})
track_fixture(%{album_title: "Album B", album_musicbrainz_id: "valid-id"})
result = ScrobbleActivity.get_albums_missing_musicbrainz_id()
assert length(result) == 1
assert List.first(result).album_title == "Album A"
end
end
defp list_tracks(params) do
ScrobbleActivity.list_tracks(params)
|> Enum.map(fn r -> r.track end)