"""Unit tests for federation DTO conversion functions.""" from __future__ import annotations from datetime import datetime from types import SimpleNamespace from unittest.mock import patch import pytest from shared.services.federation_impl import ( _actor_to_dto, _activity_to_dto, _follower_to_dto, _remote_actor_to_dto, _remote_post_to_dto, ) def _actor(**kwargs): defaults = { "id": 1, "user_id": 10, "preferred_username": "alice", "public_key_pem": "-----BEGIN PUBLIC KEY-----", "display_name": "Alice", "summary": "Hello", "created_at": datetime(2025, 1, 1), } defaults.update(kwargs) return SimpleNamespace(**defaults) def _activity(**kwargs): defaults = { "id": 1, "activity_id": "https://example.com/activity/1", "activity_type": "Create", "actor_profile_id": 1, "object_type": "Note", "object_data": {"content": "hi"}, "published": datetime(2025, 1, 1), "is_local": True, "source_type": "post", "source_id": 42, "ipfs_cid": None, } defaults.update(kwargs) return SimpleNamespace(**defaults) def _follower(**kwargs): defaults = { "id": 1, "actor_profile_id": 1, "follower_acct": "bob@remote.com", "follower_inbox": "https://remote.com/inbox", "follower_actor_url": "https://remote.com/users/bob", "created_at": datetime(2025, 1, 1), "app_domain": "federation.rose-ash.com", } defaults.update(kwargs) return SimpleNamespace(**defaults) def _remote_actor(**kwargs): defaults = { "id": 1, "actor_url": "https://remote.com/users/bob", "inbox_url": "https://remote.com/inbox", "preferred_username": "bob", "domain": "remote.com", "display_name": "Bob", "summary": "Hi", "icon_url": "https://remote.com/avatar.jpg", "shared_inbox_url": None, "public_key_pem": None, } defaults.update(kwargs) return SimpleNamespace(**defaults) def _remote_post(**kwargs): defaults = { "id": 1, "remote_actor_id": 1, "object_id": "https://remote.com/note/1", "content": "

Hello

", "summary": None, "url": "https://remote.com/note/1", "attachment_data": [{"type": "Image", "url": "img.jpg"}], "tag_data": [{"type": "Hashtag", "name": "#test"}], "published": datetime(2025, 1, 1), } defaults.update(kwargs) return SimpleNamespace(**defaults) class TestActorToDto: @patch("shared.services.federation_impl._domain", return_value="fed.example.com") def test_basic(self, mock_domain): dto = _actor_to_dto(_actor()) assert dto.preferred_username == "alice" assert dto.inbox_url == "https://fed.example.com/users/alice/inbox" assert dto.outbox_url == "https://fed.example.com/users/alice/outbox" assert dto.user_id == 10 assert dto.display_name == "Alice" class TestActivityToDto: def test_fields(self): dto = _activity_to_dto(_activity()) assert dto.activity_type == "Create" assert dto.object_type == "Note" assert dto.is_local is True assert dto.ipfs_cid is None class TestFollowerToDto: def test_fields(self): dto = _follower_to_dto(_follower()) assert dto.follower_acct == "bob@remote.com" assert dto.app_domain == "federation.rose-ash.com" class TestRemoteActorToDto: def test_fields(self): dto = _remote_actor_to_dto(_remote_actor()) assert dto.preferred_username == "bob" assert dto.domain == "remote.com" assert dto.icon_url == "https://remote.com/avatar.jpg" class TestRemotePostToDto: def test_with_actor(self): actor = _remote_actor() dto = _remote_post_to_dto(_remote_post(), actor=actor) assert dto.content == "

Hello

" assert dto.actor is not None assert dto.actor.preferred_username == "bob" def test_without_actor(self): dto = _remote_post_to_dto(_remote_post(), actor=None) assert dto.actor is None def test_none_content_becomes_empty(self): dto = _remote_post_to_dto(_remote_post(content=None)) assert dto.content == "" def test_none_attachments_becomes_list(self): dto = _remote_post_to_dto(_remote_post(attachment_data=None)) assert dto.attachments == [] def test_none_tags_becomes_list(self): dto = _remote_post_to_dto(_remote_post(tag_data=None)) assert dto.tags == []