added main-controller tests
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
from .controller import MainController
|
||||
from app.controllers.events import EventController
|
||||
from app.controllers.group import GroupController
|
||||
from app.controllers.musicians import MusicianController
|
||||
from app.controllers.users import UserController
|
||||
|
||||
controller = MainController()
|
||||
user_controller = UserController()
|
||||
event_controller = EventController()
|
||||
group_controller = GroupController()
|
||||
musicians_controller = MusicianController()
|
||||
|
||||
@@ -3,6 +3,12 @@ from fastapi.security import HTTPAuthorizationCredentials
|
||||
from icecream import ic
|
||||
|
||||
from app.admin import oauth_token
|
||||
from app.controllers import (
|
||||
event_controller,
|
||||
group_controller,
|
||||
musicians_controller,
|
||||
user_controller,
|
||||
)
|
||||
from app.controllers.events import EventController
|
||||
from app.controllers.group import GroupController
|
||||
from app.controllers.musicians import MusicianController
|
||||
@@ -22,19 +28,29 @@ class MainController:
|
||||
All methods are asynchronous to facilitate asynchronous calls from the Router layer.
|
||||
|
||||
token-based authentication is handled here as needed per the nature of the data being accessed.
|
||||
|
||||
Testing: pass mocked sub-controllers to the constructor.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.event_controller = EventController()
|
||||
self.musician_controller = MusicianController()
|
||||
self.user_controller = UserController()
|
||||
self.group_controller = GroupController()
|
||||
def __init__(
|
||||
self,
|
||||
event_controller=event_controller,
|
||||
musicians_controller=musicians_controller,
|
||||
user_controller=user_controller,
|
||||
group_controller=group_controller,
|
||||
oauth_token=oauth_token,
|
||||
) -> None:
|
||||
self.event_controller = event_controller
|
||||
self.musician_controller = musicians_controller
|
||||
self.user_controller = user_controller
|
||||
self.group_controller = group_controller
|
||||
self.oauth_token = oauth_token
|
||||
|
||||
async def get_musicians(self) -> list[Musician]:
|
||||
return self.musician_controller.get_musicians()
|
||||
|
||||
async def get_musician(self, id: int) -> Musician:
|
||||
return self.musician_controller.get_musician(id)
|
||||
async def get_musician(self, musician_id: int) -> Musician:
|
||||
return self.musician_controller.get_musician(musician_id)
|
||||
|
||||
async def update_musician(
|
||||
self,
|
||||
@@ -49,7 +65,7 @@ class MainController:
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="ID in URL does not match ID in request body",
|
||||
)
|
||||
_, sub = oauth_token.email_and_sub(token)
|
||||
_, sub = self.oauth_token.email_and_sub(token)
|
||||
self.user_controller.get_user_by_sub(sub)
|
||||
return self.musician_controller.update_musician(
|
||||
musician_id=musician.id,
|
||||
@@ -60,42 +76,54 @@ class MainController:
|
||||
async def get_events(self) -> list[EventSeries]:
|
||||
return self.event_controller.get_all_series()
|
||||
|
||||
async def get_event(self, id: int) -> EventSeries:
|
||||
return self.event_controller.get_one_series_by_id(id)
|
||||
async def get_event(self, series_id: int) -> EventSeries:
|
||||
return self.event_controller.get_one_series_by_id(series_id)
|
||||
|
||||
async def create_event(
|
||||
self, series: NewEventSeries, token: HTTPAuthorizationCredentials
|
||||
) -> EventSeries:
|
||||
_, sub = oauth_token.email_and_sub(token)
|
||||
_, sub = self.oauth_token.email_and_sub(token)
|
||||
self.user_controller.get_user_by_sub(sub)
|
||||
return self.event_controller.create_series(series)
|
||||
|
||||
async def add_series_poster(
|
||||
self, series_id: int, poster: UploadFile, token: HTTPAuthorizationCredentials
|
||||
) -> EventSeries:
|
||||
_, sub = oauth_token.email_and_sub(token)
|
||||
_, sub = self.oauth_token.email_and_sub(token)
|
||||
self.user_controller.get_user_by_sub(sub)
|
||||
return self.event_controller.add_series_poster(series_id, poster)
|
||||
|
||||
async def delete_series(self, id: int, token: HTTPAuthorizationCredentials) -> None:
|
||||
_, sub = oauth_token.email_and_sub(token)
|
||||
async def delete_series(
|
||||
self, series_id: int, token: HTTPAuthorizationCredentials
|
||||
) -> None:
|
||||
_, sub = self.oauth_token.email_and_sub(token)
|
||||
self.user_controller.get_user_by_sub(sub)
|
||||
self.event_controller.delete_series(id)
|
||||
self.event_controller.delete_series(series_id)
|
||||
|
||||
async def update_series(
|
||||
self, route_id: int, series: EventSeries, token: HTTPAuthorizationCredentials
|
||||
) -> EventSeries:
|
||||
_, sub = oauth_token.email_and_sub(token)
|
||||
_, sub = self.oauth_token.email_and_sub(token)
|
||||
self.user_controller.get_user_by_sub(sub)
|
||||
return self.event_controller.update_series(route_id, series)
|
||||
|
||||
async def get_users(self) -> list[User]:
|
||||
return self.user_controller.get_users()
|
||||
|
||||
async def get_user(self, id: int) -> User:
|
||||
return self.user_controller.get_user_by_id(id)
|
||||
async def get_user(self, user_id: int) -> User:
|
||||
return self.user_controller.get_user_by_id(user_id)
|
||||
|
||||
async def create_user(self, token: HTTPAuthorizationCredentials) -> User:
|
||||
"""This method does NOT post a user to the database.
|
||||
Instead, it retrieves the user's information from the OAuth token,
|
||||
updates the user's sub in the db if needed, and returns the user object.
|
||||
|
||||
Args:
|
||||
token (HTTPAuthorizationCredentials): The OAuth token
|
||||
|
||||
Returns:
|
||||
User: The User object
|
||||
"""
|
||||
return self.user_controller.create_user(token)
|
||||
|
||||
async def get_group(self) -> Group:
|
||||
@@ -104,6 +132,6 @@ class MainController:
|
||||
async def update_group_bio(
|
||||
self, bio: str, token: HTTPAuthorizationCredentials
|
||||
) -> Group:
|
||||
_, sub = oauth_token.email_and_sub(token)
|
||||
_, sub = self.oauth_token.email_and_sub(token)
|
||||
self.user_controller.get_user_by_sub(sub)
|
||||
return self.group_controller.update_group_bio(bio)
|
||||
|
||||
@@ -116,6 +116,14 @@ class UserController(BaseController):
|
||||
)
|
||||
|
||||
def create_user(self, token: HTTPAuthorizationCredentials) -> User:
|
||||
"""Updates a user's sub in the database and creates a new User object.
|
||||
|
||||
Args:
|
||||
token (HTTPAuthorizationCredentials): The token containing the user's email and sub
|
||||
|
||||
Returns:
|
||||
User: A User object which is suitable for a response body
|
||||
"""
|
||||
email, sub = oauth_token.email_and_sub(token)
|
||||
user: User = self.get_user_by_email(email)
|
||||
if user.sub is None:
|
||||
|
||||
@@ -3,7 +3,7 @@ from asyncio import gather
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from app.controllers import MainController
|
||||
from app.controllers.controller import MainController
|
||||
from app.models.tgd import TheGrapefruitsDuo
|
||||
from app.routers.contact import router as contact_router
|
||||
from app.routers.events import router as event_router
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from app.controllers.controller import MainController
|
||||
|
||||
controller = MainController()
|
||||
|
||||
@@ -3,8 +3,8 @@ from fastapi.security import HTTPAuthorizationCredentials
|
||||
from icecream import ic
|
||||
|
||||
from app.admin import oauth2_http
|
||||
from app.controllers import controller
|
||||
from app.models.event import EventSeries, NewEventSeries
|
||||
from app.routers import controller
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/events",
|
||||
|
||||
@@ -3,8 +3,8 @@ from fastapi.security.http import HTTPAuthorizationCredentials
|
||||
from icecream import ic
|
||||
|
||||
from app.admin import oauth2_http
|
||||
from app.controllers import controller
|
||||
from app.models.group import Group
|
||||
from app.routers import controller
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/group",
|
||||
|
||||
@@ -3,8 +3,8 @@ from fastapi.security import HTTPAuthorizationCredentials
|
||||
from icecream import ic
|
||||
|
||||
from app.admin import oauth2_http
|
||||
from app.controllers import controller
|
||||
from app.models.musician import Musician
|
||||
from app.routers import controller
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/musicians",
|
||||
|
||||
@@ -2,8 +2,8 @@ from fastapi import APIRouter, Depends, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials
|
||||
|
||||
from app.admin import oauth2_http
|
||||
from app.controllers import controller
|
||||
from app.models.user import User
|
||||
from app.routers import controller
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/users",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "thegrapefruitsduo"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
package-mode = false
|
||||
description = "FastAPI backend for thegrapefruitsduo.com"
|
||||
authors = ["Lucas Jensen <lucas.p.jensen10@gmail.com>"]
|
||||
|
||||
168
server/tests/controllers/test_main_controller.py
Normal file
168
server/tests/controllers/test_main_controller.py
Normal file
@@ -0,0 +1,168 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException, status
|
||||
from icecream import ic
|
||||
|
||||
from app.controllers.controller import MainController
|
||||
from app.models.event import Event, EventSeries, NewEventSeries
|
||||
from app.models.group import Group
|
||||
from app.models.musician import Musician
|
||||
from app.models.user import User
|
||||
|
||||
mock_user_controller = MagicMock()
|
||||
mock_musician_controller = MagicMock()
|
||||
mock_group_controller = MagicMock()
|
||||
mock_event_controller = MagicMock()
|
||||
mock_oauth_token = MagicMock()
|
||||
|
||||
mock_oauth_token.email_and_sub = MagicMock(return_value=("email", "sub"))
|
||||
|
||||
mock_token = MagicMock()
|
||||
|
||||
controller = MainController(
|
||||
user_controller=mock_user_controller,
|
||||
musicians_controller=mock_musician_controller,
|
||||
group_controller=mock_group_controller,
|
||||
event_controller=mock_event_controller,
|
||||
oauth_token=mock_oauth_token, # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def test_type():
|
||||
"""Tests the type of the controller object."""
|
||||
assert isinstance(controller, MainController)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_musicians():
|
||||
"""Tests the get_musicians method."""
|
||||
await controller.get_musicians()
|
||||
MagicMock.assert_called_once_with(mock_musician_controller.get_musicians)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_musician():
|
||||
"""Tests the get_musician method."""
|
||||
musician_id = 1
|
||||
await controller.get_musician(musician_id)
|
||||
MagicMock.assert_called_once_with(
|
||||
mock_musician_controller.get_musician, musician_id
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_musician():
|
||||
"""Tests the update_musician method.
|
||||
Underlying controller methods are tested elsewhere. This test is to ensure the method is called correctly.
|
||||
"""
|
||||
musician = Musician(
|
||||
id=1, name="John Doe", bio="A musician", headshot_id="headshot123"
|
||||
)
|
||||
|
||||
await controller.update_musician(
|
||||
musician=musician, url_param_id=1, token=mock_token
|
||||
)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called_once(mock_user_controller.get_user_by_sub)
|
||||
MagicMock.assert_called_once(mock_musician_controller.update_musician)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_events():
|
||||
"""Tests the get_events method."""
|
||||
await controller.get_events()
|
||||
MagicMock.assert_called_once(mock_event_controller.get_all_series)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_event():
|
||||
"""Tests the get_event method."""
|
||||
series_id = 1
|
||||
await controller.get_event(series_id)
|
||||
MagicMock.assert_called_once_with(
|
||||
mock_event_controller.get_one_series_by_id, series_id
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_event():
|
||||
"""Tests the create_event method."""
|
||||
series = NewEventSeries(name="Test Event", description="A test event", events=[])
|
||||
await controller.create_event(series, mock_token)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called(mock_user_controller.get_user_by_sub)
|
||||
MagicMock.assert_called(mock_event_controller.create_series)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_series_poster():
|
||||
"""Tests the add_series_poster method."""
|
||||
series_id = 1
|
||||
poster = MagicMock()
|
||||
await controller.add_series_poster(series_id, poster, mock_token)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called(mock_user_controller.get_user_by_sub)
|
||||
MagicMock.assert_called(mock_event_controller.add_series_poster)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_series():
|
||||
"""Tests the delete_series method."""
|
||||
series_id = 1
|
||||
await controller.delete_series(series_id, mock_token)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called(mock_user_controller.get_user_by_sub)
|
||||
MagicMock.assert_called(mock_event_controller.delete_series)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_series():
|
||||
"""Tests the update_series method."""
|
||||
series = EventSeries(
|
||||
series_id=1, name="Test Event", description="A test event", events=[]
|
||||
)
|
||||
await controller.update_series(1, series, mock_token)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called(mock_user_controller.get_user_by_sub)
|
||||
MagicMock.assert_called(mock_event_controller.update_series)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_users():
|
||||
"""Tests the get_users method."""
|
||||
await controller.get_users()
|
||||
MagicMock.assert_called_once(mock_user_controller.get_users)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_user():
|
||||
"""Tests the get_user method."""
|
||||
user_id = 1
|
||||
await controller.get_user(user_id)
|
||||
MagicMock.assert_called_once_with(mock_user_controller.get_user_by_id, user_id)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_user():
|
||||
"""Tests the create_user method."""
|
||||
await controller.create_user(mock_token)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called(mock_user_controller.create_user)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_group():
|
||||
"""Tests the get_group method."""
|
||||
await controller.get_group()
|
||||
MagicMock.assert_called_once(mock_group_controller.get_group)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_group_bio():
|
||||
"""Tests the update_group_bio method."""
|
||||
bio = "A new bio"
|
||||
await controller.update_group_bio(bio, mock_token)
|
||||
MagicMock.assert_called_with(mock_oauth_token.email_and_sub, mock_token)
|
||||
MagicMock.assert_called(mock_user_controller.get_user_by_sub)
|
||||
MagicMock.assert_called(mock_group_controller.update_group_bio)
|
||||
Reference in New Issue
Block a user