742 lines
23 KiB
Python
742 lines
23 KiB
Python
from datetime import datetime, timedelta
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
import time_machine
|
|
from django.contrib.auth import get_user_model
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from music.models import Album, Artist, Track
|
|
from podcasts.models import PodcastEpisode
|
|
from scrobbles.models import Scrobble
|
|
from tasks.models import Task
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_get_not_allowed_from_mopidy(client, valid_auth_token):
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.get(url, headers=headers)
|
|
assert response.status_code == 405
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_get_not_allowed_from_jellyfin(client, valid_auth_token):
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.get(url, headers=headers)
|
|
assert response.status_code == 405
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_bad_mopidy_request_data(client, valid_auth_token):
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url, "not valid json", content_type="application/json", headers=headers
|
|
)
|
|
assert response.status_code == 400
|
|
assert (
|
|
response.data["detail"]
|
|
== "JSON parse error - Expecting value: line 1 column 1 (char 0)"
|
|
)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_bad_jellyfin_request_data(client, valid_auth_token):
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url, "not valid json", content_type="application/json", headers=headers
|
|
)
|
|
assert response.status_code == 400
|
|
assert (
|
|
response.data["detail"]
|
|
== "JSON parse error - Expecting value: line 1 column 1 (char 0)"
|
|
)
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_create_scrobble_from_mopidy_track_webhook(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
mopidy_track,
|
|
):
|
|
mock_artist = MagicMock(spec=Artist)
|
|
mock_artist.id = 1
|
|
mock_artist_fc.return_value = mock_artist
|
|
|
|
mock_track = MagicMock(spec=Track)
|
|
mock_track.id = 1
|
|
mock_track.scrobble_for_user.return_value = Scrobble(
|
|
id=1, track_id=1, user_id=1, in_progress=True
|
|
)
|
|
mock_track_fc.return_value = mock_track
|
|
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url,
|
|
mopidy_track.request_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
mock_track.scrobble_for_user.assert_called_once()
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_create_scrobble_from_jellyfin_track_webhook(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
jellyfin_track,
|
|
):
|
|
mock_artist = MagicMock(spec=Artist)
|
|
mock_artist.id = 1
|
|
mock_artist_fc.return_value = mock_artist
|
|
|
|
mock_track = MagicMock(spec=Track)
|
|
mock_track.id = 1
|
|
mock_track.scrobble_for_user.return_value = Scrobble(
|
|
id=1, track_id=1, user_id=1, in_progress=True
|
|
)
|
|
mock_track_fc.return_value = mock_track
|
|
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
|
|
with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
mock_track.scrobble_for_user.assert_called_once()
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_mopidy_track_webhook_creates_track_and_scrobble(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
mopidy_track,
|
|
):
|
|
artist = Artist.objects.create(name="Sublime")
|
|
album = Album.objects.create(name="Sublime", album_artist=artist)
|
|
track = Track.objects.create(
|
|
title="Same in the End",
|
|
artist_fk=artist,
|
|
base_run_time_seconds=60,
|
|
)
|
|
track.artists.add(artist)
|
|
track.albums.add(album)
|
|
|
|
mock_artist_fc.return_value = artist
|
|
mock_track_fc.return_value = track
|
|
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url,
|
|
mopidy_track.request_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.track == track
|
|
assert scrobble.source == "Mopidy"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_jellyfin_track_webhook_creates_track_and_scrobble(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
jellyfin_track,
|
|
):
|
|
artist = Artist.objects.create(name="Carly Rae Jepsen")
|
|
album = Album.objects.create(name="Emotion", album_artist=artist)
|
|
track = Track.objects.create(
|
|
title="Emotion",
|
|
artist_fk=artist,
|
|
base_run_time_seconds=60,
|
|
)
|
|
track.artists.add(artist)
|
|
track.albums.add(album)
|
|
|
|
mock_artist_fc.return_value = artist
|
|
mock_track_fc.return_value = track
|
|
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
|
|
with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.track == track
|
|
assert scrobble.source == "Jellyfin"
|
|
assert "raw_data" in scrobble.log
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_mopidy_track_webhook_stores_raw_data(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
mopidy_track,
|
|
):
|
|
artist = Artist.objects.create(name="Sublime")
|
|
album = Album.objects.create(name="Sublime", album_artist=artist)
|
|
track = Track.objects.create(
|
|
title="Same in the End",
|
|
artist_fk=artist,
|
|
base_run_time_seconds=60,
|
|
)
|
|
track.artists.add(artist)
|
|
track.albums.add(album)
|
|
|
|
mock_artist_fc.return_value = artist
|
|
mock_track_fc.return_value = track
|
|
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url,
|
|
mopidy_track.request_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.track == track
|
|
assert scrobble.source == "Mopidy"
|
|
assert "raw_data" in scrobble.log
|
|
assert scrobble.log["raw_data"]["name"] == "Same in the End"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_mopidy_track_webhook_stores_album_id(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
mopidy_track,
|
|
):
|
|
artist = Artist.objects.create(name="Sublime")
|
|
album = Album.objects.create(name="Sublime", album_artist=artist)
|
|
track = Track.objects.create(
|
|
title="Same in the End",
|
|
artist_fk=artist,
|
|
album=album,
|
|
base_run_time_seconds=60,
|
|
)
|
|
track.artists.add(artist)
|
|
|
|
mock_artist_fc.return_value = artist
|
|
mock_track_fc.return_value = track
|
|
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url,
|
|
mopidy_track.request_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert "album_id" in scrobble.log
|
|
assert scrobble.log["album_id"] == album.id
|
|
assert "album" not in scrobble.log
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_jellyfin_track_webhook_stores_raw_data(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
jellyfin_track,
|
|
):
|
|
artist = Artist.objects.create(name="Carly Rae Jepsen")
|
|
album = Album.objects.create(name="Emotion", album_artist=artist)
|
|
track = Track.objects.create(
|
|
title="Emotion",
|
|
artist_fk=artist,
|
|
base_run_time_seconds=60,
|
|
)
|
|
track.artists.add(artist)
|
|
track.albums.add(album)
|
|
|
|
mock_artist_fc.return_value = artist
|
|
mock_track_fc.return_value = track
|
|
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
|
|
with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.track == track
|
|
assert scrobble.source == "Jellyfin"
|
|
assert "raw_data" in scrobble.log
|
|
assert scrobble.log["raw_data"]["Name"] == "Emotion"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch("music.models.Artist.find_or_create")
|
|
@patch("music.models.Track.find_or_create")
|
|
def test_jellyfin_track_webhook_stores_album_id(
|
|
mock_track_fc,
|
|
mock_artist_fc,
|
|
client,
|
|
valid_auth_token,
|
|
jellyfin_track,
|
|
):
|
|
artist = Artist.objects.create(name="Carly Rae Jepsen")
|
|
album = Album.objects.create(name="Emotion", album_artist=artist)
|
|
track = Track.objects.create(
|
|
title="Emotion",
|
|
artist_fk=artist,
|
|
album=album,
|
|
base_run_time_seconds=60,
|
|
)
|
|
track.artists.add(artist)
|
|
|
|
mock_artist_fc.return_value = artist
|
|
mock_track_fc.return_value = track
|
|
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
|
|
with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert "album_id" in scrobble.log
|
|
assert scrobble.log["album_id"] == album.id
|
|
|
|
|
|
@pytest.mark.skip("Need to refactor")
|
|
@pytest.mark.django_db
|
|
@patch("music.utils.lookup_artist_from_mb", return_value={})
|
|
@patch(
|
|
"music.utils.lookup_album_dict_from_mb",
|
|
return_value={"year": "1999", "mb_group_id": 1},
|
|
)
|
|
@patch("music.utils.lookup_track_from_mb", return_value={})
|
|
@patch("music.models.lookup_artist_from_tadb", return_value={})
|
|
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
|
|
@patch("music.models.Album.fetch_artwork", return_value=None)
|
|
@patch("music.models.Album.scrape_allmusic", return_value=None)
|
|
def test_scrobble_mopidy_same_track_different_album(
|
|
mock_lookup_artist,
|
|
mock_lookup_album,
|
|
mock_lookup_track,
|
|
mock_lookup_artist_tadb,
|
|
mock_lookup_album_tadb,
|
|
mock_fetch_artwork,
|
|
mock_scrape_allmusic,
|
|
client,
|
|
mopidy_track,
|
|
mopidy_track_diff_album_request_data,
|
|
valid_auth_token,
|
|
):
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url,
|
|
mopidy_track.request_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
scrobble = Scrobble.objects.last()
|
|
assert scrobble.media_obj.album.name == "Sublime"
|
|
|
|
response = client.post(
|
|
url,
|
|
mopidy_track_diff_album_request_data,
|
|
content_type="application/json",
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 2}
|
|
scrobble = Scrobble.objects.last()
|
|
assert scrobble.media_obj.__class__ == Track
|
|
assert scrobble.media_obj.album.name == "Sublime"
|
|
assert scrobble.media_obj.title == "Same in the End"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
@patch(
|
|
"podcasts.sources.podcastindex.lookup_podcast_from_podcastindex",
|
|
return_value={},
|
|
)
|
|
def test_scrobble_mopidy_podcast(
|
|
mock_lookup_podcast, client, mopidy_podcast_request_data, valid_auth_token
|
|
):
|
|
url = reverse("scrobbles:mopidy-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.post(
|
|
url,
|
|
mopidy_podcast_request_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.media_obj.__class__ == PodcastEpisode
|
|
assert scrobble.media_obj.title == "Up First"
|
|
|
|
|
|
@pytest.mark.skip("Need to refactor")
|
|
@pytest.mark.django_db
|
|
@patch("music.utils.lookup_artist_from_mb", return_value={})
|
|
@patch(
|
|
"music.utils.lookup_album_dict_from_mb",
|
|
return_value={"year": "1999", "mb_group_id": 1},
|
|
)
|
|
@patch("music.utils.lookup_track_from_mb", return_value={})
|
|
@patch("music.models.lookup_artist_from_tadb", return_value={})
|
|
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
|
|
@patch("music.models.Album.fetch_artwork", return_value=None)
|
|
@patch("music.models.Album.scrape_allmusic", return_value=None)
|
|
def test_scrobble_jellyfin_track(
|
|
mock_lookup_artist,
|
|
mock_lookup_album,
|
|
mock_lookup_track,
|
|
mock_lookup_artist_tadb,
|
|
mock_lookup_album_tadb,
|
|
mock_fetch_artwork,
|
|
mock_scrape_allmusic,
|
|
client,
|
|
jellyfin_track,
|
|
valid_auth_token,
|
|
):
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
|
|
with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.media_obj.__class__ == Track
|
|
assert scrobble.media_obj.title == "Emotion"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_scrobble_detail_view_with_notes_as_flat_list(client):
|
|
user = get_user_model().objects.create_user(
|
|
username="testuser", email="test@example.com", password="testpass"
|
|
)
|
|
task = Task.objects.create(title="Test Task", description="Test description")
|
|
scrobble = Scrobble.objects.create(
|
|
task=task,
|
|
media_type="Task",
|
|
user=user,
|
|
log={
|
|
"notes": ["First note", "Second note"],
|
|
"description": "Test description",
|
|
},
|
|
)
|
|
url = reverse("scrobbles:detail", kwargs={"uuid": scrobble.uuid})
|
|
response = client.get(url)
|
|
assert response.status_code == 200
|
|
assert "First note" in response.content.decode()
|
|
assert "Second note" in response.content.decode()
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_scrobble_detail_view_with_notes_as_dict_timestamps(client):
|
|
user = get_user_model().objects.create_user(
|
|
username="testuser", email="test@example.com", password="testpass"
|
|
)
|
|
task = Task.objects.create(title="Test Task", description="Test description")
|
|
scrobble = Scrobble.objects.create(
|
|
task=task,
|
|
media_type="Task",
|
|
user=user,
|
|
log={
|
|
"notes": [
|
|
{"2024-01-01 10:00:00": "Note at first timestamp"},
|
|
{"2024-01-02 11:30:00": "Note at second timestamp"},
|
|
],
|
|
"description": "Test description",
|
|
},
|
|
)
|
|
url = reverse("scrobbles:detail", kwargs={"uuid": scrobble.uuid})
|
|
response = client.get(url)
|
|
assert response.status_code == 200
|
|
content = response.content.decode()
|
|
assert "2024-01-01 10:00:00" in content
|
|
assert "Note at first timestamp" in content
|
|
assert "2024-01-02 11:30:00" in content
|
|
assert "Note at second timestamp" in content
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_scrobble_detail_view_with_notes_and_labels(client):
|
|
user = get_user_model().objects.create_user(
|
|
username="testuser", email="test@example.com", password="testpass"
|
|
)
|
|
task = Task.objects.create(title="Test Task", description="Test description")
|
|
scrobble = Scrobble.objects.create(
|
|
task=task,
|
|
media_type="Task",
|
|
user=user,
|
|
log={
|
|
"notes": [
|
|
{"2024-01-01 10:00:00": "Note with label"},
|
|
],
|
|
"labels": ["work", "urgent"],
|
|
"description": "Test description",
|
|
},
|
|
)
|
|
url = reverse("scrobbles:detail", kwargs={"uuid": scrobble.uuid})
|
|
response = client.get(url)
|
|
assert response.status_code == 200
|
|
content = response.content.decode()
|
|
assert "work" in content
|
|
assert "urgent" in content
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_scrobble_detail_view_post_updates_log(client):
|
|
user = get_user_model().objects.create_user(
|
|
username="testuser", email="test@example.com", password="testpass"
|
|
)
|
|
task = Task.objects.create(title="Test Task", description="Test description")
|
|
scrobble = Scrobble.objects.create(
|
|
task=task,
|
|
media_type="Task",
|
|
user=user,
|
|
log={
|
|
"notes": ["Original note"],
|
|
"description": "Original description",
|
|
},
|
|
)
|
|
url = reverse("scrobbles:detail", kwargs={"uuid": scrobble.uuid})
|
|
|
|
client.force_login(user)
|
|
response = client.post(
|
|
url,
|
|
{
|
|
"description": "Updated description",
|
|
"notes": "Updated note",
|
|
},
|
|
)
|
|
assert response.status_code == 302
|
|
|
|
scrobble.refresh_from_db()
|
|
assert scrobble.log["description"] == "Updated description"
|
|
assert isinstance(scrobble.log["notes"], dict)
|
|
assert list(scrobble.log["notes"].values()) == ["Updated note"]
|
|
|
|
|
|
@pytest.mark.skip("Need to refactor")
|
|
@pytest.mark.django_db
|
|
@patch("music.utils.lookup_artist_from_mb", return_value={})
|
|
@patch(
|
|
"music.utils.lookup_album_dict_from_mb",
|
|
return_value={"year": "1999", "mb_group_id": 1},
|
|
)
|
|
@patch("music.utils.lookup_track_from_mb", return_value={})
|
|
@patch("music.models.lookup_artist_from_tadb", return_value={})
|
|
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
|
|
@patch("music.models.Album.fetch_artwork", return_value=None)
|
|
@patch("music.models.Album.scrape_allmusic", return_value=None)
|
|
def test_scrobble_jellyfin_track_update(
|
|
mock_lookup_artist,
|
|
mock_lookup_album,
|
|
mock_lookup_track,
|
|
mock_lookup_artist_tadb,
|
|
mock_lookup_album_tadb,
|
|
mock_fetch_artwork,
|
|
mock_scrape_allmusic,
|
|
test_track,
|
|
client,
|
|
jellyfin_track,
|
|
valid_auth_token,
|
|
):
|
|
Scrobble.objects.create(
|
|
timestamp=timezone.now() - timedelta(minutes=0.5),
|
|
track=Track.objects.first(),
|
|
user_id=1,
|
|
)
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 1}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.media_obj.__class__ == Track
|
|
assert scrobble.media_obj.title == "Emotion"
|
|
|
|
|
|
@pytest.mark.skip("Need to refactor")
|
|
@pytest.mark.django_db
|
|
@patch("music.utils.lookup_artist_from_mb", return_value={})
|
|
@patch(
|
|
"music.utils.lookup_album_dict_from_mb",
|
|
return_value={"year": "1999", "mb_group_id": 1},
|
|
)
|
|
@patch("music.utils.lookup_track_from_mb", return_value={})
|
|
@patch("music.models.lookup_artist_from_tadb", return_value={})
|
|
@patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
|
|
@patch("music.models.Album.fetch_artwork", return_value=None)
|
|
@patch("music.models.Album.scrape_allmusic", return_value=None)
|
|
def test_scrobble_jellyfin_track_create_new(
|
|
mock_lookup_artist,
|
|
mock_lookup_album,
|
|
mock_lookup_track,
|
|
mock_lookup_artist_tadb,
|
|
mock_lookup_album_tadb,
|
|
mock_fetch_artwork,
|
|
mock_scrape_allmusic,
|
|
test_track,
|
|
client,
|
|
jellyfin_track,
|
|
valid_auth_token,
|
|
):
|
|
url = reverse("scrobbles:jellyfin-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
Scrobble.objects.create(
|
|
timestamp=timezone.now() - timedelta(minutes=1),
|
|
track=Track.objects.first(),
|
|
user_id=1,
|
|
)
|
|
jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
|
|
"%Y-%m-%d %H:%M:%S"
|
|
)
|
|
response = client.post(
|
|
url,
|
|
jellyfin_track.request_json,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.data == {"scrobble_id": 2}
|
|
|
|
scrobble = Scrobble.objects.get(id=1)
|
|
assert scrobble.media_obj.__class__ == Track
|
|
assert scrobble.media_obj.title == "Emotion"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_get_not_allowed_from_gps(client, valid_auth_token):
|
|
url = reverse("scrobbles:gps-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
response = client.get(url, headers=headers)
|
|
assert response.status_code == 405
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_gps_webhook_creates_location(client, valid_auth_token):
|
|
url = reverse("scrobbles:gps-webhook")
|
|
headers = {"Authorization": f"Token {valid_auth_token}"}
|
|
gps_data = {
|
|
"lat": "40.7128",
|
|
"lon": "-74.0060",
|
|
"alt": "10.5",
|
|
"time": "2024-01-14T12:00:00Z",
|
|
"prov": "gps",
|
|
}
|
|
response = client.post(
|
|
url,
|
|
gps_data,
|
|
content_type="application/json",
|
|
headers=headers,
|
|
)
|
|
assert response.status_code == 200
|
|
assert "scrobble_id" in response.data
|