[READY][Gameplay] #310 Host transition idempotency and error catalog for scoreboard -> next round / finish #320

Merged
agw merged 45 commits from dev/issue-310-host-transition-idempotency-v2 into main 2026-03-18 06:52:04 +01:00
Showing only changes of commit 72bc5997ff - Show all commits

View File

@@ -3,7 +3,6 @@ from unittest.mock import patch
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
from django.utils import timezone
from fupogfakta.models import Category, GameSession, Guess, LieAnswer, Player, Question, RoundConfig, RoundQuestion, ScoreEvent
@@ -194,74 +193,6 @@ class FupOgFaktaExtractionSliceTests(TestCase):
self.assertEqual(result.session.status, GameSession.Status.FINISHED)
self.assertEqual(self.session.status, GameSession.Status.FINISHED)
@patch("lobby.views.sync_broadcast_phase_event")
@patch("lobby.views._start_next_round")
def test_start_next_round_view_delegates_to_fupogfakta_service(self, mock_start_next_round, mock_broadcast):
self.client.login(username="host", password="secret123")
self.session.status = GameSession.Status.SCOREBOARD
self.session.save(update_fields=["status"])
response_payload = {
"session": {
"code": self.session.code,
"status": GameSession.Status.LIE,
"current_round": 2,
}
}
mock_start_next_round.return_value = type(
"Transition",
(),
{
"session": self.session,
"should_broadcast": True,
"response_payload": response_payload,
"phase_event_name": "phase.lie_started",
"phase_event_payload": {"round_number": 2},
},
)()
response = self.client.post(reverse("lobby:start_next_round", kwargs={"code": self.session.code}))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), response_payload)
mock_start_next_round.assert_called_once_with(self.session)
mock_broadcast.assert_called_once_with(self.session.code, "phase.lie_started", {"round_number": 2})
@patch("lobby.views.sync_broadcast_phase_event")
@patch("lobby.views._finish_game")
def test_finish_game_view_delegates_to_fupogfakta_service(self, mock_finish_game, mock_broadcast):
self.client.login(username="host", password="secret123")
self.session.status = GameSession.Status.SCOREBOARD
self.session.save(update_fields=["status"])
response_payload = {
"session": {
"code": self.session.code,
"status": GameSession.Status.FINISHED,
"current_round": 1,
},
"winner": None,
"leaderboard": [],
}
finished_session = GameSession.objects.get(pk=self.session.pk)
finished_session.status = GameSession.Status.FINISHED
mock_finish_game.return_value = type(
"Transition",
(),
{
"session": finished_session,
"should_broadcast": True,
"response_payload": response_payload,
"phase_event_name": "phase.game_over",
"phase_event_payload": {"leaderboard": []},
},
)()
response = self.client.post(reverse("lobby:finish_game", kwargs={"code": self.session.code}))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), response_payload)
mock_finish_game.assert_called_once_with(self.session)
mock_broadcast.assert_called_once_with(self.session.code, "phase.game_over", {"leaderboard": []})
def test_promote_reveal_to_scoreboard_moves_transition_into_service(self):
round_question = RoundQuestion.objects.create(
session=self.session,