More highscore endpoint functionality & tests
This commit is contained in:
@@ -7,20 +7,41 @@ from src.models import HighScore, User
|
|||||||
from src.schemas.highscores import HighScoreBase
|
from src.schemas.highscores import HighScoreBase
|
||||||
from src.schemas.users import UserHighScore
|
from src.schemas.users import UserHighScore
|
||||||
|
|
||||||
DEFAULT_NR_HIGH_SCORES = 10
|
|
||||||
|
|
||||||
|
def get_high_scores(
|
||||||
def get_high_scores(db: Session, minigame: MinigameEnum, nr_highest: int):
|
db: Session, minigame: MinigameEnum, user: User, nr_highest: int, mine_only: bool
|
||||||
|
):
|
||||||
"""Get the n highest scores of a given minigame"""
|
"""Get the n highest scores of a given minigame"""
|
||||||
if nr_highest:
|
if nr_highest < 1:
|
||||||
if nr_highest < 1:
|
raise HTTPException(status_code=400, detail="Invalid number of high scores")
|
||||||
raise HTTPException(status_code=400, detail="Invalid number of high scores")
|
|
||||||
|
if mine_only:
|
||||||
|
if nr_highest > 1:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=400,
|
||||||
|
detail="nr_highest should be 1 when requesting high score of current user only",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
high_score = (
|
||||||
|
db.query(HighScore)
|
||||||
|
.filter(
|
||||||
|
HighScore.minigame == minigame, HighScore.owner_id == user.user_id
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if high_score:
|
||||||
|
return [
|
||||||
|
UserHighScore(
|
||||||
|
username=user.username,
|
||||||
|
score_value=high_score.score_value,
|
||||||
|
avatar=user.avatar,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
user_high_scores = []
|
user_high_scores = []
|
||||||
|
|
||||||
if not nr_highest:
|
|
||||||
nr_highest = DEFAULT_NR_HIGH_SCORES
|
|
||||||
|
|
||||||
if not minigame:
|
if not minigame:
|
||||||
minigame = MinigameEnum.SpellingBee
|
minigame = MinigameEnum.SpellingBee
|
||||||
|
|
||||||
|
|||||||
18
src/main.py
18
src/main.py
@@ -64,11 +64,15 @@ async def login(user: users.UserCreate, db: Session = Depends(get_db)):
|
|||||||
@app.get("/highscores/{minigame}", response_model=List[users.UserHighScore])
|
@app.get("/highscores/{minigame}", response_model=List[users.UserHighScore])
|
||||||
async def get_high_scores(
|
async def get_high_scores(
|
||||||
minigame: MinigameEnum,
|
minigame: MinigameEnum,
|
||||||
nr_highest: Optional[int] = None,
|
nr_highest: Optional[int] = 1,
|
||||||
|
mine_only: Optional[bool] = True,
|
||||||
current_user_name: str = 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),
|
||||||
):
|
):
|
||||||
return crud_highscores.get_high_scores(db, minigame, nr_highest)
|
print(str(nr_highest))
|
||||||
|
print(str(mine_only))
|
||||||
|
user = crud_users.get_user_by_username(db, current_user_name)
|
||||||
|
return crud_highscores.get_high_scores(db, minigame, user, nr_highest, mine_only)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/highscores/{minigame}", response_model=highscores.HighScore)
|
@app.put("/highscores/{minigame}", response_model=highscores.HighScore)
|
||||||
@@ -107,13 +111,3 @@ async def patch_course_progress(
|
|||||||
return crud_courseprogress.patch_course_progress(
|
return crud_courseprogress.patch_course_progress(
|
||||||
db, current_user, course, course_progress
|
db, current_user, course, course_progress
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#### TESTING!! DELETE LATER
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/protected")
|
|
||||||
async def protected_route(
|
|
||||||
current_user_name: str = Depends(crud_authentication.get_current_user_name),
|
|
||||||
):
|
|
||||||
return {"message": f"Hello, {current_user_name}!"}
|
|
||||||
|
|||||||
@@ -134,6 +134,13 @@ async def test_get_highscores_without_auth_should_fail():
|
|||||||
|
|
||||||
assert response.status_code == 403
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{minigame}?mine_only=false&nr_highest={random.randint(1, 50)}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_highscore_for_nonexisting_minigame_should_fail():
|
async def test_get_highscore_for_nonexisting_minigame_should_fail():
|
||||||
@@ -152,6 +159,13 @@ async def test_get_highscore_for_nonexisting_minigame_should_fail():
|
|||||||
|
|
||||||
assert response.status_code == 422
|
assert response.status_code == 422
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{fake_minigame}?mine_only=false&nr_highest={random.randint(1, 50)}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 422
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_invalid_number_of_highscores_should_fail():
|
async def test_get_invalid_number_of_highscores_should_fail():
|
||||||
@@ -189,6 +203,7 @@ async def test_get_highscores_should_work_with_default_value():
|
|||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_get_highscores_returns_sorted_list_with_correct_length():
|
async def test_get_highscores_returns_sorted_list_with_correct_length():
|
||||||
|
"""Test whether getting a list of high scores gets a list in descending order and of the correct length"""
|
||||||
clear_db()
|
clear_db()
|
||||||
token = await register_user()
|
token = await register_user()
|
||||||
|
|
||||||
@@ -197,6 +212,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
|
|||||||
for minigame in MinigameEnum:
|
for minigame in MinigameEnum:
|
||||||
clear_db()
|
clear_db()
|
||||||
nr_entries = random.randint(5, 50)
|
nr_entries = random.randint(5, 50)
|
||||||
|
token = ""
|
||||||
|
|
||||||
users_score_tuples = [
|
users_score_tuples = [
|
||||||
(f"user{i + 1}", random.random()) for i in range(nr_entries)
|
(f"user{i + 1}", random.random()) for i in range(nr_entries)
|
||||||
@@ -214,7 +230,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
|
|||||||
token = response.json()["access_token"]
|
token = response.json()["access_token"]
|
||||||
|
|
||||||
response = client.put(
|
response = client.put(
|
||||||
f"/highscores/{minigame}?nr_highest={random.randint(1, nr_entries)}",
|
f"/highscores/{minigame}",
|
||||||
headers={
|
headers={
|
||||||
"Authorization": f"Bearer {token}",
|
"Authorization": f"Bearer {token}",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -225,7 +241,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
f"/highscores/{minigame}",
|
f"/highscores/{minigame}?mine_only=false&nr_highest={int(nr_entries)}",
|
||||||
headers={
|
headers={
|
||||||
"Authorization": f"Bearer {token}",
|
"Authorization": f"Bearer {token}",
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -235,5 +251,68 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
|
|||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
response = response.json()
|
response = response.json()
|
||||||
|
|
||||||
|
assert len(response) == nr_entries
|
||||||
|
|
||||||
for i in range(1, len(response)):
|
for i in range(1, len(response)):
|
||||||
assert response[i]["score_value"] <= response[i - 1]["score_value"]
|
assert response[i]["score_value"] <= response[i - 1]["score_value"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_own_existing_high_score_should_return_high_score():
|
||||||
|
"""Test whether fetching your own high score of a game succeeds"""
|
||||||
|
clear_db()
|
||||||
|
token = await register_user()
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}", "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 == 200
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/highscores/{minigame}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(response.json()) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_own_nonexisting_high_score_should_return_empty_list():
|
||||||
|
"""Test whether fetching the high score of a game you haven't played returns an empty list"""
|
||||||
|
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
|
||||||
|
assert len(response.json()) == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_get_multiple_own_high_scores_of_same_game_should_fail():
|
||||||
|
"""Test whether asking more than one of your high scores on a single game 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(2, 20)}",
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 400
|
||||||
|
|||||||
Reference in New Issue
Block a user