[release] Bump to version 66.0
- Do a deep dive on making homepage clearer and more efficient
This commit is contained in:
195
tests/scrobbles_tests/test_home.py
Normal file
195
tests/scrobbles_tests/test_home.py
Normal file
@ -0,0 +1,195 @@
|
||||
import pytest
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.cache import cache
|
||||
from django.core.cache.utils import make_template_fragment_key
|
||||
from django.db import connection
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from django.utils import timezone
|
||||
from music.models import Artist, Track
|
||||
from scrobbles.models import Scrobble
|
||||
from tasks.models import Task
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def clear_cache():
|
||||
cache.clear()
|
||||
yield
|
||||
cache.clear()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_home_renders_summary_and_timeline(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="homeuser", password="testpass"
|
||||
)
|
||||
artist = Artist.objects.create(name="Sublime")
|
||||
track = Track.objects.create(title="Same in the End", artist_fk=artist)
|
||||
task = Task.objects.create(title="Ship the thing")
|
||||
now = timezone.now()
|
||||
Scrobble.objects.create(
|
||||
user=user,
|
||||
track=track,
|
||||
media_type="Track",
|
||||
timestamp=now,
|
||||
played_to_completion=True,
|
||||
)
|
||||
Scrobble.objects.create(
|
||||
user=user,
|
||||
task=task,
|
||||
media_type="Task",
|
||||
timestamp=now - timezone.timedelta(minutes=10),
|
||||
)
|
||||
client.force_login(user)
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
content = response.content.decode()
|
||||
assert "Same in the End" in content
|
||||
assert "Ship the thing" in content
|
||||
assert "Track" in content
|
||||
assert "Task" in content
|
||||
assert "Timeline" in content
|
||||
assert "Details" in content
|
||||
assert "Browse" in content
|
||||
assert "media-browser-menu" in content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_home_does_not_render_empty_types(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="homeuser2", password="testpass"
|
||||
)
|
||||
task = Task.objects.create(title="Only task")
|
||||
now = timezone.now()
|
||||
Scrobble.objects.create(user=user, task=task, media_type="Task", timestamp=now)
|
||||
client.force_login(user)
|
||||
response = client.get("/")
|
||||
content = response.content.decode()
|
||||
assert "Only task" in content
|
||||
assert "No tracks today" not in content
|
||||
assert "No food today" not in content
|
||||
assert "No videos today" not in content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_home_type_section_cached_skips_query(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="homecache", password="testpass"
|
||||
)
|
||||
task = Task.objects.create(title="Cached task")
|
||||
now = timezone.now()
|
||||
Scrobble.objects.create(user=user, task=task, media_type="Task", timestamp=now)
|
||||
client.force_login(user)
|
||||
|
||||
# First request renders everything (cache cold)
|
||||
with CaptureQueriesContext(connection) as cold:
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "Cached task" in response.content.decode()
|
||||
|
||||
# Second request should serve the type-section fragment from cache and
|
||||
# skip its DB query entirely
|
||||
with CaptureQueriesContext(connection) as warm:
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "Cached task" in response.content.decode()
|
||||
assert len(warm) < len(cold)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_scrobble_save_invalidates_home_fragments(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="invalidate", password="testpass"
|
||||
)
|
||||
task = Task.objects.create(title="First")
|
||||
now = timezone.now()
|
||||
scrobble = Scrobble.objects.create(
|
||||
user=user, task=task, media_type="Task", timestamp=now
|
||||
)
|
||||
timeline_key = make_template_fragment_key(
|
||||
"home_timeline", [user.id, now.strftime("%Y-%m-%d")]
|
||||
)
|
||||
type_key = make_template_fragment_key(
|
||||
"home_type_section", [user.id, now.strftime("%Y-%m-%d"), "Task"]
|
||||
)
|
||||
cache.set(timeline_key, "cached")
|
||||
cache.set(type_key, "cached")
|
||||
assert cache.get(timeline_key) == "cached"
|
||||
assert cache.get(type_key) == "cached"
|
||||
|
||||
Scrobble.objects.create(
|
||||
user=user,
|
||||
task=Task.objects.create(title="Second"),
|
||||
media_type="Task",
|
||||
timestamp=timezone.now(),
|
||||
)
|
||||
assert cache.get(timeline_key) is None
|
||||
assert cache.get(type_key) is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_scrobble_delete_invalidates_home_fragments(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="invalidedel", password="testpass"
|
||||
)
|
||||
task = Task.objects.create(title="Doomed")
|
||||
now = timezone.now()
|
||||
scrobble = Scrobble.objects.create(
|
||||
user=user, task=task, media_type="Task", timestamp=now
|
||||
)
|
||||
timeline_key = make_template_fragment_key(
|
||||
"home_timeline", [user.id, now.strftime("%Y-%m-%d")]
|
||||
)
|
||||
cache.set(timeline_key, "cached")
|
||||
assert cache.get(timeline_key) == "cached"
|
||||
|
||||
scrobble.delete()
|
||||
assert cache.get(timeline_key) is None
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_home_week_view_uses_grouped_tables(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="homeweek", password="testpass"
|
||||
)
|
||||
task = Task.objects.create(title="Week task")
|
||||
now = timezone.now()
|
||||
Scrobble.objects.create(user=user, task=task, media_type="Task", timestamp=now)
|
||||
client.force_login(user)
|
||||
response = client.get("/", {"date": "this_week"})
|
||||
assert response.status_code == 200
|
||||
content = response.content.decode()
|
||||
assert "Week task" in content
|
||||
assert "Timeline" not in content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_home_media_badges_colored_initials_by_default(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="badgeinit", password="testpass"
|
||||
)
|
||||
task = Task.objects.create(title="Badge task")
|
||||
Scrobble.objects.create(
|
||||
user=user, task=task, media_type="Task", timestamp=timezone.now()
|
||||
)
|
||||
client.force_login(user)
|
||||
content = client.get("/").content.decode()
|
||||
assert 'class="badge media-badge' in content
|
||||
assert ">T</span>" in content
|
||||
assert "\u2705" not in content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_home_media_badges_use_emojis_when_enabled(client):
|
||||
user = get_user_model().objects.create_user(
|
||||
username="badgeemoji", password="testpass"
|
||||
)
|
||||
user.profile.timeline_use_emojis = True
|
||||
user.profile.save()
|
||||
task = Task.objects.create(title="Emoji task")
|
||||
Scrobble.objects.create(
|
||||
user=user, task=task, media_type="Task", timestamp=timezone.now()
|
||||
)
|
||||
client.force_login(user)
|
||||
content = client.get("/").content.decode()
|
||||
assert "\u2705" in content
|
||||
assert ">T</span>" not in content
|
||||
Reference in New Issue
Block a user