All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m11s
- Run tests for all 10 services via per-service pytest subprocesses - Group results by service with section headers - Clickable summary cards filter by outcome (passed/failed/errors/skipped) - Service filter nav using ~nav-link buttons in menu bar - Full menu integration: ~header-row + ~header-child + ~menu-row - Show logo image via cart-mini rendering - Mount full service directories in docker-compose for test access - Add 24 unit test files across 9 services Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
"""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": "<p>Hello</p>", "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 == "<p>Hello</p>"
|
|
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 == []
|