diff options
author | 2024-08-19 20:55:14 +0100 | |
---|---|---|
committer | 2024-08-19 20:55:14 +0100 | |
commit | 1a65b54c77d53ae755c5cb3fa6a8241667813f07 (patch) | |
tree | cef6c1ded5b6010976e34916d9032dbf0ca5995c /thallium-backend | |
parent | Drop static file mount (diff) |
Add conftest for access to database
Diffstat (limited to 'thallium-backend')
-rw-r--r-- | thallium-backend/tests/conftest.py | 60 | ||||
-rw-r--r-- | thallium-backend/tests/test_app.py | 12 | ||||
-rw-r--r-- | thallium-backend/tests/test_login.py | 19 |
3 files changed, 85 insertions, 6 deletions
diff --git a/thallium-backend/tests/conftest.py b/thallium-backend/tests/conftest.py new file mode 100644 index 0000000..3e3c8cf --- /dev/null +++ b/thallium-backend/tests/conftest.py @@ -0,0 +1,60 @@ +from collections.abc import AsyncGenerator, Callable + +import pytest +from fastapi import FastAPI +from httpx import AsyncClient +from sqlalchemy import text +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine + +from src.app import fastapi_app +from src.orm import Base +from src.settings import CONFIG, Connections, _get_db_session + +db_url = CONFIG.database_url.get_secret_value() +test_db_url = db_url + "_test" +DB_ENGINE = create_async_engine(test_db_url, isolation_level="REPEATABLE READ", echo=False) +DB_SESSION_MAKER = async_sessionmaker(DB_ENGINE) + + [email protected](scope="session") +async def _create_test_database_engine() -> AsyncGenerator: + """Yield back a Database engine object.""" + create_engine = Connections.DB_ENGINE.execution_options(isolation_level="AUTOCOMMIT", echo=False) + async with create_engine.connect() as conn: + await conn.execute(text(f"DROP DATABASE IF EXISTS {DB_ENGINE.url.database}")) + await conn.execute(text(f"CREATE DATABASE {DB_ENGINE.url.database}")) + + +async def db_session(_create_test_database_engine: None) -> AsyncGenerator[AsyncSession]: + """Yield an Asynchronous database session.""" + async with DB_ENGINE.begin() as conn: + await conn.run_sync(Base.metadata.drop_all) + await conn.run_sync(Base.metadata.create_all) + async with AsyncSession(bind=conn, expire_on_commit=False) as session: + yield session + await session.close() + + +def override_db_session(db_session: AsyncSession) -> AsyncSession: + """Yield the modified Database session that uses the correspondent Database.""" + + async def _override_db_session() -> AsyncGenerator[AsyncSession]: + yield db_session + + return _override_db_session + + +def app(override_db_session: Callable) -> FastAPI: + """Override the default FastAPI app to use the overridden DB session.""" + fastapi_app.dependency_overrides[_get_db_session] = override_db_session + return fastapi_app + + +async def http_client(app: FastAPI) -> AsyncGenerator[AsyncClient]: + """Yield a client for testing the app.""" + async with AsyncClient(app=app, base_url="http://testserver", follow_redirects=True) as ac: + yield ac diff --git a/thallium-backend/tests/test_app.py b/thallium-backend/tests/test_app.py index c7c4937..254bb18 100644 --- a/thallium-backend/tests/test_app.py +++ b/thallium-backend/tests/test_app.py @@ -1,9 +1,9 @@ -from fastapi.testclient import TestClient +import pytest +from httpx import AsyncClient -from src.app import fastapi_app - -def test_heartbeat() -> None: +async def test_heartbeat(http_client: AsyncClient) -> None: """Ensure the heartbeat works.""" - with TestClient(app=fastapi_app) as client: - assert client.get("/heartbeat").json() == {"detail": "I am alive!"} + resp = await http_client.get("/heartbeat") + assert resp.json() == {"detail": "I am alive!"} diff --git a/thallium-backend/tests/test_login.py b/thallium-backend/tests/test_login.py new file mode 100644 index 0000000..c742d01 --- /dev/null +++ b/thallium-backend/tests/test_login.py @@ -0,0 +1,19 @@ +from http import HTTPStatus + +import pytest +from httpx import AsyncClient +from sqlalchemy.ext.asyncio import AsyncSession + +from src.orm import Voucher + + +async def test_successful_voucher_login(http_client: AsyncClient, db_session: AsyncSession) -> None: + """Test that a valid voucher can login to the system and receive a JWT.""" + db_session.add(Voucher(voucher_code="k1p", balance="13.37")) + await db_session.flush() + + resp = await http_client.post("/voucher-login", json={"voucher_code": "k1p"}) + resp_data: dict[str, str] = resp.json() + assert resp.status_code == HTTPStatus.OK + assert {"voucher_code", "jwt"} <= resp_data.keys() |