Spaces:
Running
Running
| import pytest | |
| from animetix.models import MediaItem, TrackerConnection | |
| from django.contrib.auth.models import User | |
| from django.urls import reverse | |
| from rest_framework.test import APIClient | |
| def api_client(): | |
| return APIClient() | |
| def authenticated_client(db): | |
| client = APIClient() | |
| user = User.objects.create_user(username="testuser", password="password") | |
| client.force_authenticate(user=user) | |
| return client | |
| def test_tracker_list_empty(authenticated_client): | |
| url = reverse("api_tracker_connections") | |
| res = authenticated_client.get(url) | |
| assert res.status_code == 200 | |
| assert len(res.data) == 0 | |
| def test_tracker_link_and_list(authenticated_client): | |
| link_url = reverse("api_tracker_link") | |
| list_url = reverse("api_tracker_connections") | |
| # Link MAL | |
| res = authenticated_client.post( | |
| link_url, | |
| {"tracker": "myanimelist", "username": "mal_user", "token": "mal-token"}, | |
| format="json", | |
| ) | |
| assert res.status_code == 200 | |
| assert res.data["success"] is True | |
| # Link AniList | |
| res = authenticated_client.post( | |
| link_url, | |
| {"tracker": "anilist", "username": "anilist_user", "token": "anilist-token"}, | |
| format="json", | |
| ) | |
| assert res.status_code == 200 | |
| assert res.data["success"] is True | |
| # List connections | |
| res = authenticated_client.get(list_url) | |
| assert res.status_code == 200 | |
| assert len(res.data) == 2 | |
| trackers = {item["tracker"]: item["username"] for item in res.data} | |
| assert trackers["myanimelist"] == "mal_user" | |
| assert trackers["anilist"] == "anilist_user" | |
| def test_tracker_unlink(authenticated_client): | |
| link_url = reverse("api_tracker_link") | |
| unlink_url = reverse("api_tracker_unlink") | |
| list_url = reverse("api_tracker_connections") | |
| # Link MAL | |
| authenticated_client.post( | |
| link_url, | |
| {"tracker": "myanimelist", "username": "mal_user", "token": "mal-token"}, | |
| format="json", | |
| ) | |
| # Unlink MAL | |
| res = authenticated_client.post( | |
| unlink_url, {"tracker": "myanimelist"}, format="json" | |
| ) | |
| assert res.status_code == 200 | |
| assert res.data["success"] is True | |
| # List connections (should be empty) | |
| res = authenticated_client.get(list_url) | |
| assert len(res.data) == 0 | |
| def test_manga_chapter_sync(authenticated_client): | |
| # Created so the sync endpoint can resolve media_id "12345"; the row itself | |
| # is looked up by id, not via a local variable. | |
| MediaItem.objects.create( | |
| external_id="12345", | |
| media_type="Manga", | |
| title="Monster", | |
| metadata={"id": "12345", "idMal": 12345}, | |
| ) | |
| # Set up active connections with mock tokens that trigger simulated successes | |
| user = User.objects.get(username="testuser") | |
| TrackerConnection.objects.create( | |
| user=user, tracker="anilist", username="anilist_user", token="mock-token" | |
| ) | |
| TrackerConnection.objects.create( | |
| user=user, tracker="myanimelist", username="mal_user", token="mock-token" | |
| ) | |
| url = reverse( | |
| "api_manga_chapter_sync", kwargs={"media_id": "12345", "chapter_number": "10"} | |
| ) | |
| res = authenticated_client.post(url) | |
| assert res.status_code == 200 | |
| assert res.data["success"] is True | |
| assert res.data["results"]["anilist"]["success"] is True | |
| assert res.data["results"]["myanimelist"]["success"] is True | |
| def test_manga_chapter_sync_auto_transitions(authenticated_client): | |
| from animetix.models import FavoriteManga, MangaChapter | |
| manga = MediaItem.objects.create( | |
| external_id="sync_manga_1", | |
| media_type="Manga", | |
| title="Sync Manga", | |
| ) | |
| user = User.objects.get(username="testuser") | |
| # Create Favorite record | |
| fav = FavoriteManga.objects.create( | |
| user=user, manga=manga, status="plan_to_read", last_read_chapter=0.0 | |
| ) | |
| # Add chapters: 1.0, 2.0, 3.0 | |
| MangaChapter.objects.create(manga=manga, number=1.0) | |
| MangaChapter.objects.create(manga=manga, number=2.0) | |
| MangaChapter.objects.create(manga=manga, number=3.0) | |
| url = reverse( | |
| "api_manga_chapter_sync", | |
| kwargs={"media_id": "sync_manga_1", "chapter_number": "1.0"}, | |
| ) | |
| res = authenticated_client.post(url) | |
| assert res.status_code == 200 | |
| # Verify transition from plan_to_read -> reading (since chapters 2.0, 3.0 remain) | |
| fav.refresh_from_db() | |
| assert fav.last_read_chapter == 1.0 | |
| assert fav.status == "reading" | |
| # Now read chapter 3.0 (the last one) | |
| url_last = reverse( | |
| "api_manga_chapter_sync", | |
| kwargs={"media_id": "sync_manga_1", "chapter_number": "3.0"}, | |
| ) | |
| res_last = authenticated_client.post(url_last) | |
| assert res_last.status_code == 200 | |
| # Verify transition from reading -> completed (since no chapters > 3.0 exist) | |
| fav.refresh_from_db() | |
| assert fav.last_read_chapter == 3.0 | |
| assert fav.status == "completed" | |