From 23832574bca16c063ee820992b0c2be8e95aa6ca Mon Sep 17 00:00:00 2001 From: Thomas Sileo Date: Tue, 26 Jul 2022 20:26:34 +0200 Subject: [PATCH] Improve tests --- tests/test_inbox.py | 16 +++++------- tests/test_outbox.py | 62 +++++++++----------------------------------- tests/utils.py | 51 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 60 deletions(-) diff --git a/tests/test_inbox.py b/tests/test_inbox.py index 4d821db..0f53d72 100644 --- a/tests/test_inbox.py +++ b/tests/test_inbox.py @@ -9,8 +9,11 @@ from app import activitypub as ap from app import models from app.actor import LOCAL_ACTOR from app.ap_object import RemoteObject +from app.incoming_activities import process_next_incoming_activity from tests import factories from tests.utils import mock_httpsig_checker +from tests.utils import run_async +from tests.utils import setup_remote_actor def test_inbox_requires_httpsig( @@ -56,8 +59,7 @@ def test_inbox_follow_request( # Then the server returns a 204 assert response.status_code == 202 - # TODO: processing incoming activity instead - return + run_async(process_next_incoming_activity) # And the actor was saved in DB saved_actor = db.query(models.Actor).one() @@ -89,12 +91,7 @@ def test_inbox_accept_follow_request( respx_mock: respx.MockRouter, ) -> None: # Given a remote actor - ra = factories.RemoteActorFactory( - base_url="https://example.com", - username="toto", - public_key="pk", - ) - respx_mock.get(ra.ap_id).mock(return_value=httpx.Response(200, json=ra.ap_actor)) + ra = setup_remote_actor(respx_mock) actor_in_db = factories.ActorFactory.from_remote_actor(ra) # And a Follow activity in the outbox @@ -129,8 +126,7 @@ def test_inbox_accept_follow_request( # Then the server returns a 204 assert response.status_code == 202 - # TODO: processing incoming activity instead - return + run_async(process_next_incoming_activity) # And the Accept activity was saved in the inbox inbox_activity = db.query(models.InboxObject).one() diff --git a/tests/test_outbox.py b/tests/test_outbox.py index 6aba1d0..e3b3e94 100644 --- a/tests/test_outbox.py +++ b/tests/test_outbox.py @@ -1,20 +1,16 @@ from unittest import mock -from uuid import uuid4 -import httpx import respx from fastapi.testclient import TestClient from sqlalchemy.orm import Session from app import activitypub as ap -from app import actor from app import models from app import webfinger -from app.actor import LOCAL_ACTOR -from app.ap_object import RemoteObject from app.config import generate_csrf_token -from tests import factories from tests.utils import generate_admin_session_cookies +from tests.utils import setup_remote_actor +from tests.utils import setup_remote_actor_as_follower def test_outbox__no_activities( @@ -30,47 +26,13 @@ def test_outbox__no_activities( assert json_response["orderedItems"] == [] -def _setup_remote_actor(respx_mock: respx.MockRouter) -> actor.RemoteActor: - ra = factories.RemoteActorFactory( - base_url="https://example.com", - username="toto", - public_key="pk", - ) - respx_mock.get(ra.ap_id).mock(return_value=httpx.Response(200, json=ra.ap_actor)) - return ra - - -def _remote_actor_as_follower(ra: actor.RemoteActor) -> models.Follower: - actor = factories.ActorFactory.from_remote_actor(ra) - - follow_id = uuid4().hex - follow_from_inbox = RemoteObject( - factories.build_follow_activity( - from_remote_actor=ra, - for_remote_actor=LOCAL_ACTOR, - outbox_public_id=follow_id, - ), - ra, - ) - inbox_object = factories.InboxObjectFactory.from_remote_object( - follow_from_inbox, actor - ) - - follower = factories.FollowerFactory( - inbox_object_id=inbox_object.id, - actor_id=actor.id, - ap_actor_id=actor.ap_id, - ) - return follower - - def test_send_follow_request( db: Session, client: TestClient, respx_mock: respx.MockRouter, ) -> None: # given a remote actor - ra = _setup_remote_actor(respx_mock) + ra = setup_remote_actor(respx_mock) response = client.post( "/admin/actions/follow", @@ -103,7 +65,7 @@ def test_send_create_activity__no_followers_and_with_mention( respx_mock: respx.MockRouter, ) -> None: # given a remote actor - ra = _setup_remote_actor(respx_mock) + ra = setup_remote_actor(respx_mock) with mock.patch.object(webfinger, "get_actor_url", return_value=ra.ap_id): response = client.post( @@ -136,10 +98,10 @@ def test_send_create_activity__with_followers( respx_mock: respx.MockRouter, ) -> None: # given a remote actor - ra = _setup_remote_actor(respx_mock) + ra = setup_remote_actor(respx_mock) # who is a follower - follower = _remote_actor_as_follower(ra) + follower = setup_remote_actor_as_follower(ra) with mock.patch.object(webfinger, "get_actor_url", return_value=ra.ap_id): response = client.post( @@ -172,10 +134,10 @@ def test_send_create_activity__question__one_of( respx_mock: respx.MockRouter, ) -> None: # given a remote actor - ra = _setup_remote_actor(respx_mock) + ra = setup_remote_actor(respx_mock) # who is a follower - follower = _remote_actor_as_follower(ra) + follower = setup_remote_actor_as_follower(ra) with mock.patch.object(webfinger, "get_actor_url", return_value=ra.ap_id): response = client.post( @@ -216,10 +178,10 @@ def test_send_create_activity__question__any_of( respx_mock: respx.MockRouter, ) -> None: # given a remote actor - ra = _setup_remote_actor(respx_mock) + ra = setup_remote_actor(respx_mock) # who is a follower - follower = _remote_actor_as_follower(ra) + follower = setup_remote_actor_as_follower(ra) with mock.patch.object(webfinger, "get_actor_url", return_value=ra.ap_id): response = client.post( @@ -262,10 +224,10 @@ def test_send_create_activity__article( respx_mock: respx.MockRouter, ) -> None: # given a remote actor - ra = _setup_remote_actor(respx_mock) + ra = setup_remote_actor(respx_mock) # who is a follower - follower = _remote_actor_as_follower(ra) + follower = setup_remote_actor_as_follower(ra) with mock.patch.object(webfinger, "get_actor_url", return_value=ra.ap_id): response = client.post( diff --git a/tests/utils.py b/tests/utils.py index cd09df3..a2b51b2 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,12 +1,21 @@ +import asyncio from contextlib import contextmanager from typing import Any +from uuid import uuid4 import fastapi +import httpx +import respx from app import actor from app import httpsig +from app import models +from app.actor import LOCAL_ACTOR +from app.ap_object import RemoteObject from app.config import session_serializer +from app.database import async_session from app.main import app +from tests import factories @contextmanager @@ -28,3 +37,45 @@ def mock_httpsig_checker(ra: actor.RemoteActor): def generate_admin_session_cookies() -> dict[str, Any]: return {"session": session_serializer.dumps({"is_logged_in": True})} + + +def setup_remote_actor(respx_mock: respx.MockRouter) -> actor.RemoteActor: + ra = factories.RemoteActorFactory( + base_url="https://example.com", + username="toto", + public_key="pk", + ) + respx_mock.get(ra.ap_id).mock(return_value=httpx.Response(200, json=ra.ap_actor)) + return ra + + +def setup_remote_actor_as_follower(ra: actor.RemoteActor) -> models.Follower: + actor = factories.ActorFactory.from_remote_actor(ra) + + follow_id = uuid4().hex + follow_from_inbox = RemoteObject( + factories.build_follow_activity( + from_remote_actor=ra, + for_remote_actor=LOCAL_ACTOR, + outbox_public_id=follow_id, + ), + ra, + ) + inbox_object = factories.InboxObjectFactory.from_remote_object( + follow_from_inbox, actor + ) + + follower = factories.FollowerFactory( + inbox_object_id=inbox_object.id, + actor_id=actor.id, + ap_actor_id=actor.ap_id, + ) + return follower + + +def run_async(func, *args, **kwargs): + async def _func(): + async with async_session() as db: + return await func(db, *args, **kwargs) + + asyncio.run(_func())