156 lines
6.2 KiB
Python
156 lines
6.2 KiB
Python
from typing import Mapping
|
|
|
|
import httpx
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app import app
|
|
|
|
client = TestClient(app)
|
|
|
|
# These tests run in a clean database.
|
|
# Note, however, that they do not _each_ run in a clean database - it persists between executions.
|
|
# Note the use of `cleanups` (defined in `conftest.py`) to allow for cleanup operations that should leave the database
|
|
# in a clean state after each test - but also, note the comment above the commented-out
|
|
# `test_adding_games_with_ties`
|
|
|
|
|
|
def test_add_and_retrieve_player(test_client: TestClient, cleanups):
|
|
response = _json_get(test_client, "/player/1")
|
|
assert response.status_code == 404
|
|
|
|
create_player_response = _json_post(client, "/player", {"name": "jason"})
|
|
assert create_player_response.status_code == 201
|
|
|
|
response_1 = _json_get(client, "/player/1")
|
|
assert response_1.json()["name"] == "jason"
|
|
|
|
def cleanup():
|
|
delete_response = _json_delete(client, "/player/1")
|
|
assert delete_response.status_code == 204
|
|
|
|
cleanups.add_success(cleanup)
|
|
|
|
|
|
def test_add_and_retrieve_deck(test_client: TestClient, cleanups):
|
|
not_found_response = _json_get(test_client, "/deck/1")
|
|
assert not_found_response.status_code == 404
|
|
|
|
# Try (and fail) to create a deck owned by a non-existent player
|
|
invalid_owner_response = _json_post(
|
|
test_client, "/deck", {"name": "Baby's First Deck", "owner_id": 1}
|
|
)
|
|
assert invalid_owner_response.status_code == 400
|
|
assert invalid_owner_response.json()["detail"] == "Owner id 1 not found"
|
|
|
|
create_jim_response = _json_post(test_client, "/player", {"name": "jim"})
|
|
assert create_jim_response.status_code == 201
|
|
jim_id = create_jim_response.json()["id"]
|
|
|
|
create_deck_response = _json_post(
|
|
test_client, "/deck", {"name": "Baby's First Deck", "owner_id": str(jim_id)}
|
|
)
|
|
assert create_deck_response.status_code == 201
|
|
# _Should_ always be 1, since we expect to start with an empty database, but why risk it?
|
|
deck_id = create_deck_response.json()["id"]
|
|
|
|
get_deck_response = _json_get(test_client, f"/deck/{deck_id}")
|
|
assert get_deck_response.status_code == 200
|
|
assert get_deck_response.json()["name"] == "Baby's First Deck"
|
|
|
|
# Very basic HTML testing
|
|
html_response = test_client.get(f"/deck/{deck_id}")
|
|
assert """owned by <a href="/player/1">jim</a>""" in html_response.text
|
|
|
|
def success_cleanup():
|
|
delete_response = _json_delete(test_client, f"/deck/{deck_id}")
|
|
assert delete_response.status_code == 204
|
|
|
|
cleanups.add_success(success_cleanup)
|
|
|
|
|
|
def test_incremental_add_of_games(test_client: TestClient, cleanups):
|
|
latest_game_response = _json_get(test_client, "/game/latest_game")
|
|
assert latest_game_response.status_code == 404
|
|
|
|
# https://github.com/tiangolo/fastapi/issues/1536#issuecomment-640781718
|
|
with open("seed-data/all-in-one.csv", "rb") as f:
|
|
test_client.post(
|
|
"/api/seed/all_in_one",
|
|
files={"file": ("fake_all_in_one_filename.csv", f, "text/csv")},
|
|
)
|
|
|
|
latest_game_response = _json_get(test_client, "/game/latest_game")
|
|
assert latest_game_response.status_code == 200
|
|
print(latest_game_response.json())
|
|
assert latest_game_response.json()["date"] == "2024-07-05T00:00:00"
|
|
|
|
# then seed again, and check that it successfully gets the expected latest
|
|
with open(
|
|
"seed-data/all-in-one-updated-for-incremental-add-testing.csv", "rb"
|
|
) as f:
|
|
test_client.post(
|
|
"/api/seed/all_in_one",
|
|
files={"file": ("fake_all_in_one_filename.csv", f, "text/csv")},
|
|
)
|
|
|
|
latest_deck_response = _json_get(test_client, "/game/latest_game")
|
|
assert latest_deck_response.status_code == 200
|
|
assert latest_deck_response.json()["date"] == "2024-07-25T00:00:00"
|
|
|
|
def success_cleanup():
|
|
games = _json_get(test_client, "/game/list")
|
|
for game in games.json():
|
|
_json_delete(test_client, f"/game/{game['id']}")
|
|
|
|
decks = _json_get(test_client, "/deck/list")
|
|
for deck in decks.json():
|
|
_json_delete(test_client, f"/deck/{deck['id']}")
|
|
|
|
players = _json_get(test_client, "/player/list")
|
|
for player in players.json():
|
|
_json_delete(test_client, f"/player/{player['id']}")
|
|
|
|
cleanups.add_success(success_cleanup)
|
|
|
|
|
|
# TODO - this test is valid and correct, but I can't find a way to run it.
|
|
# The "cleanups" can only interact with the database via APIs (not directly), and the preceding test adds content to the
|
|
# database that cannot (currently) be nuked (specifically - sequence numbers).
|
|
# Either:
|
|
# * Add a full "nuke the database" API (probably not a good thing to expose!)
|
|
# * Find a way to initialize a full fresh database for each _test_ (see `isolated_database` in `tests/sql/test_crud.py`
|
|
# and `tests/routers/test_stats.py` for inspiration )
|
|
#
|
|
# def test_adding_games_with_ties(test_client: TestClient, cleanups):
|
|
# latest_game_response = _json_get(test_client, "/game/latest_game")
|
|
# assert latest_game_response.status_code == 404
|
|
|
|
# with open("seed-data/all-in-one-with-tied-games.csv", "rb") as f:
|
|
# test_client.post(
|
|
# "/api/seed/all_in_one",
|
|
# files={"file": ("fake_all_in_one_filename.csv", f, "text/csv")},
|
|
# )
|
|
|
|
# tied_game_response = _json_get(test_client, "/game/141")
|
|
# assert tied_game_response.status_code == 200
|
|
|
|
# winning_deck_id = tied_game_response.json()["winning_deck_id"]
|
|
# other_winning_deck_ids = tied_game_response.json()["other_winning_deck_ids"].split(',')
|
|
# assert _json_get(test_client, f"/deck/{winning_deck_id}").json()['name'] == "Narset, Enlightened Exile"
|
|
# assert len(other_winning_deck_ids) == 1
|
|
# assert _json_get(test_client, f"/deck/{other_winning_deck_ids[0]}").json()['name'] == "Aminatou, Veil Piercer"
|
|
|
|
|
|
def _json_get(c: TestClient, path: str) -> httpx.Response:
|
|
return c.get(f"/api{path}", headers={"Content-Type": "application/json"})
|
|
|
|
|
|
def _json_post(c: TestClient, path: str, body: Mapping) -> httpx.Response:
|
|
return c.post(
|
|
f"/api{path}", headers={"Content-Type": "application/json"}, json=body
|
|
)
|
|
|
|
|
|
def _json_delete(c: TestClient, path: str) -> httpx.Response:
|
|
return c.delete(f"/api{path}", headers={"Content-Type": "application/json"})
|