Skip to content

Commit

Permalink
Added a User base model + BaseUserRepository + User actions (create, …
Browse files Browse the repository at this point in the history
…list, retrieve) + tests
  • Loading branch information
vanbuiten committed Feb 13, 2024
1 parent 6097037 commit 7e916bc
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 2 deletions.
File renamed without changes.
File renamed without changes.
38 changes: 38 additions & 0 deletions meldingen_core/actions/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from meldingen_core.models import User
from meldingen_core.repositories import BaseUserRepository


class UserCreateAction:
"""Action that stores a user."""

repository: BaseUserRepository

def __init__(self, repository: BaseUserRepository):
self.repository = repository

def __call__(self, user: User) -> None:
self.repository.add(user)


class UserListAction:
"""Action that retrieves a list of users."""

repository: BaseUserRepository

def __init__(self, repository: BaseUserRepository):
self.repository = repository

def __call__(self, *, limit: int | None = None, offset: int | None = None) -> list[User]:
return self.repository.list(limit=limit, offset=offset)


class UserRetrieveAction:
"""Action that retrieves a user."""

repository: BaseUserRepository

def __init__(self, repository: BaseUserRepository):
self.repository = repository

def __call__(self, pk: int) -> User | None:
return self.repository.retrieve(pk=pk)
7 changes: 7 additions & 0 deletions meldingen_core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ class Melding:
"""This is the base model for a 'melding'."""

text: str


class User:
"""This is the base model for a 'user'."""

username: str
email: str
6 changes: 5 additions & 1 deletion meldingen_core/repositories.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from abc import ABCMeta, abstractmethod
from typing import Generic, TypeVar

from meldingen_core.models import Melding
from meldingen_core.models import Melding, User

T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)
Expand All @@ -23,3 +23,7 @@ def retrieve(self, pk: int) -> T_co | None:

class BaseMeldingRepository(BaseRepository[Melding, Melding], metaclass=ABCMeta):
"""Repository for Melding."""


class BaseUserRepository(BaseRepository[User, User], metaclass=ABCMeta):
"""Repository for User."""
Empty file added tests/test_actions/__init__.py
Empty file.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from meldingen_core.actions import MeldingCreateAction, MeldingListAction, MeldingRetrieveAction
from meldingen_core.actions.melding import MeldingCreateAction, MeldingListAction, MeldingRetrieveAction
from meldingen_core.models import Melding
from meldingen_core.repositories import BaseMeldingRepository

Expand Down
151 changes: 151 additions & 0 deletions tests/test_actions/test_user_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import pytest

from meldingen_core.actions.user import UserCreateAction, UserListAction, UserRetrieveAction
from meldingen_core.models import User
from meldingen_core.repositories import BaseUserRepository

# Fixtures


@pytest.fixture
def unpopulated_users_repository() -> BaseUserRepository:
class TestUserRepository(BaseUserRepository):
data: list[User]

def __init__(self) -> None:
self.data = []

def add(self, user: User) -> None:
self.data.append(user)

def list(self, *, limit: int | None = None, offset: int | None = None) -> list[User]:
if limit and offset:
return self.data[offset : offset + limit]
elif limit and not offset:
return self.data[:limit]
elif not limit and offset:
return self.data[offset:]
else:
return self.data

def retrieve(self, pk: int) -> User | None:
for _user in self.data:
if _user.username == str(pk):
return _user
return None

def find_by_email(self, email: str) -> User | None:
for _user in self.data:
if _user.email == email:
return _user
return None

repository = TestUserRepository()
return repository


@pytest.fixture
def populated_users_repository(
unpopulated_users_repository: BaseUserRepository,
) -> BaseUserRepository:
for _pk in range(10):
user = User()
user.username = f"{_pk}"
user.email = f"user-{_pk}@example.com"
unpopulated_users_repository.add(user)

return unpopulated_users_repository


@pytest.fixture
def users_create_action(
unpopulated_users_repository: BaseUserRepository,
) -> UserCreateAction:
return UserCreateAction(unpopulated_users_repository)


@pytest.fixture
def users_list_action(
populated_users_repository: BaseUserRepository,
) -> UserListAction:
return UserListAction(populated_users_repository)


@pytest.fixture
def users_retrieve_action(
populated_users_repository: BaseUserRepository,
) -> UserRetrieveAction:
return UserRetrieveAction(populated_users_repository)


# PyTest Classes


class TestUserCreateAction:
def test_add(self, users_create_action: UserCreateAction) -> None:
assert len(users_create_action.repository.list()) == 0

user = User()
user.username = "1"

users_create_action(user)

assert len(users_create_action.repository.list()) == 1
assert users_create_action.repository.retrieve(pk=1) == user


class TestUserListAction:
def test_list_all(self, users_list_action: UserListAction) -> None:
users = users_list_action()

assert len(users) == 10

@pytest.mark.parametrize(
"limit, expected_result",
[(1, 1), (5, 5), (10, 10), (20, 10)],
)
def test_list_limit(self, users_list_action: UserListAction, limit: int, expected_result: int) -> None:
users = users_list_action(limit=limit)

assert len(users) == expected_result

@pytest.mark.parametrize("offset, expected_result", [(1, 9), (5, 5), (10, 0), (20, 0)])
def test_list_offset(
self,
users_list_action: UserListAction,
offset: int,
expected_result: int,
) -> None:
users = users_list_action(offset=offset)

assert len(users) == expected_result

@pytest.mark.parametrize(
"limit, offset, expected_result",
[(10, 0, 10), (5, 0, 5), (10, 10, 0), (20, 0, 10)],
)
def test_list_limit_offset(
self,
users_list_action: UserListAction,
limit: int,
offset: int,
expected_result: int,
) -> None:
users = users_list_action(limit=limit, offset=offset)

assert len(users) == expected_result


class TestUserRetrieveAction:
@pytest.mark.parametrize("pk", [1, 2, 3, 4, 5])
def test_retrieve_existing_users(self, users_retrieve_action: UserRetrieveAction, pk: int) -> None:
user = users_retrieve_action(pk=pk)

assert user is not None
assert user.username == str(pk)

@pytest.mark.parametrize("pk", [101, 102, 103, 104, 105])
def test_retrieve_non_existing_users(self, users_retrieve_action: UserRetrieveAction, pk: int) -> None:
user = users_retrieve_action(pk=pk)

assert user is None

0 comments on commit 7e916bc

Please sign in to comment.