diff --git a/lobby/tests.py b/lobby/tests.py index 081fa1c..2a64f4f 100644 --- a/lobby/tests.py +++ b/lobby/tests.py @@ -788,6 +788,68 @@ class CanonicalRoundFlowTests(TestCase): self.assertEqual([entry["nickname"] for entry in payload["scoreboard"]], ["Luna", "Nora", "Mads"]) 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._resolve_scores") @patch("lobby.views.GameSession.objects.get") diff --git a/lobby/views.py b/lobby/views.py index 804404d..4146cb5 100644 --- a/lobby/views.py +++ b/lobby/views.py @@ -247,13 +247,6 @@ def _maybe_promote_reveal_to_scoreboard(session: GameSession) -> GameSession: if current_round_question is None: 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(): locked_session = GameSession.objects.select_for_update().get(pk=session.pk) if locked_session.status != GameSession.Status.REVEAL: