fix(lobby): avoid orphaned round configs on round start
This commit is contained in:
@@ -308,6 +308,23 @@ class StartRoundTests(TestCase):
|
|||||||
self.assertEqual(response.json()["locale"], "en")
|
self.assertEqual(response.json()["locale"], "en")
|
||||||
self.assertEqual(response.json()["error"], "Only host can start round")
|
self.assertEqual(response.json()["error"], "Only host can start round")
|
||||||
|
|
||||||
|
@patch("lobby.views._select_round_question", side_effect=ValueError("no_available_questions"))
|
||||||
|
def test_start_round_does_not_persist_round_config_when_question_selection_fails(self, _mock_select_round_question):
|
||||||
|
self.client.login(username="host", password="secret123")
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("lobby:start_round", kwargs={"code": self.session.code}),
|
||||||
|
data={"category_slug": self.category.slug},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
self.assertEqual(response.json()["error_code"], "no_available_questions")
|
||||||
|
self.session.refresh_from_db()
|
||||||
|
self.assertEqual(self.session.status, GameSession.Status.LOBBY)
|
||||||
|
self.assertFalse(RoundConfig.objects.filter(session=self.session, number=1).exists())
|
||||||
|
self.assertFalse(RoundQuestion.objects.filter(session=self.session, round_number=1).exists())
|
||||||
|
|
||||||
|
|
||||||
class LieSubmissionTests(TestCase):
|
class LieSubmissionTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -1329,6 +1346,26 @@ class RevealRoundFlowTests(TestCase):
|
|||||||
self.assertEqual(response.json()["locale"], "da")
|
self.assertEqual(response.json()["locale"], "da")
|
||||||
self.assertEqual(response.json()["error"], "Næste runde kan kun starte fra scoreboard-fasen")
|
self.assertEqual(response.json()["error"], "Næste runde kan kun starte fra scoreboard-fasen")
|
||||||
|
|
||||||
|
def test_start_next_round_does_not_persist_round_config_when_question_selection_fails(self):
|
||||||
|
self.client.login(username="host_reveal", password="secret123")
|
||||||
|
self.client.get(reverse("lobby:reveal_scoreboard", kwargs={"code": self.session.code}))
|
||||||
|
self.next_question.delete()
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
reverse(
|
||||||
|
"lobby:start_next_round",
|
||||||
|
kwargs={"code": self.session.code},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
self.assertEqual(response.json()["error_code"], "no_available_questions")
|
||||||
|
self.session.refresh_from_db()
|
||||||
|
self.assertEqual(self.session.status, GameSession.Status.SCOREBOARD)
|
||||||
|
self.assertEqual(self.session.current_round, 1)
|
||||||
|
self.assertFalse(RoundConfig.objects.filter(session=self.session, number=2).exists())
|
||||||
|
self.assertFalse(RoundQuestion.objects.filter(session=self.session, round_number=2).exists())
|
||||||
|
|
||||||
def test_reveal_scoreboard_unsupported_locale_falls_back_to_en_deterministically(self):
|
def test_reveal_scoreboard_unsupported_locale_falls_back_to_en_deterministically(self):
|
||||||
self.client.login(username="other_reveal", password="secret123")
|
self.client.login(username="other_reveal", password="secret123")
|
||||||
|
|
||||||
|
|||||||
@@ -528,23 +528,25 @@ def start_round(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
status=400,
|
status=400,
|
||||||
)
|
)
|
||||||
|
|
||||||
round_config, created = RoundConfig.objects.get_or_create(
|
if RoundConfig.objects.filter(session=session, number=session.current_round).exists():
|
||||||
session=session,
|
|
||||||
number=session.current_round,
|
|
||||||
defaults={"category": category},
|
|
||||||
)
|
|
||||||
if not created:
|
|
||||||
return api_error(
|
return api_error(
|
||||||
request,
|
request,
|
||||||
code="round_already_configured",
|
code="round_already_configured",
|
||||||
status=409,
|
status=409,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
round_config = RoundConfig(
|
||||||
|
session=session,
|
||||||
|
number=session.current_round,
|
||||||
|
category=category,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
round_question = _select_round_question(session, round_config)
|
round_question = _select_round_question(session, round_config)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
return api_error(request, code=str(exc), status=400)
|
return api_error(request, code=str(exc), status=400)
|
||||||
|
|
||||||
|
round_config.save()
|
||||||
session.status = GameSession.Status.LIE
|
session.status = GameSession.Status.LIE
|
||||||
session.save(update_fields=["status"])
|
session.save(update_fields=["status"])
|
||||||
|
|
||||||
@@ -1101,22 +1103,24 @@ def start_next_round(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
if previous_round_config is None:
|
if previous_round_config is None:
|
||||||
return api_error(request, code="round_config_missing", status=400)
|
return api_error(request, code="round_config_missing", status=400)
|
||||||
|
|
||||||
locked_session.current_round += 1
|
next_round_number = locked_session.current_round + 1
|
||||||
next_round_config = RoundConfig.objects.create(
|
next_round_config = RoundConfig(
|
||||||
session=locked_session,
|
session=locked_session,
|
||||||
number=locked_session.current_round,
|
number=next_round_number,
|
||||||
category=previous_round_config.category,
|
category=previous_round_config.category,
|
||||||
lie_seconds=previous_round_config.lie_seconds,
|
lie_seconds=previous_round_config.lie_seconds,
|
||||||
guess_seconds=previous_round_config.guess_seconds,
|
guess_seconds=previous_round_config.guess_seconds,
|
||||||
points_correct=previous_round_config.points_correct,
|
points_correct=previous_round_config.points_correct,
|
||||||
points_bluff=previous_round_config.points_bluff,
|
points_bluff=previous_round_config.points_bluff,
|
||||||
)
|
)
|
||||||
|
locked_session.current_round = next_round_number
|
||||||
|
|
||||||
try:
|
try:
|
||||||
round_question = _select_round_question(locked_session, next_round_config)
|
round_question = _select_round_question(locked_session, next_round_config)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
return api_error(request, code=str(exc), status=400)
|
return api_error(request, code=str(exc), status=400)
|
||||||
|
|
||||||
|
next_round_config.save()
|
||||||
locked_session.status = GameSession.Status.LIE
|
locked_session.status = GameSession.Status.LIE
|
||||||
locked_session.save(update_fields=["current_round", "status"])
|
locked_session.save(update_fields=["current_round", "status"])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user