[charts] Clean up, add tests and signals
All checks were successful
build & deploy / test (push) Successful in 1m43s
build & deploy / deploy (push) Successful in 21s

This commit is contained in:
2026-03-23 11:58:05 -04:00
parent d9a7a1cfd9
commit 881450eb8d
5 changed files with 365 additions and 7 deletions

View File

@ -0,0 +1,268 @@
import datetime
import pytest
from django.contrib.auth import get_user_model
from django.utils import timezone
from charts.models import ChartRecord
from charts.utils import build_charts
User = get_user_model()
@pytest.fixture
def user(db):
return User.objects.create_user(username="charttester", password="testpass123")
@pytest.fixture
def scrobble_data(user, db):
from scrobbles.models import Scrobble
from music.models import Track, Artist, Album
artist = Artist.objects.create(name="Test Artist")
album = Album.objects.create(name="Test Album", album_artist=artist)
track = Track.objects.create(title="Test Track", artist=artist, album=album)
return {
"user": user,
"track": track,
}
@pytest.mark.django_db
def test_build_daily_charts_creates_daily_record(user, scrobble_data):
from scrobbles.models import Scrobble
Scrobble.objects.create(
user=user,
track=scrobble_data["track"],
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
build_charts(user, year=2024, month=3, day=15)
daily = ChartRecord.objects.filter(
user=user,
year=2024,
month=3,
day=15,
week__isnull=True,
track__isnull=False,
)
assert daily.exists()
assert daily.first().track == scrobble_data["track"]
@pytest.mark.django_db
def test_build_monthly_charts_creates_monthly_record(user, scrobble_data):
from scrobbles.models import Scrobble
Scrobble.objects.create(
user=user,
track=scrobble_data["track"],
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
build_charts(user, year=2024, month=3)
monthly = ChartRecord.objects.filter(
user=user,
year=2024,
month=3,
week__isnull=True,
day__isnull=True,
track__isnull=False,
)
assert monthly.exists()
assert monthly.first().track == scrobble_data["track"]
@pytest.mark.django_db
def test_build_weekly_charts_creates_weekly_record(user, scrobble_data):
from scrobbles.models import Scrobble
Scrobble.objects.create(
user=user,
track=scrobble_data["track"],
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
build_charts(user, year=2024, week=11)
weekly = ChartRecord.objects.filter(
user=user,
year=2024,
week=11,
month__isnull=True,
day__isnull=True,
track__isnull=False,
)
assert weekly.exists()
assert weekly.first().track == scrobble_data["track"]
@pytest.mark.django_db
def test_build_yearly_charts_creates_yearly_record(user, scrobble_data):
from scrobbles.models import Scrobble
Scrobble.objects.create(
user=user,
track=scrobble_data["track"],
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
build_charts(user, year=2024)
yearly = ChartRecord.objects.filter(
user=user,
year=2024,
month__isnull=True,
week__isnull=True,
day__isnull=True,
track__isnull=False,
)
assert yearly.exists()
assert yearly.first().track == scrobble_data["track"]
@pytest.mark.django_db
def test_build_charts_ranks_by_count(user, scrobble_data):
from scrobbles.models import Scrobble
from music.models import Track, Artist
track1 = scrobble_data["track"]
track2 = Track.objects.create(
title="Test Track 2",
artist=track1.artist,
album=track1.album,
)
Scrobble.objects.create(
user=user,
track=track1,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
Scrobble.objects.create(
user=user,
track=track1,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 11, 0)),
)
Scrobble.objects.create(
user=user,
track=track2,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 12, 0)),
)
build_charts(user, year=2024, month=3, day=15)
daily = ChartRecord.objects.filter(
user=user,
year=2024,
month=3,
day=15,
track__isnull=False,
).order_by("rank")
assert daily.count() == 2
assert daily[0].track == track1
assert daily[0].rank == 1
assert daily[0].count == 2
assert daily[1].track == track2
assert daily[1].rank == 2
assert daily[1].count == 1
@pytest.mark.django_db
def test_build_daily_charts_deletes_existing_daily_record(user, scrobble_data):
from scrobbles.models import Scrobble
from music.models import Track, Artist
track1 = scrobble_data["track"]
track2 = Track.objects.create(
title="Test Track 2",
artist=track1.artist,
album=track1.album,
)
Scrobble.objects.create(
user=user,
track=track1,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
build_charts(user, year=2024, month=3, day=15)
assert ChartRecord.objects.filter(
user=user, year=2024, month=3, day=15, track=track1
).exists()
Scrobble.objects.create(
user=user,
track=track2,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 11, 0)),
)
build_charts(user, year=2024, month=3, day=15)
daily = ChartRecord.objects.filter(
user=user,
year=2024,
month=3,
day=15,
track__isnull=False,
)
assert daily.count() == 2
assert daily.filter(track=track1).exists()
assert daily.filter(track=track2).exists()
@pytest.mark.django_db
def test_build_monthly_charts_deletes_existing_monthly_record(user, scrobble_data):
from scrobbles.models import Scrobble
from music.models import Track, Artist
track1 = scrobble_data["track"]
track2 = Track.objects.create(
title="Test Track 2",
artist=track1.artist,
album=track1.album,
)
Scrobble.objects.create(
user=user,
track=track1,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 15, 10, 0)),
)
build_charts(user, year=2024, month=3)
ChartRecord.objects.filter(user=user, year=2024, month=3, track=track1).delete()
Scrobble.objects.create(
user=user,
track=track2,
played_to_completion=True,
timestamp=timezone.make_aware(datetime.datetime(2024, 3, 16, 11, 0)),
)
build_charts(user, year=2024, month=3)
monthly = ChartRecord.objects.filter(
user=user,
year=2024,
month=3,
week__isnull=True,
day__isnull=True,
track__isnull=False,
)
assert monthly.count() == 2

View File

@ -76,9 +76,9 @@ def build_charts(
]
period_filter = Q(year=year)
if day:
if day and month:
period_filter = (
period_filter & Q(day=day) & Q(week__isnull=True) & Q(month__isnull=True)
period_filter & Q(day=day) & Q(month=month) & Q(week__isnull=True)
)
elif week:
period_filter = (
@ -88,6 +88,13 @@ def build_charts(
period_filter = (
period_filter & Q(month=month) & Q(week__isnull=True) & Q(day__isnull=True)
)
else:
period_filter = (
period_filter
& Q(month__isnull=True)
& Q(week__isnull=True)
& Q(day__isnull=True)
)
ChartRecord.objects.filter(period_filter, user=user).delete()
@ -311,6 +318,7 @@ def build_daily_charts(
build_charts(
user=user,
year=year,
month=month,
day=day,
media_types=media_types,
)
@ -322,9 +330,7 @@ def build_charts_since(user, media_types: Optional[list] = None) -> None:
Scrobble = apps.get_model("scrobbles", "Scrobble")
latest_daily = (
ChartRecord.objects.filter(
user=user, day__isnull=False, month__isnull=True
)
ChartRecord.objects.filter(user=user, day__isnull=False)
.order_by("-year", "-month", "-day")
.first()
)