import random import pytest from fastapi.testclient import TestClient from src.enums import MinigameEnum 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 async def register_user(): response = client.post( "/register", headers={"Content-Type": "application/json"}, json={"username": username, "password": password, "avatar": avatar}, ) assert response.status_code == 200 return response.json()["access_token"] @pytest.mark.asyncio async def test_put_highscore(): """Test whether putting a new high score succeeds""" 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"]