More refactoring

This commit is contained in:
lvrossem
2023-04-18 02:52:26 -06:00
parent d074074b03
commit 3968dfd4eb
10 changed files with 156 additions and 64 deletions

View File

@@ -53,7 +53,6 @@ def get_highest_high_scores(
.first() .first()
) )
if high_score: if high_score:
print(str(high_score.time))
return [ return [
Score( Score(
score_value=high_score.score_value, score_value=high_score.score_value,

View File

@@ -6,10 +6,33 @@ from src.models import CourseProgress, LearnableProgress, User
from src.schemas.learnableprogress import SavedLearnableProgress from src.schemas.learnableprogress import SavedLearnableProgress
def get_learnables(db: Session, user: User, course: CourseEnum):
"""Get all learnables of a certain course"""
db_course = (
db.query(CourseProgress)
.filter(
CourseProgress.owner_id == user.user_id, CourseProgress.course == course
)
.first()
)
db_learnable_query = (
db.query(LearnableProgress)
.filter(LearnableProgress.course_progress_id == db_course.course_progress_id)
.all()
)
return [
SavedLearnableProgress(
index=dbl.index, in_use=dbl.in_use, name=dbl.name, progress=dbl.progress
)
for dbl in db_learnable_query
]
def create_learnable( def create_learnable(
db: Session, user: User, course: CourseEnum, learnable: SavedLearnableProgress db: Session, user: User, course: CourseEnum, learnable: SavedLearnableProgress
): ):
"""Create a new learnable""" """Create a new learnable for a given course"""
if learnable.index < 0: if learnable.index < 0:
raise HTTPException(status_code=400, detail="Negative index not allowed") raise HTTPException(status_code=400, detail="Negative index not allowed")

View File

@@ -128,6 +128,19 @@ async def patch_course_progress(
) )
@app.get(
"/learnables/{course}",
response_model=List[learnableprogress.SavedLearnableProgress],
)
async def create_learnable(
course: CourseEnum,
current_user_name: str = Depends(crud_authentication.get_current_user_name),
db: Session = Depends(get_db),
):
current_user = crud_users.get_user_by_username(db, current_user_name)
return crud_learnables.get_learnables(db, current_user, course)
@app.post("/learnables/{course}") @app.post("/learnables/{course}")
async def create_learnable( async def create_learnable(
course: CourseEnum, course: CourseEnum,

View File

@@ -16,10 +16,17 @@ password = "password"
avatar_index = 1 avatar_index = 1
def get_headers(token=None):
if token:
return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
else:
return {"Content-Type": "application/json"}
async def register_user(): async def register_user():
response = client.post( response = client.post(
"/register", "/register",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "password": password, "avatar_index": avatar_index}, json={"username": username, "password": password, "avatar_index": avatar_index},
) )

View File

@@ -2,7 +2,7 @@ from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from src.database import Base from src.database import Base
from src.models import CourseProgress, HighScore, User from src.models import CourseProgress, HighScore, LearnableProgress, User
SQLALCHEMY_DATABASE_URL = "postgresql://admin:WeSign123!@localhost/wesigntest" SQLALCHEMY_DATABASE_URL = "postgresql://admin:WeSign123!@localhost/wesigntest"
@@ -17,6 +17,7 @@ def clear_db():
db = TestSessionLocal() db = TestSessionLocal()
db.query(HighScore).delete() db.query(HighScore).delete()
db.query(LearnableProgress).delete()
db.query(CourseProgress).delete() db.query(CourseProgress).delete()
db.query(User).delete() db.query(User).delete()
db.commit() db.commit()

View File

@@ -1,17 +1,18 @@
import pytest import pytest
from tests.base import avatar_index, client, password, register_user, username from tests.base import (avatar_index, client, get_headers, password,
register_user, username)
from tests.config.database import clear_db from tests.config.database import clear_db
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_register(): async def test_register_should_succeed():
"""Test the register endpoint""" """Test the register endpoint"""
clear_db() clear_db()
response = client.post( response = client.post(
"/register", "/register",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "password": password, "avatar_index": avatar_index}, json={"username": username, "password": password, "avatar_index": avatar_index},
) )
@@ -27,7 +28,7 @@ async def test_register_duplicate_name_should_fail():
response = client.post( response = client.post(
"/register", "/register",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "password": password, "avatar_index": avatar_index}, json={"username": username, "password": password, "avatar_index": avatar_index},
) )
@@ -42,7 +43,7 @@ async def test_register_without_username_should_fail():
response = client.post( response = client.post(
"/register", "/register",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"password": password, "avatar_index": avatar_index}, json={"password": password, "avatar_index": avatar_index},
) )
@@ -57,7 +58,7 @@ async def test_register_without_password_should_fail():
response = client.post( response = client.post(
"/register", "/register",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "avatar_index": avatar_index}, json={"username": username, "avatar_index": avatar_index},
) )
@@ -72,7 +73,7 @@ async def test_register_without_avatar_should_fail():
response = client.post( response = client.post(
"/register", "/register",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "password": password}, json={"username": username, "password": password},
) )
@@ -81,14 +82,14 @@ async def test_register_without_avatar_should_fail():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_login(): async def test_login_should_succeed():
"""Test the login endpoint""" """Test the login endpoint"""
clear_db() clear_db()
await register_user() await register_user()
response = client.post( response = client.post(
"/login", "/login",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "password": password}, json={"username": username, "password": password},
) )
@@ -104,7 +105,7 @@ async def test_login_wrong_password_should_fail():
wrong_password = password + "extra characters" wrong_password = password + "extra characters"
response = client.post( response = client.post(
"/login", "/login",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username, "password": wrong_password}, json={"username": username, "password": wrong_password},
) )
@@ -120,7 +121,7 @@ async def test_login_without_username_should_fail():
response = client.post( response = client.post(
"/login", "/login",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"password": password}, json={"password": password},
) )
@@ -136,7 +137,7 @@ async def test_login_without_password_should_fail():
response = client.post( response = client.post(
"/login", "/login",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": username}, json={"username": username},
) )

View File

@@ -3,17 +3,17 @@ import random
import pytest import pytest
from src.enums import CourseEnum from src.enums import CourseEnum
from tests.base import client, register_user from tests.base import client, get_headers, register_user
from tests.config.database import clear_db from tests.config.database import clear_db
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_register_creates_progress_of_zero(): async def test_register_should_create_progress_of_zero():
"""Test whether registering a new user initializes all progress values to 0.0""" """Test whether registering a new user initializes all progress values to 0.0"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for course in CourseEnum: for course in CourseEnum:
if course != CourseEnum.All: if course != CourseEnum.All:
@@ -27,12 +27,12 @@ async def test_register_creates_progress_of_zero():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_all_returns_all(): async def test_get_all_sould_return_all():
"""Test whether the 'All'-course fetches all course progress values""" """Test whether the 'All'-course fetches all course progress values"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.get("/courseprogress/All", headers=headers) response = client.get("/courseprogress/All", headers=headers)
assert response.status_code == 200 assert response.status_code == 200
@@ -48,7 +48,7 @@ async def test_get_course_progress_without_auth_should_fail():
"""Test whether fetching a course progress value without authentication fails""" """Test whether fetching a course progress value without authentication fails"""
clear_db() clear_db()
headers = {"Content-Type": "application/json"} headers = get_headers()
for course in CourseEnum: for course in CourseEnum:
response = client.get(f"/courseprogress/{course}", headers=headers) response = client.get(f"/courseprogress/{course}", headers=headers)
@@ -64,19 +64,19 @@ async def test_get_nonexisting_course_should_fail():
fake_course = "FakeCourse" fake_course = "FakeCourse"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.get(f"/courseprogress/{fake_course}", headers=headers) response = client.get(f"/courseprogress/{fake_course}", headers=headers)
assert response.status_code == 422 assert response.status_code == 422
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_patch_course_progress(): async def test_patch_course_progress_should_succeed():
"""Test whether patching the progress value of a course works properly""" """Test whether patching the progress value of a course works properly"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for course in CourseEnum: for course in CourseEnum:
if course != CourseEnum.All: if course != CourseEnum.All:
@@ -98,7 +98,7 @@ async def test_patch_all_should_patch_all_courses():
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
progress = random.uniform(0, 1) progress = random.uniform(0, 1)
@@ -128,7 +128,7 @@ async def test_patch_nonexisting_course_should_fail():
fake_course = "FakeCourse" fake_course = "FakeCourse"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
progress = random.uniform(0, 1) progress = random.uniform(0, 1)
@@ -147,7 +147,7 @@ async def test_patch_course_with_invalid_value_should_fail():
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
too_high_progress = random.uniform(0, 1) + 2 too_high_progress = random.uniform(0, 1) + 2
too_low_progress = random.uniform(0, 1) - 2 too_low_progress = random.uniform(0, 1) - 2
@@ -174,7 +174,7 @@ async def test_patch_course_progress_without_auth_should_fail():
"""Test whether updating a course progress value without authentication fails""" """Test whether updating a course progress value without authentication fails"""
clear_db() clear_db()
headers = {"Content-Type": "application/json"} headers = get_headers()
for course in CourseEnum: for course in CourseEnum:
response = client.patch( response = client.patch(

View File

@@ -3,17 +3,18 @@ import random
import pytest import pytest
from src.enums import MinigameEnum from src.enums import MinigameEnum
from tests.base import avatar_index, client, password, register_user from tests.base import (avatar_index, client, get_headers, password,
register_user)
from tests.config.database import clear_db from tests.config.database import clear_db
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_put_highscore(): async def test_put_highscore_should_succeed():
"""Test whether putting a new high score succeeds""" """Test whether putting a new high score succeeds"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
score_value = random.random() score_value = random.random()
@@ -31,12 +32,12 @@ async def test_put_highscore():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_put_lower_highscore_does_not_change_old_value(): async def test_put_lower_highscore_should_not_change_old_value():
"""Test whether putting a new high score lower than the current one doesn't change the old one""" """Test whether putting a new high score lower than the current one doesn't change the old one"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
score_value = random.random() score_value = random.random()
@@ -74,7 +75,7 @@ async def test_put_highscore_for_nonexisting_minigame_should_fail():
fake_minigame = "FakeGame" fake_minigame = "FakeGame"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.put( response = client.put(
f"/highscores/{fake_minigame}", f"/highscores/{fake_minigame}",
@@ -90,7 +91,7 @@ async def test_put_highscores_without_auth_should_fail():
"""Test whether putting high scores without authentication fails""" """Test whether putting high scores without authentication fails"""
clear_db() clear_db()
headers = {"Content-Type": "application/json"} headers = get_headers()
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.put( response = client.put(
@@ -107,7 +108,7 @@ async def test_get_highscores_without_auth_should_fail():
"""Test whether fetching high scores without authentication fails""" """Test whether fetching high scores without authentication fails"""
clear_db() clear_db()
headers = {"Content-Type": "application/json"} headers = get_headers()
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.get( response = client.get(
@@ -133,7 +134,7 @@ async def test_get_highscore_for_nonexisting_minigame_should_fail():
fake_minigame = "FakeGame" fake_minigame = "FakeGame"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.get( response = client.get(
f"/highscores/{fake_minigame}", f"/highscores/{fake_minigame}",
@@ -156,7 +157,7 @@ async def test_get_invalid_number_of_highscores_should_fail():
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.get( response = client.get(
@@ -168,12 +169,12 @@ async def test_get_invalid_number_of_highscores_should_fail():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_highscores_should_work_with_default_value(): async def test_get_highscores_should_succeed_with_default_value():
"""Test whether fetching high scores without passing an explicit amount still succeeds""" """Test whether fetching high scores without passing an explicit amount still succeeds"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.get( response = client.get(
@@ -185,16 +186,16 @@ 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_should_return_sorted_list_with_correct_length():
"""Test whether getting a list of high scores gets a list in descending order and of the 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()
headers = {"Content-Type": "application/json"} headers = get_headers()
for minigame in MinigameEnum: for minigame in MinigameEnum:
clear_db() clear_db()
nr_entries = random.randint(5, 50) nr_entries = random.randint(5, 10)
token = "" token = ""
users_score_tuples = [ users_score_tuples = [
@@ -218,10 +219,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
response = client.put( response = client.put(
f"/highscores/{minigame}", f"/highscores/{minigame}",
headers={ headers=get_headers(token),
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
json={"score_value": score}, json={"score_value": score},
) )
@@ -229,10 +227,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
response = client.get( response = client.get(
f"/highscores/{minigame}?mine_only=false&amount={int(nr_entries)}", f"/highscores/{minigame}?mine_only=false&amount={int(nr_entries)}",
headers={ headers=get_headers(token),
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
) )
assert response.status_code == 200 assert response.status_code == 200
@@ -243,14 +238,27 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
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"]
response = client.get(
f"/highscores/{minigame}?most_recent=true&mine_only=false&amount={int(nr_entries)}",
headers=get_headers(token),
)
assert response.status_code == 200
response = response.json()
assert len(response) == nr_entries
for i in range(1, len(response)):
assert response[i]["time"] <= response[i - 1]["time"]
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_own_existing_high_score_should_return_high_score(): async def test_get_own_existing_high_score_should_succeed():
"""Test whether fetching your own high score of a game succeeds""" """Test whether fetching your own high score of a game succeeds"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.put( response = client.put(
@@ -276,7 +284,7 @@ async def test_get_own_nonexisting_high_score_should_return_empty_list():
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.get( response = client.get(
@@ -294,7 +302,7 @@ async def test_get_multiple_own_high_scores_of_same_game_should_fail():
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
for minigame in MinigameEnum: for minigame in MinigameEnum:
response = client.get( response = client.get(

39
tests/test_learnables.py Normal file
View File

@@ -0,0 +1,39 @@
import random
import pytest
from src.enums import CourseEnum
from tests.base import client, get_headers, register_user
from tests.config.database import clear_db
@pytest.mark.asyncio
async def test_create_learnables_should_succeed():
clear_db()
token = await register_user()
headers = get_headers(token)
for course in CourseEnum:
if course != CourseEnum.All:
nr_learnables = random.randint(1, 5)
for i in range(nr_learnables):
response = client.post(
f"/learnables/{course}",
json={
"index": i,
"in_use": bool(random.randint(0, 1)),
"name": f"{course} {i}",
},
headers=headers,
)
assert response.status_code == 200
response = client.get(f"/learnables/{course}", headers=headers)
assert response.status_code == 200
response = response.json()
assert len(response) == nr_learnables

View File

@@ -1,6 +1,7 @@
import pytest import pytest
from tests.base import avatar_index, client, register_user, username from tests.base import (avatar_index, client, get_headers, register_user,
username)
from tests.config.database import clear_db from tests.config.database import clear_db
patched_username = "New name" patched_username = "New name"
@@ -9,13 +10,13 @@ patched_avatar_index = 2
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_patch_user(): async def test_patch_user_should_succeed():
"""Test the patching of a user's username, password and avatar""" """Test the patching of a user's username, password and avatar"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.patch( response = client.patch(
"/users", "/users",
@@ -30,14 +31,14 @@ async def test_patch_user():
response = client.post( response = client.post(
"/login", "/login",
headers={"Content-Type": "application/json"}, headers=get_headers(),
json={"username": patched_username, "password": patched_password}, json={"username": patched_username, "password": patched_password},
) )
assert response.status_code == 200 assert response.status_code == 200
token = response.json()["access_token"] token = response.json()["access_token"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.get("/saveddata", headers=headers) response = client.get("/saveddata", headers=headers)
assert response.status_code == 200 assert response.status_code == 200
@@ -47,13 +48,13 @@ async def test_patch_user():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_patch_user_with_empty_fields(): async def test_patch_user_with_empty_fields_should_succeed():
"""Patching a user with empty fields should fail""" """Patching a user with empty fields should still succeed"""
clear_db() clear_db()
token = await register_user() token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"} headers = get_headers(token)
response = client.patch( response = client.patch(
"/users", "/users",