Added seperate bracket/node logic

This commit is contained in:
2026-02-12 16:03:10 +01:00 Verified
parent 7cbb7faca8
commit bb68e326cd
13 changed files with 540 additions and 530 deletions
+34 -33
View File
@@ -15,21 +15,22 @@ async def test_scoring_flow(
t_id = res.json()["id"]
t_code = valid_tournament_payload["code"]
# 2. Get Matches to find a Round 1 match
matches_res = await client.get(f"/tournaments/{t_id}/matches")
matches = matches_res.json()
# 2. Get Bracket Nodes (Updated Endpoint)
bracket_res = await client.get(f"/tournaments/{t_id}/bracket")
nodes = bracket_res.json()
# Find a match that has real players (not BYE)
# In double elim, Round 1 matches usually have seeds.
target_match = next(m for m in matches if m["p1"] and m["p2"])
match_id = target_match["id"]
next_match_id = target_match["next_win"] # Note: using alias from schema
# Find active node
active_node = next(n for n in nodes if n.get("match") is not None)
# 3. Report Score WITHOUT Auth Header (Public user with Code)
match_data = active_node["match"]
match_id = match_data["id"]
next_node_id = active_node["winner_next_node_id"]
# 3. Report Score
score_payload = {
"id": match_id,
"code": t_code,
"sets": [{"p1": 21, "p2": 19}, {"p1": 21, "p2": 15}], # P1 Wins
"sets": [{"p1": 21, "p2": 19}, {"p1": 21, "p2": 15}],
}
report_res = await client.post(
@@ -37,15 +38,17 @@ async def test_scoring_flow(
)
assert report_res.status_code == 200
# 4. Verify Winner Advanced
# Fetch the *Next* match
next_match_res = await client.get(f"/tournaments/{t_id}/matches/{next_match_id}")
next_match = next_match_res.json()
# 4. Verify Winner Advanced (Fetch bracket again)
updated_res = await client.get(f"/tournaments/{t_id}/bracket")
updated_nodes = updated_res.json()
# Assert P1 from previous match is now in the next match
# Note: We check if the name matches the winner
winner_name = target_match["p1"]
assert (next_match["p1"] == winner_name) or (next_match["p2"] == winner_name)
target_node = next(n for n in updated_nodes if n["id"] == next_node_id)
winner_id = match_data["p1_team"]["id"]
p1_in_target = target_node["p1_team"]["id"] if target_node["p1_team"] else None
p2_in_target = target_node["p2_team"]["id"] if target_node["p2_team"] else None
assert winner_id in [p1_in_target, p2_in_target]
# 5. Test Invalid Code
bad_payload = score_payload.copy()
@@ -57,38 +60,36 @@ async def test_scoring_flow(
async def test_clear_score(client: AsyncClient, auth_headers, valid_tournament_payload):
# Setup: Create & Score
# Setup
res = await client.post(
"/tournaments", json=valid_tournament_payload, headers=auth_headers
)
t_id = res.json()["id"]
matches = (await client.get(f"/tournaments/{t_id}/matches")).json()
target = next(m for m in matches if m["p1"] and m["p2"])
score_payload = {"id": target["id"], "code": "1234", "sets": [{"p1": 25, "p2": 0}]}
# Get active match
bracket = (await client.get(f"/tournaments/{t_id}/bracket")).json()
active_node = next(n for n in bracket if n.get("match"))
match_id = active_node["match"]["id"]
score_payload = {"id": match_id, "code": "1234", "sets": [{"p1": 25, "p2": 0}]}
await client.post(
f"/tournaments/{t_id}/matches/{target['id']}/score", json=score_payload
f"/tournaments/{t_id}/matches/{match_id}/score", json=score_payload
)
# Verify Finished
check_res = await client.get(f"/tournaments/{t_id}/matches/{target['id']}")
check_res = await client.get(f"/tournaments/{t_id}/matches/{match_id}")
assert check_res.json()["status"] == "Finished"
# Action: Clear Score
clear_res = await client.delete(
f"/tournaments/{t_id}/matches/{target['id']}/score", headers=auth_headers
f"/tournaments/{t_id}/matches/{match_id}/score", headers=auth_headers
)
assert clear_res.status_code == 200
# Verify Reset
final_res = await client.get(f"/tournaments/{t_id}/matches/{target['id']}")
final_res = await client.get(f"/tournaments/{t_id}/matches/{match_id}")
data = final_res.json()
# 1. We already fixed this to expect 'Scheduled'
assert data["status"] == "Scheduled"
# 2. FIX: Check 'winner_side' instead of 'winner'
# Use the Enum value "none"
assert data["winner_side"] == "none"
assert data["status"] == "Pending"
assert data["winner_team_id"] is None
assert len(data["sets"]) == 0
+10 -9
View File
@@ -14,7 +14,7 @@ async def test_manage_teams(
)
t_id = res.json()["id"]
# 1. Add a Team via POST
# 1. Add a Team
new_team = {"name": "Team E"}
post_res = await client.post(
f"/tournaments/{t_id}/teams", json=new_team, headers=auth_headers
@@ -22,12 +22,14 @@ async def test_manage_teams(
assert post_res.status_code == 200
assert post_res.json()["name"] == "Team E"
# 2. Verify Bracket Regenerated (Match count should likely change or re-seed)
matches_res = await client.get(f"/tournaments/{t_id}/matches")
# With 4 teams -> ~6 matches. With 5 teams -> ~8-10 matches in Double Elim.
assert len(matches_res.json()) > 0
# 2. Verify Bracket Regenerated (Call new endpoint)
bracket_res = await client.get(f"/tournaments/{t_id}/bracket")
nodes = bracket_res.json()
# 3. Bulk Update via PATCH (Replace all teams)
# With 5 teams -> size 8 bracket
assert len(nodes) > 4
# 3. Bulk Update
new_team_list = ["Team X", "Team Y"]
patch_res = await client.patch(
f"/tournaments/{t_id}/teams", json=new_team_list, headers=auth_headers
@@ -35,7 +37,6 @@ async def test_manage_teams(
assert patch_res.status_code == 200
data = patch_res.json()
assert len(data) == 2
assert data[0]["name"] in ["Team X", "Team Y"]
async def test_manage_courts(
@@ -51,14 +52,14 @@ async def test_manage_courts(
initial_courts = courts_res.json()
assert len(initial_courts) == 2
# Delete a court
# Delete
court_id = initial_courts[0]["id"]
del_res = await client.delete(
f"/tournaments/{t_id}/courts/{court_id}", headers=auth_headers
)
assert del_res.status_code == 200
# Create a court
# Create
create_res = await client.post(
f"/tournaments/{t_id}/courts", json={"name": "New Court"}, headers=auth_headers
)
+17 -9
View File
@@ -2,7 +2,6 @@
import pytest
from httpx import AsyncClient
# Mark all tests in this file as async
pytestmark = pytest.mark.anyio
@@ -15,15 +14,14 @@ async def test_create_tournament(
assert response.status_code == 200
data = response.json()
assert data["name"] == "Test Tournament"
assert data["team_count"] == 4
assert data["court_count"] == 2
assert len(data["teams"]) == 4
assert len(data["courts"]) == 2
assert "id" in data
async def test_list_tournaments(
client: AsyncClient, auth_headers, valid_tournament_payload
):
# Create one first
await client.post(
"/tournaments", json=valid_tournament_payload, headers=auth_headers
)
@@ -35,7 +33,7 @@ async def test_list_tournaments(
assert data[0]["name"] == "Test Tournament"
async def test_get_tournament_detail(
async def test_get_tournament_detail_and_bracket(
client: AsyncClient, auth_headers, valid_tournament_payload
):
create_res = await client.post(
@@ -43,12 +41,24 @@ async def test_get_tournament_detail(
)
t_id = create_res.json()["id"]
# 1. Test Light Detail Endpoint
response = await client.get(f"/tournaments/{t_id}")
assert response.status_code == 200
data = response.json()
# Check deeply nested fields
assert len(data["matches"]) > 0 # Logic should have generated matches
# Should HAVE metadata
assert len(data["teams"]) == 4
# Should NOT have heavy bracket data
assert "nodes" not in data
# 2. Test New Bracket Endpoint
bracket_res = await client.get(f"/tournaments/{t_id}/bracket")
assert bracket_res.status_code == 200
nodes = bracket_res.json()
assert len(nodes) > 0
first_node = nodes[0]
assert "display_number" in first_node
async def test_update_settings(
@@ -64,7 +74,6 @@ async def test_update_settings(
f"/tournaments/{t_id}", json=update_payload, headers=auth_headers
)
# This will now succeed because we updated the response_model!
assert response.status_code == 200
data = response.json()
assert data["name"] == "Updated Name"
@@ -82,6 +91,5 @@ async def test_delete_tournament(
del_res = await client.delete(f"/tournaments/{t_id}", headers=auth_headers)
assert del_res.status_code == 200
# Verify it's gone
get_res = await client.get(f"/tournaments/{t_id}")
assert get_res.status_code == 404