Files
links/tests/test_bookmarks_api.py
T
2026-07-30 15:56:31 +10:00

152 lines
6.3 KiB
Python

"""Integration tests for the Bookmarks REST API (/api/bookmarks)."""
import pytest
# a minimal full-export object as produced by x-bookmarks-exporter
SAMPLE_EXPORT = {
"id": "1234567890",
"url": "https://x.com/user/status/1234567890",
"author": {
"screen_name": "testuser",
"name": "Test User",
"profile_image_url": "https://example.com/avatar.jpg",
},
"text": "Hello world",
"media": [{"type": "photo", "media_url": "https://example.com/p.jpg",
"media_large": "https://example.com/p.jpg"}],
"card": None,
"quoted": None,
"retweet": None,
"favorite_count": 7, "view_count": 21, "bookmark_count": 1,
}
@pytest.mark.django_db
class TestBookmarksAPI:
BASE = "/api/bookmarks"
def test_list_empty(self, api_client):
r = api_client.get(f"{self.BASE}")
assert r.status_code == 200
assert r.json()["count"] == 0
def test_create_then_list_and_detail(self, api_client):
r = api_client.post(self.BASE, {
"tweet_id": "111",
"url": "https://x.com/u/status/111",
"author_screen_name": "u",
"text": "hi", "has_photo": True,
}, format="json")
assert r.status_code == 201, r.content
created = r.json()
assert created["tweet_id"] == "111"
list_r = api_client.get(self.BASE)
assert list_r.json()["count"] == 1
det = api_client.get(f"{self.BASE}/{created['id']}")
assert det.status_code == 200
assert det.json()["has_photo"] is True
def test_filter_has_video(self, api_client):
api_client.post(self.BASE, {"tweet_id": "v1", "has_video": True}, format="json")
api_client.post(self.BASE, {"tweet_id": "p1", "has_photo": True}, format="json")
r = api_client.get(f"{self.BASE}", {"has_video": "true"})
assert r.json()["count"] == 1
assert r.json()["results"][0]["tweet_id"] == "v1"
def test_search_q(self, api_client):
api_client.post(self.BASE, {"tweet_id": "a1", "text": "python tips"}, format="json")
api_client.post(self.BASE, {"tweet_id": "a2", "text": "rust tricks"}, format="json")
r = api_client.get(f"{self.BASE}", {"q": "python"})
assert r.json()["count"] == 1
assert r.json()["results"][0]["tweet_id"] == "a1"
def test_update_summary(self, api_client):
created = api_client.post(self.BASE, {"tweet_id": "u1"}, format="json").json()
r = api_client.patch(f"{self.BASE}/{created['id']}", {"summary": "AI summary"},
format="json")
assert r.status_code == 200
assert r.json()["summary"] == "AI summary"
def test_delete(self, api_client):
created = api_client.post(self.BASE, {"tweet_id": "d1"}, format="json").json()
r = api_client.delete(f"{self.BASE}/{created['id']}")
assert r.status_code == 204
def test_bulk_import_upserts(self, api_client):
r = api_client.post(f"{self.BASE}/import",
{"bookmarks": [SAMPLE_EXPORT]},
format="json")
assert r.status_code == 200, r.content
assert r.json()["created"] == 1
# second import with changed content → update
r2 = api_client.post(f"{self.BASE}/import",
{"bookmarks": [
{**SAMPLE_EXPORT, "text": "updated"}]},
format="json")
assert r2.json()["updated"] == 1
assert r2.json()["created"] == 0
from links.models import Bookmark
assert Bookmark.objects.count() == 1
assert Bookmark.objects.first().text == "updated"
def test_bulk_import_unchanged_skips_save(self, api_client):
"""Re-importing identical content should count as 'unchanged', not 'updated'."""
# first import
r1 = api_client.post(f"{self.BASE}/import",
{"bookmarks": [SAMPLE_EXPORT]},
format="json")
assert r1.json()["created"] == 1
# second import with identical content
r2 = api_client.post(f"{self.BASE}/import",
{"bookmarks": [SAMPLE_EXPORT]},
format="json")
assert r2.status_code == 200, r2.content
assert r2.json()["unchanged"] == 1
assert r2.json()["updated"] == 0
assert r2.json()["created"] == 0
from links.models import Bookmark
bm = Bookmark.objects.first()
# last_imported_at should be set even when unchanged
assert bm.last_imported_at is not None
# content_hash should be populated
assert bm.content_hash != ''
def test_bulk_upsert_array_unchanged(self, api_client):
"""Bulk array endpoint should also detect unchanged content."""
r1 = api_client.post(f"{self.BASE}/bulk",
[{"tweet_id": "ub1", "text": "same"}],
format="json")
assert r1.json()["created"] == 1
# re-import identical
r2 = api_client.post(f"{self.BASE}/bulk",
[{"tweet_id": "ub1", "text": "same"}],
format="json")
assert r2.json()["unchanged"] == 1
assert r2.json()["updated"] == 0
def test_bulk_upsert_array(self, api_client):
r = api_client.post(f"{self.BASE}/bulk",
[{"tweet_id": "b1", "text": "one"},
{"tweet_id": "b2", "text": "two"}],
format="json")
assert r.status_code == 200
assert r.json()["created"] == 2
r2 = api_client.post(f"{self.BASE}/bulk",
[{"tweet_id": "b1", "text": "one-edit"}],
format="json")
assert r2.json()["updated"] == 1
from links.models import Bookmark
assert Bookmark.objects.get(tweet_id="b1").text == "one-edit"
def test_stats(self, api_client):
api_client.post(self.BASE, {"tweet_id": "s1", "has_video": True}, format="json")
api_client.post(self.BASE, {"tweet_id": "s2", "has_photo": True}, format="json")
r = api_client.get(f"{self.BASE}/stats")
assert r.status_code == 200
s = r.json()
assert s["total"] == 2
assert s["has_video"] == 1
assert s["has_photo"] == 1