ScoreTab viste hele turneringsfeltet i stedet for brukerens egen utslagsgruppe. Defaulter nå til egen flight med "vis hele feltet"- veksling og fallback når gruppe mangler. is_self beregnes server-side (aldri rå user_id). Lukker et reelt RLS-hull på tournament_round_group funnet underveis (migrasjon 089). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
107 lines
4.2 KiB
Python
107 lines
4.2 KiB
Python
"""
|
|
PATCH for å endre utslagssted på en allerede-tilordnet rundedeltaker
|
|
(ADR-093, 2026-08-19). Bygget som en direkte oppfølger til bulk-
|
|
rundedeltakelse-tabellen i "Spillere"-steget -- eneste grunn PATCH-en
|
|
finnes i det hele tatt (fremfor slett+opprett-på-nytt, som allerede var
|
|
mulig med de to eksisterende endepunktene) er at slett+opprett ville
|
|
STILLE fjernet spilleren fra en allerede tildelt utslagsgruppe
|
|
(migrasjon 084: tournament_round_group_id er en kolonne direkte på
|
|
tournament_round_participant, ikke en egen koblingstabell -- en ny rad
|
|
får alltid tournament_round_group_id=NULL).
|
|
"""
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from app.auth import CurrentUser
|
|
from app.routers.individual_tournaments import (
|
|
RoundGroupIn,
|
|
RoundParticipantTeeUpdate,
|
|
SaveRoundGroupsIn,
|
|
save_round_groups,
|
|
update_round_participant_tee,
|
|
)
|
|
|
|
from tests.conftest import (
|
|
create_org,
|
|
create_course,
|
|
create_player,
|
|
create_tee,
|
|
create_tournament,
|
|
create_tournament_participant,
|
|
create_tournament_round,
|
|
create_tournament_round_participant,
|
|
create_user,
|
|
)
|
|
|
|
import app.db as app_db
|
|
|
|
|
|
async def _setup(org_id):
|
|
tournament_id = await create_tournament(org_id, name="Utslagssted-turnering")
|
|
course_id = await create_course(org_id, name="Utslagssted Links")
|
|
tee_a = await create_tee(org_id, course_id, name="Gul")
|
|
tee_b = await create_tee(org_id, course_id, name="Rød")
|
|
async with app_db.org_connection(org_id) as conn:
|
|
await conn.execute(
|
|
"UPDATE tournament SET format_type = 'individual', scoring_method = 'stroke_gross' WHERE id = $1",
|
|
tournament_id,
|
|
)
|
|
round_id = await create_tournament_round(org_id, tournament_id, course_id, sequence=1)
|
|
player_id = await create_player(org_id, display_name="Spiller Ett")
|
|
tp_id = await create_tournament_participant(org_id, tournament_id, player_id)
|
|
rp_id = await create_tournament_round_participant(org_id, round_id, tp_id, tee_a)
|
|
return tournament_id, round_id, rp_id, tee_a, tee_b
|
|
|
|
|
|
async def test_changing_tee_preserves_group_membership(pool):
|
|
org_id = await create_org()
|
|
tournament_id, round_id, rp_id, tee_a, tee_b = await _setup(org_id)
|
|
|
|
saved = await save_round_groups(
|
|
tournament_id, round_id,
|
|
SaveRoundGroupsIn(groups=[RoundGroupIn(sequence=1, round_participant_ids=[rp_id])]),
|
|
organization_id=org_id,
|
|
)
|
|
assert len(saved.groups[0].participants) == 1
|
|
|
|
async with app_db.org_connection(org_id) as conn:
|
|
group_id_before = await conn.fetchval(
|
|
"SELECT tournament_round_group_id FROM tournament_round_participant WHERE id = $1", rp_id
|
|
)
|
|
assert group_id_before is not None
|
|
|
|
user_id = await create_user()
|
|
updated = await update_round_participant_tee(
|
|
tournament_id, round_id, rp_id, RoundParticipantTeeUpdate(tee_id=tee_b),
|
|
organization_id=org_id, user=CurrentUser(user_id=user_id),
|
|
)
|
|
assert updated.tee_id == tee_b
|
|
assert updated.id == rp_id # samme rad, ikke slett+gjenopprett
|
|
|
|
async with app_db.org_connection(org_id) as conn:
|
|
group_id_after = await conn.fetchval(
|
|
"SELECT tournament_round_group_id FROM tournament_round_participant WHERE id = $1", rp_id
|
|
)
|
|
assert group_id_after == group_id_before # fortsatt i samme gruppe
|
|
|
|
|
|
async def test_changing_tee_to_one_outside_course_is_rejected(pool):
|
|
org_id = await create_org()
|
|
tournament_id, round_id, rp_id, tee_a, _tee_b = await _setup(org_id)
|
|
other_course_id = await create_course(org_id, name="En annen bane")
|
|
foreign_tee_id = await create_tee(org_id, other_course_id, name="Blå")
|
|
|
|
user_id = await create_user()
|
|
with pytest.raises(HTTPException) as exc_info:
|
|
await update_round_participant_tee(
|
|
tournament_id, round_id, rp_id,
|
|
RoundParticipantTeeUpdate(tee_id=foreign_tee_id),
|
|
organization_id=org_id, user=CurrentUser(user_id=user_id),
|
|
)
|
|
assert exc_info.value.status_code == 400
|
|
assert exc_info.value.detail["code"] == "OUT_OF_SCOPE"
|
|
|
|
async with app_db.org_connection(org_id) as conn:
|
|
tee_after = await conn.fetchval("SELECT tee_id FROM tournament_round_participant WHERE id = $1", rp_id)
|
|
assert str(tee_after) == tee_a # uendret etter avvist forsøk
|