Skip to content

Commit

Permalink
Cover manga repository with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ThirVondukr committed Feb 23, 2024
1 parent 3983051 commit c484122
Show file tree
Hide file tree
Showing 18 changed files with 110 additions and 32 deletions.
15 changes: 9 additions & 6 deletions src/app/db/models/_manga.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,26 @@ class MangaInfo(
),
)

manga_id: Mapped[UUID] = mapped_column(ForeignKey("manga.id"), index=True)
manga: Mapped[Manga] = relationship(back_populates="info")
manga_id: Mapped[UUID] = mapped_column(
ForeignKey("manga.id"),
index=True,
default=None,
)
manga: Mapped[Manga] = relationship(back_populates="info", default=None)
language: Mapped[Language]
language_regconfig: Mapped[str] = mapped_column(
REGCONFIG,
insert_default=_regconfig_default,
init=False,
)
title: Mapped[str] = mapped_column(String(250))
description: Mapped[str] = mapped_column(
String(1000),
nullable=False,
)
description: Mapped[str] = mapped_column(String(1000))
search_ts_vector: Mapped[str] = mapped_column(
TSVECTOR,
Computed(
"setweight(to_tsvector(language_regconfig, coalesce(title, '')), 'A') || "
"setweight(to_tsvector(language_regconfig, coalesce(description, '')), 'D')",
persisted=True,
),
init=False,
)
3 changes: 2 additions & 1 deletion src/lib/db.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from collections.abc import Sequence
from typing import Protocol, TypeVar
from typing import Protocol, TypeVar, runtime_checkable

from sqlalchemy.orm import DeclarativeBase

T = TypeVar("T", bound=DeclarativeBase)


@runtime_checkable
class DBContext(Protocol):
"""
Constrained interface for sqlalchemy AsyncSession.
Expand Down
3 changes: 0 additions & 3 deletions tests/adapters/api/test_healthcheck.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
from http import HTTPStatus

import pytest
from httpx import AsyncClient

pytestmark = [pytest.mark.anyio]


async def test_healthcheck(http_client: AsyncClient) -> None:
response = await http_client.get("/health")
Expand Down
4 changes: 0 additions & 4 deletions tests/adapters/graphql/auth/test_signin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
from typing import Any

import pytest

from app.db.models import User
from app.settings import AuthSettings
from tests.adapters.graphql.client import GraphQLClient

pytestmark = pytest.mark.anyio

_QUERY = """mutation ($input: SignInInput!) {
auth {
signIn(input: $input) {
Expand Down
2 changes: 0 additions & 2 deletions tests/adapters/graphql/auth/test_signup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
from app.settings import AuthSettings
from tests.adapters.graphql.client import GraphQLClient

pytestmark = pytest.mark.anyio

_QUERY = """mutation ($input: SignUpInput!) {
auth {
signUp(input: $input) {
Expand Down
3 changes: 0 additions & 3 deletions tests/adapters/graphql/manga/fields/test_manga_tags.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import pytest
from sqlalchemy.ext.asyncio import AsyncSession

from app.db.models import Manga
from tests.adapters.graphql.client import GraphQLClient
from tests.factories import MangaTagFactory

pytestmark = pytest.mark.anyio

_QUERY = """query ($id: ID!) {
manga(id: $id) {
id
Expand Down
2 changes: 1 addition & 1 deletion tests/adapters/graphql/manga/queries/test_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from app.db.models import Manga
from tests.adapters.graphql.client import GraphQLClient

pytestmark = [pytest.mark.anyio, pytest.mark.usefixtures("session")]
pytestmark = [pytest.mark.usefixtures("session")]

QUERY = """
query Query($id: ID!) {
Expand Down
2 changes: 1 addition & 1 deletion tests/adapters/graphql/manga/queries/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from app.db.models import Manga
from tests.adapters.graphql.client import GraphQLClient

pytestmark = [pytest.mark.anyio, pytest.mark.usefixtures("session")]
pytestmark = [pytest.mark.usefixtures("session")]

QUERY = """
query SearchManga($filter: MangaFilter! = {}, $pagination: PagePaginationInput! = {}) {
Expand Down
2 changes: 1 addition & 1 deletion tests/adapters/graphql/manga/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from app.db.models import Manga
from tests.adapters.graphql.client import GraphQLClient

pytestmark = [pytest.mark.anyio, pytest.mark.usefixtures("session")]
pytestmark = [pytest.mark.usefixtures("session")]

QUERY = """mutation Mutation($input: MangaCreateInput!) {
manga {
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
]


@pytest.fixture(scope="session")
@pytest.fixture(scope="session", autouse=True)
def anyio_backend() -> str:
return "asyncio"

Expand Down
2 changes: 1 addition & 1 deletion tests/core/domains/auth/commands/test_signin_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from app.db.models import User
from tests.types import Resolver

pytestmark = [pytest.mark.anyio, pytest.mark.usefixtures("session")]
pytestmark = [pytest.mark.usefixtures("session")]


@pytest.fixture
Expand Down
3 changes: 0 additions & 3 deletions tests/core/domains/auth/test_token_service.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from datetime import UTC, datetime

import freezegun
import pytest

from app.core.domain.auth.services import TokenService
from app.db.models import User
from app.settings import AuthSettings

pytestmark = pytest.mark.anyio


async def test_create_access_token_ok(
user: User,
Expand Down
Empty file.
85 changes: 85 additions & 0 deletions tests/core/domains/manga/test_manga_repository.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import random
import uuid
from collections.abc import Sequence

from app.core.domain.manga.filters import MangaFilter, TagFilter
from app.core.domain.manga.repositories import MangaRepository
from app.db.models import Manga, MangaInfo, MangaTag
from lib.db import DBContext
from lib.pagination.pagination import PagePaginationParamsDTO
from lib.types import Language


async def test_get_ok(manga_repository: MangaRepository, manga: Manga) -> None:
assert await manga_repository.get(id=manga.id) is manga


async def test_get_not_found(manga_repository: MangaRepository) -> None:
assert await manga_repository.get(id=uuid.uuid4()) is None


async def test_filter_search_term(
manga: Manga,
manga_repository: MangaRepository,
db_context: DBContext,
) -> None:
manga.info = [
MangaInfo(title="Search title", description="", language=Language.eng),
]
db_context.add(manga)
await db_context.flush()

result = await manga_repository.paginate(
filter=MangaFilter(search_term="not included"),
pagination=PagePaginationParamsDTO(page=1, page_size=100),
)
assert result.items == []

result = await manga_repository.paginate(
filter=MangaFilter(search_term="Search"),
pagination=PagePaginationParamsDTO(page=1, page_size=100),
)
assert result.items == [manga]


async def test_tags(
manga_repository: MangaRepository,
db_context: DBContext,
manga: Manga,
tags: Sequence[MangaTag],
) -> None:
manga.tags = random.sample(tags, k=len(tags) // 2)
assert manga.tags

db_context.add(manga)
await db_context.flush()
pagination = PagePaginationParamsDTO(page=1, page_size=100)

for tag in manga.tags:
result = await manga_repository.paginate(
filter=MangaFilter(tags=TagFilter(include=[tag.name_slug])),
pagination=pagination,
)
assert result.items == [manga]

result = await manga_repository.paginate(
filter=MangaFilter(tags=TagFilter(exclude=[tag.name_slug])),
pagination=pagination,
)
assert result.items == []

for tag in tags:
if tag in manga.tags:
continue

result = await manga_repository.paginate(
filter=MangaFilter(tags=TagFilter(include=[tag.name_slug])),
pagination=pagination,
)
assert result.items == []

result = await manga_repository.paginate(
filter=MangaFilter(tags=TagFilter(exclude=[tag.name_slug])),
pagination=pagination,
)
assert result.items == [manga]
2 changes: 1 addition & 1 deletion tests/core/domains/users/commands/test_register_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from app.db.models import User
from tests.types import Resolver

pytestmark = [pytest.mark.anyio, pytest.mark.usefixtures("session")]
pytestmark = [pytest.mark.usefixtures("session")]


@pytest.fixture
Expand Down
2 changes: 0 additions & 2 deletions tests/core/domains/users/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from app.core.domain.users.filters import UserFilter
from app.core.domain.users.repositories import UserRepository

pytestmark = pytest.mark.anyio


@pytest.mark.usefixtures("user")
async def test_exists_ok(user_repository: UserRepository) -> None:
Expand Down
4 changes: 2 additions & 2 deletions tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ class MangaFactory(GenericFactory[Manga]):


class MangaTagFactory(GenericFactory[MangaTag]):
name = factory.Faker("word")
name_slug = factory.Faker("word")
name = factory.Faker("text", max_nb_chars=32)
name_slug = factory.Faker("text", max_nb_chars=32)


class ChapterFactory:
Expand Down
6 changes: 6 additions & 0 deletions tests/plugins/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from passlib.context import CryptContext
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.domain.manga.repositories import MangaRepository
from lib.db import DBContext
from tests.types import Resolver

Expand All @@ -14,3 +15,8 @@ def db_context(session: AsyncSession) -> DBContext:
@pytest.fixture
async def crypt_context(resolver: Resolver) -> CryptContext:
return await resolver(CryptContext)


@pytest.fixture
async def manga_repository(resolver: Resolver) -> MangaRepository:
return await resolver(MangaRepository)

0 comments on commit c484122

Please sign in to comment.