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()
)
if high_score:
print(str(high_score.time))
return [
Score(
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
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(
db: Session, user: User, course: CourseEnum, learnable: SavedLearnableProgress
):
"""Create a new learnable"""
"""Create a new learnable for a given course"""
if learnable.index < 0:
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}")
async def create_learnable(
course: CourseEnum,

View File

@@ -16,10 +16,17 @@ password = "password"
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():
response = client.post(
"/register",
headers={"Content-Type": "application/json"},
headers=get_headers(),
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 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"
@@ -17,6 +17,7 @@ def clear_db():
db = TestSessionLocal()
db.query(HighScore).delete()
db.query(LearnableProgress).delete()
db.query(CourseProgress).delete()
db.query(User).delete()
db.commit()

View File

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

View File

@@ -3,17 +3,17 @@ import random
import pytest
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
@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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for course in CourseEnum:
if course != CourseEnum.All:
@@ -27,12 +27,12 @@ async def test_register_creates_progress_of_zero():
@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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
response = client.get("/courseprogress/All", headers=headers)
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"""
clear_db()
headers = {"Content-Type": "application/json"}
headers = get_headers()
for course in CourseEnum:
response = client.get(f"/courseprogress/{course}", headers=headers)
@@ -64,19 +64,19 @@ async def test_get_nonexisting_course_should_fail():
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)
assert response.status_code == 422
@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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for course in CourseEnum:
if course != CourseEnum.All:
@@ -98,7 +98,7 @@ async def test_patch_all_should_patch_all_courses():
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
progress = random.uniform(0, 1)
@@ -128,7 +128,7 @@ async def test_patch_nonexisting_course_should_fail():
fake_course = "FakeCourse"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
progress = random.uniform(0, 1)
@@ -147,7 +147,7 @@ async def test_patch_course_with_invalid_value_should_fail():
clear_db()
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_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"""
clear_db()
headers = {"Content-Type": "application/json"}
headers = get_headers()
for course in CourseEnum:
response = client.patch(

View File

@@ -3,17 +3,18 @@ import random
import pytest
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
@pytest.mark.asyncio
async def test_put_highscore():
async def test_put_highscore_should_succeed():
"""Test whether putting a new high score succeeds"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
score_value = random.random()
@@ -31,12 +32,12 @@ async def test_put_highscore():
@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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
score_value = random.random()
@@ -74,7 +75,7 @@ async def test_put_highscore_for_nonexisting_minigame_should_fail():
fake_minigame = "FakeGame"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
response = client.put(
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"""
clear_db()
headers = {"Content-Type": "application/json"}
headers = get_headers()
for minigame in MinigameEnum:
response = client.put(
@@ -107,7 +108,7 @@ async def test_get_highscores_without_auth_should_fail():
"""Test whether fetching high scores without authentication fails"""
clear_db()
headers = {"Content-Type": "application/json"}
headers = get_headers()
for minigame in MinigameEnum:
response = client.get(
@@ -133,7 +134,7 @@ async def test_get_highscore_for_nonexisting_minigame_should_fail():
fake_minigame = "FakeGame"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
response = client.get(
f"/highscores/{fake_minigame}",
@@ -156,7 +157,7 @@ async def test_get_invalid_number_of_highscores_should_fail():
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
response = client.get(
@@ -168,12 +169,12 @@ async def test_get_invalid_number_of_highscores_should_fail():
@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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
response = client.get(
@@ -185,16 +186,16 @@ async def test_get_highscores_should_work_with_default_value():
@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"""
clear_db()
token = await register_user()
headers = {"Content-Type": "application/json"}
headers = get_headers()
for minigame in MinigameEnum:
clear_db()
nr_entries = random.randint(5, 50)
nr_entries = random.randint(5, 10)
token = ""
users_score_tuples = [
@@ -218,10 +219,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
response = client.put(
f"/highscores/{minigame}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
headers=get_headers(token),
json={"score_value": score},
)
@@ -229,10 +227,7 @@ async def test_get_highscores_returns_sorted_list_with_correct_length():
response = client.get(
f"/highscores/{minigame}?mine_only=false&amount={int(nr_entries)}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
headers=get_headers(token),
)
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)):
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
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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
response = client.put(
@@ -276,7 +284,7 @@ async def test_get_own_nonexisting_high_score_should_return_empty_list():
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
response = client.get(
@@ -294,7 +302,7 @@ async def test_get_multiple_own_high_scores_of_same_game_should_fail():
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
for minigame in MinigameEnum:
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
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
patched_username = "New name"
@@ -9,13 +10,13 @@ patched_avatar_index = 2
@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"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
response = client.patch(
"/users",
@@ -30,14 +31,14 @@ async def test_patch_user():
response = client.post(
"/login",
headers={"Content-Type": "application/json"},
headers=get_headers(),
json={"username": patched_username, "password": patched_password},
)
assert response.status_code == 200
token = response.json()["access_token"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
response = client.get("/saveddata", headers=headers)
assert response.status_code == 200
@@ -47,13 +48,13 @@ async def test_patch_user():
@pytest.mark.asyncio
async def test_patch_user_with_empty_fields():
"""Patching a user with empty fields should fail"""
async def test_patch_user_with_empty_fields_should_succeed():
"""Patching a user with empty fields should still succeed"""
clear_db()
token = await register_user()
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
headers = get_headers(token)
response = client.patch(
"/users",