From f7e72a93c056da92ae48124e57b3250f31f43524 Mon Sep 17 00:00:00 2001 From: Simone Robutti Date: Fri, 2 Dec 2022 19:40:58 +0100 Subject: [PATCH] add pagination (#179) * added pagination * integrated pagination with tortoise * added test for publications --- mobilizon_reshare/models/notification.py | 4 +- .../web/backend/events/endpoints.py | 9 +- mobilizon_reshare/web/backend/main.py | 10 +- .../web/backend/publications/endpoints.py | 9 +- poetry.lock | 162 ++++++++++++++---- pyproject.toml | 1 + tests/conftest.py | 18 +- tests/web/conftest.py | 5 +- tests/web/endpoints/test_events.py | 2 +- tests/web/endpoints/test_publications.py | 15 ++ 10 files changed, 184 insertions(+), 51 deletions(-) create mode 100644 tests/web/endpoints/test_publications.py diff --git a/mobilizon_reshare/models/notification.py b/mobilizon_reshare/models/notification.py index 5fee413..c3e1e1c 100644 --- a/mobilizon_reshare/models/notification.py +++ b/mobilizon_reshare/models/notification.py @@ -17,9 +17,7 @@ class Notification(Model): message = fields.TextField() - target = fields.ForeignKeyField( - "models.Publisher", related_name="notifications", null=True - ) + target = fields.ForeignKeyField("models.Publisher", null=True, related_name=False,) publication = fields.ForeignKeyField( "models.Publication", related_name="notifications", null=True diff --git a/mobilizon_reshare/web/backend/events/endpoints.py b/mobilizon_reshare/web/backend/events/endpoints.py index 329c208..3b0b49f 100644 --- a/mobilizon_reshare/web/backend/events/endpoints.py +++ b/mobilizon_reshare/web/backend/events/endpoints.py @@ -1,9 +1,10 @@ +from fastapi_pagination import Page +from fastapi_pagination.ext.tortoise import paginate + from mobilizon_reshare.models.event import Event -from mobilizon_reshare.storage.query.read import get_all_events def register_endpoints(app): - @app.get("/events", status_code=200) + @app.get("/events", status_code=200, response_model=Page[Event.to_pydantic()]) async def get_events(): - all_events = await get_all_events() - return [await Event.to_pydantic().from_tortoise_orm(x) for x in all_events] + return await paginate(Event, prefetch_related=True) diff --git a/mobilizon_reshare/web/backend/main.py b/mobilizon_reshare/web/backend/main.py index 6aaba5d..65b15bb 100644 --- a/mobilizon_reshare/web/backend/main.py +++ b/mobilizon_reshare/web/backend/main.py @@ -1,6 +1,7 @@ import logging from fastapi import FastAPI +from fastapi_pagination import add_pagination from mobilizon_reshare.storage.db import init as init_db, get_db_url from mobilizon_reshare.web.backend.events.endpoints import ( @@ -11,7 +12,6 @@ from mobilizon_reshare.web.backend.publications.endpoints import ( ) app = FastAPI() - logger = logging.getLogger(__name__) @@ -30,9 +30,15 @@ def register_endpoints(app): register_publication_endpoints(app) +def init_endpoints(app): + + register_endpoints(app) + add_pagination(app) + + @app.on_event("startup") async def init_app(init_logging=True): check_database() await init_db(init_logging=init_logging) - register_endpoints(app) + init_endpoints(app) return app diff --git a/mobilizon_reshare/web/backend/publications/endpoints.py b/mobilizon_reshare/web/backend/publications/endpoints.py index 7465fc7..987419c 100644 --- a/mobilizon_reshare/web/backend/publications/endpoints.py +++ b/mobilizon_reshare/web/backend/publications/endpoints.py @@ -1,7 +1,12 @@ +from fastapi_pagination import Page +from fastapi_pagination.ext.tortoise import paginate + from mobilizon_reshare.models.publication import Publication def register_endpoints(app): - @app.get("/publications", status_code=200) + @app.get( + "/publications", status_code=200, response_model=Page[Publication.to_pydantic()] + ) async def get_publications(): - return await Publication.to_pydantic().from_queryset(Publication.all()) + return await paginate(Publication, prefetch_related=True) diff --git a/poetry.lock b/poetry.lock index 197d033..526f638 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,8 +14,8 @@ tomlkit = "*" tortoise-orm = "*" [package.extras] -asyncmy = ["asyncmy"] asyncpg = ["asyncpg"] +asyncmy = ["asyncmy"] [[package]] name = "aiosqlite" @@ -221,10 +221,10 @@ optional = false python-versions = "*" [package.extras] -tests = ["pytest-pydocstyle (>=2.2.0)", "pytest-pycodestyle (>=2.2.0)", "pytest (>=6)", "pytest-pydocstyle (>=2)", "pytest-pycodestyle (>=2)", "pytest (==5.4.3)", "tox (>=3.7.0)", "sphinx (>=3)", "pytest-isort (>=1.2.0)", "pytest-cov (>=2.10.1)", "mock (>=1.3.0)", "check-manifest (>=0.42)"] -numpy = ["numpy (>=1.20.0)", "numpy (>=1.18.0)", "numpy (>=1.15.0)", "numpy (>=1.13.0)"] -docs = ["sphinx-rtd-theme (>=0.2)", "Sphinx (>=3)"] -all = ["numpy (>=1.20.0)", "pytest-pydocstyle (>=2.2.0)", "pytest-pycodestyle (>=2.2.0)", "pytest (>=6)", "pytest-pydocstyle (>=2)", "pytest-pycodestyle (>=2)", "pytest (==5.4.3)", "numpy (>=1.18.0)", "numpy (>=1.15.0)", "numpy (>=1.13.0)", "tox (>=3.7.0)", "sphinx (>=3)", "pytest-isort (>=1.2.0)", "pytest-cov (>=2.10.1)", "mock (>=1.3.0)", "check-manifest (>=0.42)", "sphinx-rtd-theme (>=0.2)", "Sphinx (>=3)"] +all = ["Sphinx (>=3)", "sphinx-rtd-theme (>=0.2)", "check-manifest (>=0.42)", "mock (>=1.3.0)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "sphinx (>=3)", "tox (>=3.7.0)", "numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "pytest (==5.4.3)", "pytest-pycodestyle (>=2)", "pytest-pydocstyle (>=2)", "pytest (>=6)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2.2.0)", "numpy (>=1.20.0)"] +docs = ["Sphinx (>=3)", "sphinx-rtd-theme (>=0.2)"] +numpy = ["numpy (>=1.13.0)", "numpy (>=1.15.0)", "numpy (>=1.18.0)", "numpy (>=1.20.0)"] +tests = ["check-manifest (>=0.42)", "mock (>=1.3.0)", "pytest-cov (>=2.10.1)", "pytest-isort (>=1.2.0)", "sphinx (>=3)", "tox (>=3.7.0)", "pytest (==5.4.3)", "pytest-pycodestyle (>=2)", "pytest-pydocstyle (>=2)", "pytest (>=6)", "pytest-pycodestyle (>=2.2.0)", "pytest-pydocstyle (>=2.2.0)"] [[package]] name = "docutils" @@ -281,6 +281,34 @@ dev = ["autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "pre-commit (>=2 doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer[all] (>=0.6.1,<0.7.0)"] test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.8.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest-cov (>=2.12.0,<5.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "requests (>=2.24.0,<3.0.0)", "sqlalchemy (>=1.3.18,<=1.4.41)", "types-orjson (==3.6.2)", "types-ujson (==5.5.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] +[[package]] +name = "fastapi-pagination" +version = "0.11.0" +description = "FastAPI pagination" +category = "main" +optional = false +python-versions = ">=3.8,<4.0" + +[package.dependencies] +fastapi = ">=0.80.0" +pydantic = ">=1.9.1" + +[package.extras] +sqlalchemy = ["SQLAlchemy (>=1.3.20)", "sqlakeyset (>=1.0.1659142803,<2.0.0)"] +asyncpg = ["SQLAlchemy (>=1.3.20)", "asyncpg (>=0.24.0)"] +all = ["SQLAlchemy (>=1.3.20)", "databases (>=0.6.0)", "orm (>=0.3.1)", "tortoise-orm (>=0.16.18,<0.20.0)", "asyncpg (>=0.24.0)", "ormar (>=0.11.2)", "django (<5.0.0)", "piccolo (>=0.89,<0.98)", "motor (>=2.5.1,<4.0.0)", "mongoengine (>=0.23.1,<0.25.0)", "sqlmodel (>=0.0.8,<0.0.9)", "pony (>=0.7.16,<0.8.0)", "beanie (>=1.11.9,<2.0.0)", "sqlakeyset (>=1.0.1659142803,<2.0.0)", "scylla-driver (>=3.25.6,<4.0.0)"] +databases = ["databases (>=0.6.0)"] +orm = ["databases (>=0.6.0)", "orm (>=0.3.1)"] +django = ["databases (>=0.6.0)", "django (<5.0.0)"] +tortoise = ["tortoise-orm (>=0.16.18,<0.20.0)"] +ormar = ["ormar (>=0.11.2)"] +piccolo = ["piccolo (>=0.89,<0.98)"] +motor = ["motor (>=2.5.1,<4.0.0)"] +mongoengine = ["mongoengine (>=0.23.1,<0.25.0)"] +sqlmodel = ["sqlmodel (>=0.0.8,<0.0.9)", "sqlakeyset (>=1.0.1659142803,<2.0.0)"] +beanie = ["beanie (>=1.11.9,<2.0.0)"] +scylla-driver = ["scylla-driver (>=3.25.6,<4.0.0)"] + [[package]] name = "h11" version = "0.12.0" @@ -456,8 +484,8 @@ optional = false python-versions = ">=3.6" [package.extras] -testing = ["pytest-benchmark", "pytest"] -dev = ["tox", "pre-commit"] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "pockets" @@ -597,11 +625,11 @@ six = ">=1.5" [[package]] name = "python-slugify" -version = "6.1.2" +version = "7.0.0" description = "A Python slugify application that also handles Unicode" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" [package.dependencies] text-unidecode = ">=1.3" @@ -1013,62 +1041,123 @@ content-hash = "2aa23f0b2cdc0fbe76d3a7430e3a8ce65bd037dd737d64c1c22a6b6db0d8e66b [metadata.files] aerich = [] -aiosqlite = [] +aiosqlite = [ + {file = "aiosqlite-0.17.0-py3-none-any.whl", hash = "sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231"}, + {file = "aiosqlite-0.17.0.tar.gz", hash = "sha256:f0e6acc24bc4864149267ac82fb46dfb3be4455f99fe21df82609cc6e6baee51"}, +] alabaster = [] anyio = [] -appdirs = [] -arrow = [] +appdirs = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] +arrow = [ + {file = "arrow-1.1.1-py3-none-any.whl", hash = "sha256:77a60a4db5766d900a2085ce9074c5c7b8e2c99afeaa98ad627637ff6f292510"}, + {file = "arrow-1.1.1.tar.gz", hash = "sha256:dee7602f6c60e3ec510095b5e301441bc56288cb8f51def14dcb3079f623823a"}, +] asgiref = [] asyncpg = [] -asynctest = [] +asynctest = [ + {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, + {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, +] atomicwrites = [] attrs = [] babel = [] -beautifulsoup4 = [] +beautifulsoup4 = [ + {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, + {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, +] certifi = [] -charset-normalizer = [] +charset-normalizer = [ + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, +] click = [] colorama = [] coverage = [] css-html-js-minify = [] -dictdiffer = [] +dictdiffer = [ + {file = "dictdiffer-0.9.0-py2.py3-none-any.whl", hash = "sha256:442bfc693cfcadaf46674575d2eba1c53b42f5e404218ca2c2ff549f2df56595"}, + {file = "dictdiffer-0.9.0.tar.gz", hash = "sha256:17bacf5fbfe613ccf1b6d512bd766e6b21fb798822a133aa86098b8ac9997578"}, +] docutils = [] dynaconf = [] facebook-sdk = [] fastapi = [] -h11 = [] +fastapi-pagination = [] +h11 = [ + {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, + {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, +] httpcore = [] httpx = [] idna = [] imagesize = [] importlib-metadata = [] -iniconfig = [] +iniconfig = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] iso8601 = [] jinja2 = [] lxml = [] markdownify = [] markupsafe = [] oauthlib = [] -packaging = [] -pluggy = [] +packaging = [ + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, +] +pluggy = [ + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, +] pockets = [] -py = [] +py = [ + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, +] pydantic = [] pygments = [] pyparsing = [] pypika-tortoise = [] -pytest = [] -pytest-asyncio = [] +pytest = [ + {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, + {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, +] +pytest-asyncio = [ + {file = "pytest-asyncio-0.15.1.tar.gz", hash = "sha256:2564ceb9612bbd560d19ca4b41347b54e7835c2f792c504f698e05395ed63f6f"}, + {file = "pytest_asyncio-0.15.1-py3-none-any.whl", hash = "sha256:3042bcdf1c5d978f6b74d96a151c4cfb9dcece65006198389ccd7e6c60eb1eea"}, +] pytest-cov = [] -pytest-lazy-fixture = [] -python-dateutil = [] +pytest-lazy-fixture = [ + {file = "pytest-lazy-fixture-0.6.3.tar.gz", hash = "sha256:0e7d0c7f74ba33e6e80905e9bfd81f9d15ef9a790de97993e34213deb5ad10ac"}, + {file = "pytest_lazy_fixture-0.6.3-py3-none-any.whl", hash = "sha256:e0b379f38299ff27a653f03eaa69b08a6fd4484e46fd1c9907d984b9f9daeda6"}, +] +python-dateutil = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] python-slugify = [] pytz = [] -requests = [] +requests = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, +] requests-oauthlib = [] -responses = [] -rfc3986 = [] -six = [] +responses = [ + {file = "responses-0.13.4-py2.py3-none-any.whl", hash = "sha256:d8d0f655710c46fd3513b9202a7f0dcedd02ca0f8cf4976f27fa8ab5b81e656d"}, + {file = "responses-0.13.4.tar.gz", hash = "sha256:9476775d856d3c24ae660bbebe29fb6d789d4ad16acd723efbfb6ee20990b899"}, +] +rfc3986 = [ + {file = "rfc3986-1.5.0-py2.py3-none-any.whl", hash = "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"}, + {file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"}, +] +six = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] sniffio = [] snowballstemmer = [] soupsieve = [] @@ -1083,12 +1172,21 @@ sphinxcontrib-napoleon = [] sphinxcontrib-qthelp = [] sphinxcontrib-serializinghtml = [] starlette = [] -text-unidecode = [] -toml = [] +text-unidecode = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] +toml = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] tomli = [] tomlkit = [] tortoise-orm = [] -tweepy = [] +tweepy = [ + {file = "tweepy-4.4.0-py2.py3-none-any.whl", hash = "sha256:cf02c4fbbd027fbc7172c24d03f53f061329ac040b22d201e59592a1cff86364"}, + {file = "tweepy-4.4.0.tar.gz", hash = "sha256:8d4b4520271b796fa7efc4c5d5ef3228af4d79f6a4d3ace3900b2778ed8f6f1c"}, +] typing-extensions = [] unidecode = [] urllib3 = [] diff --git a/pyproject.toml b/pyproject.toml index 410c750..3798e9f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ facebook-sdk = "~3.1" aerich = "~0.6" fastapi = "~0.85" uvicorn = "~0.17" +fastapi-pagination = "^0.11.0" [tool.poetry.dev-dependencies] responses = "~0.13" diff --git a/tests/conftest.py b/tests/conftest.py index a0b8065..48c996c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,7 +25,6 @@ from mobilizon_reshare.publishers.abstract import ( ) from mobilizon_reshare.publishers.exceptions import PublisherError, InvalidResponse from mobilizon_reshare.storage.query.converter import event_to_model -from mobilizon_reshare.storage.query.write import get_publisher_by_name from tests import today with importlib.resources.path( @@ -195,8 +194,10 @@ def event_model_generator(): @pytest.fixture() def publisher_model_generator(): - def _publisher_model_generator(idx=1,): - return Publisher(name=f"publisher_{idx}", account_ref=f"account_ref_{idx}") + def _publisher_model_generator(idx=1, name=None): + return Publisher( + name=name or f"publisher_{idx}", account_ref=f"account_ref_{idx}" + ) return _publisher_model_generator @@ -509,13 +510,13 @@ async def event_with_failed_publication( @pytest.fixture -async def failed_publication(stored_event) -> Publication: +async def failed_publication(stored_event, mock_publisher) -> Publication: p = Publication( event=stored_event, status=PublicationStatus.FAILED, timestamp=arrow.now().datetime, - publisher=await get_publisher_by_name("mock"), + publisher=mock_publisher, ) await p.save() return p @@ -524,3 +525,10 @@ async def failed_publication(stored_event) -> Publication: @pytest.fixture def command_config(): return CommandConfig(dry_run=False) + + +@pytest.fixture() +async def mock_publisher(publisher_model_generator): + publisher = await publisher_model_generator(name="mock") + await publisher.save() + return publisher diff --git a/tests/web/conftest.py b/tests/web/conftest.py index c90cd18..0626099 100644 --- a/tests/web/conftest.py +++ b/tests/web/conftest.py @@ -3,7 +3,7 @@ import urllib3 from httpx import AsyncClient from mobilizon_reshare.storage import db -from mobilizon_reshare.web.backend.main import app, register_endpoints +from mobilizon_reshare.web.backend.main import app, init_endpoints @pytest.fixture(scope="session") @@ -13,7 +13,8 @@ def anyio_backend(): @pytest.fixture() async def client(): - register_endpoints(app) + init_endpoints(app) + async with AsyncClient(app=app, base_url="http://test") as client: yield client diff --git a/tests/web/endpoints/test_events.py b/tests/web/endpoints/test_events.py index e397041..20bc44e 100644 --- a/tests/web/endpoints/test_events.py +++ b/tests/web/endpoints/test_events.py @@ -14,4 +14,4 @@ async def test_events(client: AsyncClient, event_model_generator): response = await client.get("/events") assert response.status_code == 200 expected = await Event.to_pydantic().from_tortoise_orm(event) - assert response.json()[0] == json.loads(expected.json()) + assert response.json()["items"][0] == json.loads(expected.json()) diff --git a/tests/web/endpoints/test_publications.py b/tests/web/endpoints/test_publications.py new file mode 100644 index 0000000..69d6987 --- /dev/null +++ b/tests/web/endpoints/test_publications.py @@ -0,0 +1,15 @@ +import json + +import pytest +from httpx import AsyncClient + +from mobilizon_reshare.models.publication import Publication + + +@pytest.mark.asyncio +async def test_publication(client: AsyncClient, failed_publication): + + response = await client.get("/publications") + assert response.status_code == 200 + expected = await Publication.to_pydantic().from_tortoise_orm(failed_publication) + assert response.json()["items"][0] == json.loads(expected.json())