Finish off backend tests
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
from sqlalchemy.orm import Session
|
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.enums import CourseEnum
|
from src.enums import CourseEnum
|
||||||
from src.models import CourseProgress, User
|
from src.models import CourseProgress, User
|
||||||
@@ -50,7 +50,9 @@ def initialize_user(db: Session, user: User):
|
|||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
def patch_course_progress(db: Session, user: User, course: CourseEnum, course_progress: CourseProgressBase):
|
def patch_course_progress(
|
||||||
|
db: Session, user: User, course: CourseEnum, course_progress: CourseProgressBase
|
||||||
|
):
|
||||||
"""Change the progress value for a given course"""
|
"""Change the progress value for a given course"""
|
||||||
if course_progress.progress_value > 1 or course_progress.progress_value < 0:
|
if course_progress.progress_value > 1 or course_progress.progress_value < 0:
|
||||||
raise HTTPException(status_code=400, detail="Invalid progress value")
|
raise HTTPException(status_code=400, detail="Invalid progress value")
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ DEFAULT_NR_HIGH_SCORES = 10
|
|||||||
|
|
||||||
def get_high_scores(db: Session, minigame: MinigameEnum, nr_highest: int):
|
def get_high_scores(db: Session, minigame: MinigameEnum, nr_highest: int):
|
||||||
"""Get the n highest scores of a given minigame"""
|
"""Get the n highest scores of a given minigame"""
|
||||||
if nr_highest < 1:
|
if nr_highest:
|
||||||
raise HTTPException(status_code=400, detail="Invalid number of high scores")
|
if nr_highest < 1:
|
||||||
|
raise HTTPException(status_code=400, detail="Invalid number of high scores")
|
||||||
|
|
||||||
user_high_scores = []
|
user_high_scores = []
|
||||||
|
|
||||||
@@ -42,7 +43,9 @@ def get_high_scores(db: Session, minigame: MinigameEnum, nr_highest: int):
|
|||||||
return user_high_scores
|
return user_high_scores
|
||||||
|
|
||||||
|
|
||||||
def create_high_score(db: Session, user: User, minigame: MinigameEnum, high_score: HighScoreBase):
|
def create_high_score(
|
||||||
|
db: Session, user: User, minigame: MinigameEnum, high_score: HighScoreBase
|
||||||
|
):
|
||||||
"""Create a new high score for a given minigame"""
|
"""Create a new high score for a given minigame"""
|
||||||
|
|
||||||
def add_to_db():
|
def add_to_db():
|
||||||
|
|||||||
13
src/main.py
13
src/main.py
@@ -65,16 +65,17 @@ async def login(user: users.UserCreate, db: Session = Depends(get_db)):
|
|||||||
async def get_high_scores(
|
async def get_high_scores(
|
||||||
minigame: MinigameEnum,
|
minigame: MinigameEnum,
|
||||||
nr_highest: Optional[int] = None,
|
nr_highest: Optional[int] = None,
|
||||||
|
current_user_name: str = Depends(crud_authentication.get_current_user_name),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
return crud_highscores.get_high_scores(db, minigame, nr_highest)
|
return crud_highscores.get_high_scores(db, minigame, nr_highest)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/highscores/{minigame}", response_model=highscores.HighScore)
|
@app.put("/highscores/{minigame}", response_model=highscores.HighScore)
|
||||||
async def create_high_score(
|
async def create_high_score(
|
||||||
minigame: MinigameEnum,
|
minigame: MinigameEnum,
|
||||||
high_score: highscores.HighScoreBase,
|
high_score: highscores.HighScoreBase,
|
||||||
current_user_name=Depends(crud_authentication.get_current_user_name),
|
current_user_name: str = Depends(crud_authentication.get_current_user_name),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
current_user = crud_users.get_user_by_username(db, current_user_name)
|
current_user = crud_users.get_user_by_username(db, current_user_name)
|
||||||
@@ -93,7 +94,9 @@ async def get_course_progress(
|
|||||||
return crud_courseprogress.get_course_progress(db, current_user, course)
|
return crud_courseprogress.get_course_progress(db, current_user, course)
|
||||||
|
|
||||||
|
|
||||||
@app.patch("/courseprogress/{course}", response_model=List[courseprogress.CourseProgressParent])
|
@app.patch(
|
||||||
|
"/courseprogress/{course}", response_model=List[courseprogress.CourseProgressParent]
|
||||||
|
)
|
||||||
async def patch_course_progress(
|
async def patch_course_progress(
|
||||||
course: CourseEnum,
|
course: CourseEnum,
|
||||||
course_progress: courseprogress.CourseProgressBase,
|
course_progress: courseprogress.CourseProgressBase,
|
||||||
@@ -101,7 +104,9 @@ async def patch_course_progress(
|
|||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
current_user = crud_users.get_user_by_username(db, current_user_name)
|
current_user = crud_users.get_user_by_username(db, current_user_name)
|
||||||
return crud_courseprogress.patch_course_progress(db, current_user, course, course_progress)
|
return crud_courseprogress.patch_course_progress(
|
||||||
|
db, current_user, course, course_progress
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#### TESTING!! DELETE LATER
|
#### TESTING!! DELETE LATER
|
||||||
|
|||||||
16
tests/base.py
Normal file
16
tests/base.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
sys.path.append("..")
|
||||||
|
|
||||||
|
from src.main import app, get_db
|
||||||
|
from tests.config.database import override_get_db
|
||||||
|
|
||||||
|
app.dependency_overrides[get_db] = override_get_db
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
username = "user1"
|
||||||
|
password = "password"
|
||||||
|
avatar = "lion"
|
||||||
@@ -1,21 +1,10 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
sys.path.append("..")
|
|
||||||
|
|
||||||
from src.main import app, get_db
|
from src.main import app, get_db
|
||||||
|
from tests.base import avatar, client, password, username
|
||||||
from tests.config.database import clear_db, override_get_db
|
from tests.config.database import clear_db, override_get_db
|
||||||
|
|
||||||
app.dependency_overrides[get_db] = override_get_db
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
username = "user1"
|
|
||||||
password = "password"
|
|
||||||
avatar = "lion"
|
|
||||||
|
|
||||||
|
|
||||||
async def register_user():
|
async def register_user():
|
||||||
response = client.post(
|
response = client.post(
|
||||||
|
|||||||
@@ -1,23 +1,13 @@
|
|||||||
import random
|
import random
|
||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
sys.path.append("..")
|
|
||||||
|
|
||||||
from src.enums import CourseEnum
|
from src.enums import CourseEnum
|
||||||
from src.main import app, get_db
|
from src.main import app, get_db
|
||||||
|
from tests.base import avatar, client, password, username
|
||||||
from tests.config.database import clear_db, override_get_db
|
from tests.config.database import clear_db, override_get_db
|
||||||
|
|
||||||
app.dependency_overrides[get_db] = override_get_db
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
username = "user1"
|
|
||||||
password = "password"
|
|
||||||
avatar = "lion"
|
|
||||||
|
|
||||||
|
|
||||||
async def register_user():
|
async def register_user():
|
||||||
response = client.post(
|
response = client.post(
|
||||||
@@ -67,6 +57,19 @@ async def test_get_all_returns_all():
|
|||||||
assert {"progress_value": 0.0, "course": course} in response
|
assert {"progress_value": 0.0, "course": course} in response
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_course_progress_value_without_auth_should_fail():
|
||||||
|
"""Test whether fetching a course progress value without authentication fails"""
|
||||||
|
clear_db()
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for course in CourseEnum:
|
||||||
|
response = client.get(f"/courseprogress/{course}", headers=headers)
|
||||||
|
|
||||||
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_nonexisting_course_should_fail():
|
async def test_get_nonexisting_course_should_fail():
|
||||||
"""Test whether fetching the progress of a nonexisting course fails"""
|
"""Test whether fetching the progress of a nonexisting course fails"""
|
||||||
@@ -178,3 +181,20 @@ async def test_patch_course_with_invalid_value_should_fail():
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert response.status_code == 400
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_patch_course_progress_value_without_auth_should_fail():
|
||||||
|
"""Test whether updating a course progress value without authentication fails"""
|
||||||
|
clear_db()
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for course in CourseEnum:
|
||||||
|
response = client.patch(
|
||||||
|
f"/courseprogress/{course}",
|
||||||
|
headers=headers,
|
||||||
|
json={"progress_value": random.uniform(0, 1)},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 403
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
import sys
|
import random
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
sys.path.append("..")
|
from src.enums import MinigameEnum
|
||||||
|
|
||||||
from src.main import app, get_db
|
from src.main import app, get_db
|
||||||
|
from tests.base import avatar, client, password, username
|
||||||
from tests.config.database import clear_db, override_get_db
|
from tests.config.database import clear_db, override_get_db
|
||||||
|
|
||||||
app.dependency_overrides[get_db] = override_get_db
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
username = "user1"
|
|
||||||
password = "password"
|
|
||||||
avatar = "lion"
|
|
||||||
|
|
||||||
|
|
||||||
async def register_user():
|
async def register_user():
|
||||||
response = client.post(
|
response = client.post(
|
||||||
@@ -30,6 +22,218 @@ async def register_user():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_post_highscore():
|
async def test_put_highscore():
|
||||||
"""Test whether posting a new high score succeeds"""
|
"""Test whether putting a new high score succeeds"""
|
||||||
clear_db()
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
score_value = random.random()
|
||||||
|
response = client.put(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
json={"score_value": score_value},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = response.json()
|
||||||
|
|
||||||
|
assert response["minigame"] == minigame
|
||||||
|
assert response["score_value"] == score_value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_put_lower_highscore_does_not_change_old_value():
|
||||||
|
"""Test whether putting a new high score lower than the current one doesn't change the old one"""
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
score_value = random.random()
|
||||||
|
response = client.put(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
json={"score_value": score_value},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = response.json()
|
||||||
|
|
||||||
|
assert response["minigame"] == minigame
|
||||||
|
assert response["score_value"] == score_value
|
||||||
|
|
||||||
|
lower_score_value = score_value - 100
|
||||||
|
response = client.put(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
json={"score_value": lower_score_value},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = response.json()
|
||||||
|
|
||||||
|
assert response["minigame"] == minigame
|
||||||
|
assert response["score_value"] == score_value
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_put_highscore_for_nonexisting_minigame_should_fail():
|
||||||
|
"""Test whether putting a new high score for a nonexisting minigame fails"""
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
fake_minigame = "FakeGame"
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
|
||||||
|
response = client.put(
|
||||||
|
f"/highscores/{fake_minigame}",
|
||||||
|
headers=headers,
|
||||||
|
json={"score_value": random.random()},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 422
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_put_highscores_without_auth_should_fail():
|
||||||
|
"""Test whether putting high scores without authentication fails"""
|
||||||
|
clear_db()
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
response = client.put(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
json={"score_value": random.random()},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_highscores_without_auth_should_fail():
|
||||||
|
"""Test whether fetching high scores without authentication fails"""
|
||||||
|
clear_db()
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_highscore_for_nonexisting_minigame_should_fail():
|
||||||
|
"""Test whether fetching a new high score for a nonexisting minigame fails"""
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
fake_minigame = "FakeGame"
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{fake_minigame}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 422
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_invalid_number_of_highscores_should_fail():
|
||||||
|
"""Test whether getting a numbe rof high scores lower than 1 fails"""
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{minigame}?nr_highest={random.randint(-100, 0)}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_highscores_should_work_with_default_value():
|
||||||
|
"""Test whether fetching high scores without passing an explicit amount still succeeds"""
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_highscores_returns_sorted_list_with_correct_length():
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
|
for minigame in MinigameEnum:
|
||||||
|
clear_db()
|
||||||
|
nr_entries = random.randint(5, 50)
|
||||||
|
|
||||||
|
users_score_tuples = [
|
||||||
|
(f"user{i + 1}", random.random()) for i in range(nr_entries)
|
||||||
|
]
|
||||||
|
|
||||||
|
for user, score in users_score_tuples:
|
||||||
|
response = client.post(
|
||||||
|
"/register",
|
||||||
|
headers=headers,
|
||||||
|
json={"username": user, "password": password, "avatar": avatar},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
token = response.json()["access_token"]
|
||||||
|
|
||||||
|
response = client.put(
|
||||||
|
f"/highscores/{minigame}?nr_highest={random.randint(1, nr_entries)}",
|
||||||
|
headers={
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
json={"score_value": score},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers={
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
response = response.json()
|
||||||
|
|
||||||
|
for i in range(1, len(response)):
|
||||||
|
assert response[i]["score_value"] <= response[i - 1]["score_value"]
|
||||||
|
|||||||
@@ -1,21 +1,10 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from fastapi.testclient import TestClient
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
sys.path.append("..")
|
|
||||||
|
|
||||||
from src.main import app, get_db
|
from src.main import app, get_db
|
||||||
|
from tests.base import avatar, client, password, username
|
||||||
from tests.config.database import clear_db, override_get_db
|
from tests.config.database import clear_db, override_get_db
|
||||||
|
|
||||||
app.dependency_overrides[get_db] = override_get_db
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
username = "user1"
|
|
||||||
password = "password"
|
|
||||||
avatar = "lion"
|
|
||||||
|
|
||||||
patched_username = "New name"
|
patched_username = "New name"
|
||||||
patched_password = "New password"
|
patched_password = "New password"
|
||||||
patched_avatar = "New avatar"
|
patched_avatar = "New avatar"
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import pytest
|
|
||||||
from fastapi.testclient import TestClient
|
|
||||||
|
|
||||||
from main import app
|
|
||||||
|
|
||||||
client = TestClient(app)
|
|
||||||
|
|
||||||
|
|
||||||
def test_add_user():
|
|
||||||
response = client.post(
|
|
||||||
"/users",
|
|
||||||
headers={"Content-Type": "application/json"},
|
|
||||||
json={"username": "Lukas", "password": "mettn"},
|
|
||||||
)
|
|
||||||
assert response.status_code == 200
|
|
||||||
Reference in New Issue
Block a user