import json from django.test import TestCase from apps.drama.models import GameEvent, record from apps.epic.models import Room from apps.lyric.models import User class WebFingerTest(TestCase): def setUp(self): self.user = User.objects.create(email="actor@test.io", username="actor") def test_returns_jrd_for_known_user(self): response = self.client.get( "/.well-known/webfinger", {"resource": "acct:actor@earthmanrpg.me"}, ) self.assertEqual(response.status_code, 200) self.assertEqual(response["Content-Type"], "application/jrd+json") def test_jrd_links_to_actor_url(self): response = self.client.get( "/.well-known/webfinger", {"resource": "acct:actor@earthmanrpg.me"}, ) data = json.loads(response.content) hrefs = [link["href"] for link in data["links"]] self.assertTrue(any("/ap/users/actor/" in href for href in hrefs)) def test_returns_404_for_unknown_user(self): response = self.client.get( "/.well-known/webfinger", {"resource": "acct:nobody@earthmanrpg.me"}, ) self.assertEqual(response.status_code, 404) def test_returns_400_for_missing_resource(self): response = self.client.get("/.well-known/webfinger") self.assertEqual(response.status_code, 400) class ActorViewTest(TestCase): def setUp(self): self.user = User.objects.create(email="actor@test.io", username="actor") def test_returns_200_for_known_user(self): response = self.client.get("/ap/users/actor/") self.assertEqual(response.status_code, 200) def test_returns_activity_json_content_type(self): response = self.client.get("/ap/users/actor/") self.assertEqual(response["Content-Type"], "application/activity+json") def test_actor_has_required_fields(self): response = self.client.get("/ap/users/actor/") data = json.loads(response.content) self.assertEqual(data["type"], "Person") self.assertIn("id", data) self.assertIn("outbox", data) self.assertIn("publicKey", data) def test_requires_no_authentication(self): # AP Actor endpoints must be publicly accessible self.client.logout() response = self.client.get("/ap/users/actor/") self.assertEqual(response.status_code, 200) def test_returns_404_for_unknown_user(self): response = self.client.get("/ap/users/nobody/") self.assertEqual(response.status_code, 404) class OutboxViewTest(TestCase): def setUp(self): self.user = User.objects.create(email="actor@test.io", username="actor") self.room = Room.objects.create(name="Test Room", owner=self.user) record( self.room, GameEvent.SLOT_FILLED, actor=self.user, slot_number=1, token_type="coin", token_display="Coin", renewal_days=7, ) record( self.room, GameEvent.ROLE_SELECTED, actor=self.user, role="PC", slot_number=1, role_display="Player", ) # INVITE_SENT is unsupported — should be excluded from outbox record(self.room, GameEvent.INVITE_SENT, actor=self.user) def test_returns_200(self): response = self.client.get("/ap/users/actor/outbox/") self.assertEqual(response.status_code, 200) def test_returns_activity_json_content_type(self): response = self.client.get("/ap/users/actor/outbox/") self.assertEqual(response["Content-Type"], "application/activity+json") def test_outbox_is_ordered_collection(self): response = self.client.get("/ap/users/actor/outbox/") data = json.loads(response.content) self.assertEqual(data["type"], "OrderedCollection") def test_total_items_excludes_unsupported_verbs(self): response = self.client.get("/ap/users/actor/outbox/") data = json.loads(response.content) # 2 supported events (SLOT_FILLED + ROLE_SELECTED); INVITE_SENT excluded self.assertEqual(data["totalItems"], 2) def test_requires_no_authentication(self): self.client.logout() response = self.client.get("/ap/users/actor/outbox/") self.assertEqual(response.status_code, 200) def test_returns_404_for_unknown_user(self): response = self.client.get("/ap/users/nobody/outbox/") self.assertEqual(response.status_code, 404)