More tests

This commit is contained in:
Thomas Sileo 2022-06-22 22:17:07 +02:00
parent 01a409dc78
commit a2cfc36dab
3 changed files with 97 additions and 7 deletions

View File

@ -6,6 +6,7 @@ from typing import Any
import httpx
from app import config
from app.config import AP_CONTENT_TYPE # noqa: F401
from app.httpsig import auth
from app.key import get_pubkey_as_pem

View File

@ -1,7 +1,9 @@
from urllib.parse import urlparse
from uuid import uuid4
import factory # type: ignore
from Crypto.PublicKey import RSA
from dateutil.parser import isoparse
from sqlalchemy import orm
from app import activitypub as ap
@ -10,6 +12,7 @@ from app import models
from app.actor import RemoteActor
from app.ap_object import RemoteObject
from app.database import engine
from app.database import now
_Session = orm.scoped_session(orm.sessionmaker(bind=engine))
@ -47,6 +50,36 @@ def build_accept_activity(
}
def build_note_object(
from_remote_actor: actor.RemoteActor,
outbox_public_id: str | None = None,
content: str = "Hello",
to: list[str] = None,
cc: list[str] = None,
tags: list[ap.RawObject] = None,
) -> ap.RawObject:
published = now().replace(microsecond=0).isoformat().replace("+00:00", "Z")
context = from_remote_actor.ap_id + "/ctx/" + uuid4().hex
note_id = outbox_public_id or uuid4().hex
return {
"@context": ap.AS_CTX,
"type": "Note",
"id": from_remote_actor.ap_id + "/note/" + note_id,
"attributedTo": from_remote_actor.ap_id,
"content": content,
"to": to or [ap.AS_PUBLIC],
"cc": cc or [],
"published": published,
"context": context,
"conversation": context,
"url": from_remote_actor.ap_id + "/note/" + note_id,
"tag": tags or [],
"summary": None,
"inReplyTo": None,
"sensitive": False,
}
class BaseModelMeta:
sqlalchemy_session = _Session
sqlalchemy_session_persistence = "commit"
@ -138,3 +171,36 @@ class OutgoingActivityFactory(factory.alchemy.SQLAlchemyModelFactory):
# recipient
# outbox_object_id
class InboxObjectFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta(BaseModelMeta):
model = models.InboxObject
@classmethod
def from_remote_object(
cls,
ro: RemoteObject,
actor: models.Actor,
relates_to_inbox_object_id: int | None = None,
relates_to_outbox_object_id: int | None = None,
):
ap_published_at = now()
if "published" in ro.ap_object:
ap_published_at = isoparse(ro.ap_object["published"])
return cls(
server=urlparse(ro.ap_id).netloc,
actor_id=actor.id,
ap_actor_id=actor.ap_id,
ap_type=ro.ap_type,
ap_id=ro.ap_id,
ap_context=ro.context,
ap_published_at=ap_published_at,
ap_object=ro.ap_object,
visibility=ro.visibility,
relates_to_inbox_object_id=relates_to_inbox_object_id,
relates_to_outbox_object_id=relates_to_outbox_object_id,
activity_object_ap_id=ro.activity_object_ap_id,
# Hide replies from the stream
is_hidden_from_stream=True if ro.in_reply_to else False,
)

View File

@ -1,6 +1,8 @@
import pytest
from fastapi.testclient import TestClient
from app import activitypub as ap
from app.actor import LOCAL_ACTOR
from app.database import Session
_ACCEPTED_AP_HEADERS = [
@ -11,20 +13,41 @@ _ACCEPTED_AP_HEADERS = [
]
@pytest.mark.anyio
def test_index(db: Session, client: TestClient):
def test_index__html(db: Session, client: TestClient):
response = client.get("/")
assert response.status_code == 200
assert response.headers["content-type"].startswith("text/html")
@pytest.mark.parametrize("accept", _ACCEPTED_AP_HEADERS)
def test__ap_version(client, db, accept: str) -> None:
response = client.get("/followers", headers={"Accept": accept})
def test_index__ap(db: Session, client: TestClient, accept: str):
response = client.get("/", headers={"Accept": accept})
assert response.status_code == 200
assert response.headers["content-type"] == "application/activity+json"
assert response.headers["content-type"] == ap.AP_CONTENT_TYPE
assert response.json() == LOCAL_ACTOR.ap_actor
def test_followers__ap(client, db) -> None:
response = client.get("/followers", headers={"Accept": ap.AP_CONTENT_TYPE})
assert response.status_code == 200
assert response.headers["content-type"] == ap.AP_CONTENT_TYPE
assert response.json()["id"].endswith("/followers")
def test__html(client, db) -> None:
response = client.get("/followers", headers={"Accept": "application/activity+json"})
def test_followers__html(client, db) -> None:
response = client.get("/followers")
assert response.status_code == 200
assert response.headers["content-type"].startswith("text/html")
def test_following__ap(client, db) -> None:
response = client.get("/following", headers={"Accept": ap.AP_CONTENT_TYPE})
assert response.status_code == 200
assert response.headers["content-type"] == ap.AP_CONTENT_TYPE
assert response.json()["id"].endswith("/following")
def test_following__html(client, db) -> None:
response = client.get("/following")
assert response.status_code == 200
assert response.headers["content-type"].startswith("text/html")