158 lines
4.6 KiB
Python
158 lines
4.6 KiB
Python
import json
|
|
from pathlib import Path
|
|
from httpx import AsyncClient
|
|
import pytest
|
|
|
|
from collections.abc import AsyncGenerator
|
|
from typing import Any
|
|
|
|
from sqlalchemy.ext.asyncio import (
|
|
AsyncSession,
|
|
AsyncEngine,
|
|
async_sessionmaker,
|
|
)
|
|
from advanced_alchemy.base import UUIDAuditBase
|
|
from chitai.database import models as m
|
|
from chitai import services
|
|
from chitai.database.config import config
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _patch_db(
|
|
engine: AsyncEngine,
|
|
sessionmaker: async_sessionmaker[AsyncSession],
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
monkeypatch.setattr(config, "session_maker", sessionmaker)
|
|
monkeypatch.setattr(config, "engine_instance", engine)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
async def _seed_db(
|
|
engine: AsyncEngine,
|
|
sessionmaker: async_sessionmaker[AsyncSession],
|
|
raw_users: list[m.User | dict[str, Any]],
|
|
raw_libraries: list[m.Library | dict[str, Any]],
|
|
) -> AsyncGenerator[None, None]:
|
|
"""Populate test database with.
|
|
|
|
Args:
|
|
engine: The SQLAlchemy engine instance.
|
|
sessionmaker: The SQLAlchemy sessionmaker factory.
|
|
raw_users: Test users to add to the database
|
|
raw_teams: Test teams to add to the database
|
|
|
|
"""
|
|
|
|
metadata = UUIDAuditBase.registry.metadata
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(metadata.drop_all)
|
|
await conn.run_sync(metadata.create_all)
|
|
|
|
async with services.UserService.new(sessionmaker()) as users_service:
|
|
await users_service.create_many(raw_users, auto_commit=True)
|
|
|
|
async with services.LibraryService.new(sessionmaker()) as library_service:
|
|
await library_service.create_many(raw_libraries, auto_commit=True)
|
|
|
|
yield
|
|
|
|
|
|
@pytest.fixture
|
|
async def populated_authenticated_client(
|
|
authenticated_client: AsyncClient, books_to_upload: list[tuple[Path, dict]]
|
|
) -> AsyncClient:
|
|
# Upload books
|
|
for path, data in books_to_upload:
|
|
await upload_book_via_api(authenticated_client, data, path)
|
|
|
|
await create_bookshelf(
|
|
authenticated_client, {"title": "Favourites", "library_id": 1}
|
|
)
|
|
|
|
await add_books_to_bookshelf(authenticated_client, 1, [1, 2])
|
|
|
|
return authenticated_client
|
|
|
|
|
|
@pytest.fixture
|
|
def books_to_upload() -> list[tuple[Path, dict]]:
|
|
return [
|
|
(
|
|
Path(
|
|
"tests/data_files/The Adventures of Sherlock Holmes - Arthur Conan Doyle.epub"
|
|
),
|
|
{
|
|
"library_id": "1",
|
|
"title": "The Adventures of Sherlock Holmes",
|
|
"description": "Some description...",
|
|
"authors": "Arthur Conan Doyle",
|
|
"publisher": "Some Publisher",
|
|
"tags": "Mystery",
|
|
"edition": "2",
|
|
"language": "en",
|
|
"pages": "300",
|
|
"series": "Sherlock Holmes",
|
|
"series_position": "1",
|
|
"identifiers": json.dumps({"isbn-10": "1234567890"}),
|
|
},
|
|
),
|
|
(
|
|
Path("tests/data_files/Frankenstein - Mary Shelley.epub"),
|
|
{
|
|
"library_id": "1",
|
|
"title": "Frankenstein",
|
|
"description": "Some description...",
|
|
"authors": "Mary Shelley",
|
|
"tags": "Mystery",
|
|
"edition": "1",
|
|
"language": "en",
|
|
"pages": "250",
|
|
},
|
|
),
|
|
(
|
|
Path("tests/data_files/A Tale of Two Cities - Charles Dickens.epub"),
|
|
{
|
|
"library_id": "1",
|
|
"title": "A Tale of Two Cities",
|
|
"description": "Some description...",
|
|
"authors": "Charles Dickens",
|
|
"tags": "Classic",
|
|
"edition": "1",
|
|
"language": "en",
|
|
"pages": "500",
|
|
},
|
|
),
|
|
]
|
|
|
|
|
|
async def upload_book_via_api(
|
|
client: AsyncClient, book_data: dict, book_file_path: Path
|
|
) -> None:
|
|
with book_file_path.open("rb") as file:
|
|
files = {"files": file}
|
|
|
|
response = await client.post("/books?library_id=1", data=book_data, files=files)
|
|
|
|
assert response.status_code == 201
|
|
|
|
|
|
async def create_bookshelf(client: AsyncClient, shelf_data: dict) -> None:
|
|
response = await client.post("/shelves", json=shelf_data)
|
|
|
|
assert response.status_code == 201
|
|
|
|
|
|
async def add_books_to_bookshelf(
|
|
client: AsyncClient, shelf_id: int, book_ids: list[int]
|
|
) -> None:
|
|
query_params = ""
|
|
for id in book_ids:
|
|
query_params += f"book_ids={id}&"
|
|
|
|
response = await client.post(
|
|
f"/shelves/{shelf_id}/books", params={"book_ids": book_ids}
|
|
)
|
|
|
|
assert response.status_code == 201
|