fix(lobby): promote zero-score reveals to scoreboard
This commit is contained in:
@@ -788,6 +788,68 @@ class CanonicalRoundFlowTests(TestCase):
|
|||||||
self.assertEqual([entry["nickname"] for entry in payload["scoreboard"]], ["Luna", "Nora", "Mads"])
|
self.assertEqual([entry["nickname"] for entry in payload["scoreboard"]], ["Luna", "Nora", "Mads"])
|
||||||
self.assertEqual(payload["reveal"]["correct_answer"], "Shakespeare")
|
self.assertEqual(payload["reveal"]["correct_answer"], "Shakespeare")
|
||||||
|
|
||||||
|
@patch("lobby.views.sync_broadcast_phase_event")
|
||||||
|
@patch("lobby.views._resolve_scores")
|
||||||
|
def test_session_detail_promotes_zero_score_event_reveal_to_scoreboard(self, mock_resolve_scores, mock_sync_broadcast):
|
||||||
|
self.client.login(username="host_canonical", password="secret123")
|
||||||
|
self.session.status = GameSession.Status.GUESS
|
||||||
|
self.session.save(update_fields=["status"])
|
||||||
|
|
||||||
|
round_config = RoundConfig.objects.create(
|
||||||
|
session=self.session,
|
||||||
|
number=1,
|
||||||
|
category=self.category,
|
||||||
|
points_correct=5,
|
||||||
|
points_bluff=2,
|
||||||
|
)
|
||||||
|
round_question = RoundQuestion.objects.create(
|
||||||
|
session=self.session,
|
||||||
|
round_number=1,
|
||||||
|
question=self.question,
|
||||||
|
correct_answer="Shakespeare",
|
||||||
|
)
|
||||||
|
LieAnswer.objects.create(round_question=round_question, player=self.players[0], text="Marlowe")
|
||||||
|
LieAnswer.objects.create(round_question=round_question, player=self.players[1], text="Chaucer")
|
||||||
|
LieAnswer.objects.create(round_question=round_question, player=self.players[2], text="Austen")
|
||||||
|
|
||||||
|
mock_resolve_scores.return_value = ([], [
|
||||||
|
{"id": player.id, "nickname": player.nickname, "score": player.score}
|
||||||
|
for player in sorted(self.players, key=lambda player: player.nickname)
|
||||||
|
])
|
||||||
|
|
||||||
|
guess_targets = ["Shakespeare", "Shakespeare", "Shakespeare"]
|
||||||
|
guess_responses = []
|
||||||
|
for player, selected_text in zip(self.players, guess_targets, strict=True):
|
||||||
|
guess_responses.append(
|
||||||
|
self.client.post(
|
||||||
|
reverse("lobby:submit_guess", kwargs={"code": self.session.code, "round_question_id": round_question.id}),
|
||||||
|
data={"player_id": player.id, "session_token": player.session_token, "selected_text": selected_text},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(all(response.status_code == 201 for response in guess_responses))
|
||||||
|
self.assertEqual(guess_responses[-1].json()["session"]["status"], GameSession.Status.REVEAL)
|
||||||
|
self.assertEqual(ScoreEvent.objects.filter(session=self.session, meta__round_question_id=round_question.id).count(), 0)
|
||||||
|
|
||||||
|
detail_response = self.client.get(reverse("lobby:session_detail", kwargs={"code": self.session.code}))
|
||||||
|
|
||||||
|
self.assertEqual(detail_response.status_code, 200)
|
||||||
|
payload = detail_response.json()
|
||||||
|
self.assertEqual(payload["session"]["status"], GameSession.Status.SCOREBOARD)
|
||||||
|
self.assertEqual(payload["phase_view_model"]["current_phase"], GameSession.Status.SCOREBOARD)
|
||||||
|
self.assertTrue(payload["phase_view_model"]["readiness"]["scoreboard_ready"])
|
||||||
|
self.assertEqual(payload["reveal"]["correct_answer"], "Shakespeare")
|
||||||
|
mock_resolve_scores.assert_called_once_with(self.session, round_question, round_config)
|
||||||
|
mock_sync_broadcast.assert_any_call(
|
||||||
|
self.session.code,
|
||||||
|
"phase.scoreboard",
|
||||||
|
{
|
||||||
|
"leaderboard": payload["scoreboard"],
|
||||||
|
"current_round": self.session.current_round,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@patch("lobby.views.sync_broadcast_phase_event")
|
@patch("lobby.views.sync_broadcast_phase_event")
|
||||||
@patch("lobby.views._resolve_scores")
|
@patch("lobby.views._resolve_scores")
|
||||||
@patch("lobby.views.GameSession.objects.get")
|
@patch("lobby.views.GameSession.objects.get")
|
||||||
|
|||||||
@@ -247,13 +247,6 @@ def _maybe_promote_reveal_to_scoreboard(session: GameSession) -> GameSession:
|
|||||||
if current_round_question is None:
|
if current_round_question is None:
|
||||||
return session
|
return session
|
||||||
|
|
||||||
has_round_scores = ScoreEvent.objects.filter(
|
|
||||||
session=session,
|
|
||||||
meta__round_question_id=current_round_question.id,
|
|
||||||
).exists()
|
|
||||||
if not has_round_scores:
|
|
||||||
return session
|
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
locked_session = GameSession.objects.select_for_update().get(pk=session.pk)
|
locked_session = GameSession.objects.select_for_update().get(pk=session.pk)
|
||||||
if locked_session.status != GameSession.Status.REVEAL:
|
if locked_session.status != GameSession.Status.REVEAL:
|
||||||
|
|||||||
Reference in New Issue
Block a user