test_views.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. from datetime import datetime, timedelta
  2. from unittest.mock import patch
  3. from django.utils import timezone
  4. import pytest
  5. import time_machine
  6. from django.urls import reverse
  7. from music.models import Track
  8. from podcasts.models import PodcastEpisode
  9. from scrobbles.models import Scrobble
  10. @pytest.mark.django_db
  11. def test_get_not_allowed_from_mopidy(client, valid_auth_token):
  12. url = reverse("scrobbles:mopidy-webhook")
  13. headers = {"Authorization": f"Token {valid_auth_token}"}
  14. response = client.get(url, headers=headers)
  15. assert response.status_code == 405
  16. @pytest.mark.django_db
  17. def test_bad_mopidy_request_data(client, valid_auth_token):
  18. url = reverse("scrobbles:mopidy-webhook")
  19. headers = {"Authorization": f"Token {valid_auth_token}"}
  20. response = client.post(url, headers)
  21. assert response.status_code == 400
  22. assert (
  23. response.data["detail"]
  24. == "JSON parse error - Expecting value: line 1 column 1 (char 0)"
  25. )
  26. @pytest.mark.skip("Need to refactor")
  27. @pytest.mark.django_db
  28. @patch("music.utils.lookup_artist_from_mb", return_value={})
  29. @patch(
  30. "music.utils.lookup_album_dict_from_mb",
  31. return_value={"year": "1999", "mb_group_id": 1},
  32. )
  33. @patch("music.utils.lookup_track_from_mb", return_value={})
  34. @patch("music.models.lookup_artist_from_tadb", return_value={})
  35. @patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
  36. @patch("music.models.Album.fetch_artwork", return_value=None)
  37. @patch("music.models.Album.scrape_allmusic", return_value=None)
  38. def test_scrobble_mopidy_same_track_different_album(
  39. mock_lookup_artist,
  40. mock_lookup_album,
  41. mock_lookup_track,
  42. mock_lookup_artist_tadb,
  43. mock_lookup_album_tadb,
  44. mock_fetch_artwork,
  45. mock_scrape_allmusic,
  46. client,
  47. mopidy_track,
  48. mopidy_track_diff_album_request_data,
  49. valid_auth_token,
  50. ):
  51. url = reverse("scrobbles:mopidy-webhook")
  52. headers = {"Authorization": f"Token {valid_auth_token}"}
  53. response = client.post(
  54. url,
  55. mopidy_track.request_data,
  56. content_type="application/json",
  57. headers=headers,
  58. )
  59. assert response.status_code == 200
  60. assert response.data == {"scrobble_id": 1}
  61. scrobble = Scrobble.objects.last()
  62. assert scrobble.media_obj.album.name == "Sublime"
  63. response = client.post(
  64. url,
  65. mopidy_track_diff_album_request_data,
  66. content_type="application/json",
  67. )
  68. assert response.status_code == 200
  69. assert response.data == {"scrobble_id": 2}
  70. scrobble = Scrobble.objects.last()
  71. assert scrobble.media_obj.__class__ == Track
  72. assert scrobble.media_obj.album.name == "Sublime"
  73. assert scrobble.media_obj.title == "Same in the End"
  74. @pytest.mark.django_db
  75. @patch(
  76. "podcasts.sources.podcastindex.lookup_podcast_from_podcastindex",
  77. return_value={},
  78. )
  79. def test_scrobble_mopidy_podcast(
  80. mock_lookup_podcast, client, mopidy_podcast_request_data, valid_auth_token
  81. ):
  82. url = reverse("scrobbles:mopidy-webhook")
  83. headers = {"Authorization": f"Token {valid_auth_token}"}
  84. response = client.post(
  85. url,
  86. mopidy_podcast_request_data,
  87. content_type="application/json",
  88. headers=headers,
  89. )
  90. assert response.status_code == 200
  91. assert response.data == {"scrobble_id": 1}
  92. scrobble = Scrobble.objects.get(id=1)
  93. assert scrobble.media_obj.__class__ == PodcastEpisode
  94. assert scrobble.media_obj.title == "Up First"
  95. @pytest.mark.skip("Need to refactor")
  96. @pytest.mark.django_db
  97. @patch("music.utils.lookup_artist_from_mb", return_value={})
  98. @patch(
  99. "music.utils.lookup_album_dict_from_mb",
  100. return_value={"year": "1999", "mb_group_id": 1},
  101. )
  102. @patch("music.utils.lookup_track_from_mb", return_value={})
  103. @patch("music.models.lookup_artist_from_tadb", return_value={})
  104. @patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
  105. @patch("music.models.Album.fetch_artwork", return_value=None)
  106. @patch("music.models.Album.scrape_allmusic", return_value=None)
  107. def test_scrobble_jellyfin_track(
  108. mock_lookup_artist,
  109. mock_lookup_album,
  110. mock_lookup_track,
  111. mock_lookup_artist_tadb,
  112. mock_lookup_album_tadb,
  113. mock_fetch_artwork,
  114. mock_scrape_allmusic,
  115. client,
  116. jellyfin_track,
  117. valid_auth_token,
  118. ):
  119. url = reverse("scrobbles:jellyfin-webhook")
  120. headers = {"Authorization": f"Token {valid_auth_token}"}
  121. with time_machine.travel(datetime(2024, 1, 14, 12, 00, 1)):
  122. jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
  123. "%Y-%m-%d %H:%M:%S"
  124. )
  125. response = client.post(
  126. url,
  127. jellyfin_track.request_json,
  128. content_type="application/json",
  129. headers=headers,
  130. )
  131. assert response.status_code == 200
  132. assert response.data == {"scrobble_id": 1}
  133. scrobble = Scrobble.objects.get(id=1)
  134. assert scrobble.media_obj.__class__ == Track
  135. assert scrobble.media_obj.title == "Emotion"
  136. @pytest.mark.skip("Need to refactor")
  137. @pytest.mark.django_db
  138. @patch("music.utils.lookup_artist_from_mb", return_value={})
  139. @patch(
  140. "music.utils.lookup_album_dict_from_mb",
  141. return_value={"year": "1999", "mb_group_id": 1},
  142. )
  143. @patch("music.utils.lookup_track_from_mb", return_value={})
  144. @patch("music.models.lookup_artist_from_tadb", return_value={})
  145. @patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
  146. @patch("music.models.Album.fetch_artwork", return_value=None)
  147. @patch("music.models.Album.scrape_allmusic", return_value=None)
  148. def test_scrobble_jellyfin_track_update(
  149. mock_lookup_artist,
  150. mock_lookup_album,
  151. mock_lookup_track,
  152. mock_lookup_artist_tadb,
  153. mock_lookup_album_tadb,
  154. mock_fetch_artwork,
  155. mock_scrape_allmusic,
  156. test_track,
  157. client,
  158. jellyfin_track,
  159. valid_auth_token,
  160. ):
  161. Scrobble.objects.create(
  162. timestamp=timezone.now() - timedelta(minutes=0.5),
  163. track=Track.objects.first(),
  164. user_id=1,
  165. )
  166. url = reverse("scrobbles:jellyfin-webhook")
  167. headers = {"Authorization": f"Token {valid_auth_token}"}
  168. jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
  169. "%Y-%m-%d %H:%M:%S"
  170. )
  171. response = client.post(
  172. url,
  173. jellyfin_track.request_json,
  174. content_type="application/json",
  175. headers=headers,
  176. )
  177. assert response.status_code == 200
  178. assert response.data == {"scrobble_id": 1}
  179. scrobble = Scrobble.objects.get(id=1)
  180. assert scrobble.media_obj.__class__ == Track
  181. assert scrobble.media_obj.title == "Emotion"
  182. @pytest.mark.skip("Need to refactor")
  183. @pytest.mark.django_db
  184. @patch("music.utils.lookup_artist_from_mb", return_value={})
  185. @patch(
  186. "music.utils.lookup_album_dict_from_mb",
  187. return_value={"year": "1999", "mb_group_id": 1},
  188. )
  189. @patch("music.utils.lookup_track_from_mb", return_value={})
  190. @patch("music.models.lookup_artist_from_tadb", return_value={})
  191. @patch("music.models.lookup_album_from_tadb", return_value={"year": "1999"})
  192. @patch("music.models.Album.fetch_artwork", return_value=None)
  193. @patch("music.models.Album.scrape_allmusic", return_value=None)
  194. def test_scrobble_jellyfin_track_create_new(
  195. mock_lookup_artist,
  196. mock_lookup_album,
  197. mock_lookup_track,
  198. mock_lookup_artist_tadb,
  199. mock_lookup_album_tadb,
  200. mock_fetch_artwork,
  201. mock_scrape_allmusic,
  202. test_track,
  203. client,
  204. jellyfin_track,
  205. valid_auth_token,
  206. ):
  207. url = reverse("scrobbles:jellyfin-webhook")
  208. headers = {"Authorization": f"Token {valid_auth_token}"}
  209. Scrobble.objects.create(
  210. timestamp=timezone.now() - timedelta(minutes=1),
  211. track=Track.objects.first(),
  212. user_id=1,
  213. )
  214. jellyfin_track.request_data["UtcTimestamp"] = timezone.now().strftime(
  215. "%Y-%m-%d %H:%M:%S"
  216. )
  217. response = client.post(
  218. url,
  219. jellyfin_track.request_json,
  220. content_type="application/json",
  221. headers=headers,
  222. )
  223. assert response.status_code == 200
  224. assert response.data == {"scrobble_id": 2}
  225. scrobble = Scrobble.objects.get(id=1)
  226. assert scrobble.media_obj.__class__ == Track
  227. assert scrobble.media_obj.title == "Emotion"