Normalize session code input in join and lookup flows
This commit is contained in:
@@ -60,6 +60,28 @@ class LobbyFlowTests(TestCase):
|
|||||||
self.assertTrue(body["player"]["session_token"])
|
self.assertTrue(body["player"]["session_token"])
|
||||||
self.assertTrue(Player.objects.filter(session=session, nickname="Luna").exists())
|
self.assertTrue(Player.objects.filter(session=session, nickname="Luna").exists())
|
||||||
|
|
||||||
|
def test_player_can_join_with_trimmed_code(self):
|
||||||
|
session = GameSession.objects.create(host=self.host, code="ABCD23")
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("lobby:join_session"),
|
||||||
|
data={"code": " abcd23 ", "nickname": "Luna"},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 201)
|
||||||
|
self.assertTrue(Player.objects.filter(session=session, nickname="Luna").exists())
|
||||||
|
|
||||||
|
def test_join_rejects_code_empty_after_trim(self):
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("lobby:join_session"),
|
||||||
|
data={"code": " ", "nickname": "Luna"},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 400)
|
||||||
|
self.assertEqual(response.json()["error"], "Session code is required")
|
||||||
|
|
||||||
def test_join_rejects_duplicate_nickname_case_insensitive(self):
|
def test_join_rejects_duplicate_nickname_case_insensitive(self):
|
||||||
session = GameSession.objects.create(host=self.host, code="QWER12")
|
session = GameSession.objects.create(host=self.host, code="QWER12")
|
||||||
Player.objects.create(session=session, nickname="Luna")
|
Player.objects.create(session=session, nickname="Luna")
|
||||||
@@ -131,6 +153,21 @@ class StartRoundTests(TestCase):
|
|||||||
round_config = RoundConfig.objects.get(session=self.session, number=1)
|
round_config = RoundConfig.objects.get(session=self.session, number=1)
|
||||||
self.assertEqual(round_config.category, self.category)
|
self.assertEqual(round_config.category, self.category)
|
||||||
|
|
||||||
|
def test_host_start_round_uses_normalized_session_code_from_path(self):
|
||||||
|
self.client.login(username="host", password="secret123")
|
||||||
|
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("lobby:start_round", kwargs={"code": " abcd23 "}),
|
||||||
|
data={"category_slug": self.category.slug},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 201)
|
||||||
|
self.session.refresh_from_db()
|
||||||
|
self.assertEqual(self.session.status, GameSession.Status.LIE)
|
||||||
|
round_config = RoundConfig.objects.get(session=self.session, number=1)
|
||||||
|
self.assertEqual(round_config.category, self.category)
|
||||||
|
|
||||||
def test_start_round_requires_host(self):
|
def test_start_round_requires_host(self):
|
||||||
self.client.login(username="other", password="secret123")
|
self.client.login(username="other", password="secret123")
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ def _generate_session_code() -> str:
|
|||||||
return "".join(random.choices(SESSION_CODE_ALPHABET, k=SESSION_CODE_LENGTH))
|
return "".join(random.choices(SESSION_CODE_ALPHABET, k=SESSION_CODE_LENGTH))
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_session_code(code: str) -> str:
|
||||||
|
return code.strip().upper()
|
||||||
|
|
||||||
|
|
||||||
def _create_unique_session_code() -> str:
|
def _create_unique_session_code() -> str:
|
||||||
for _ in range(MAX_CODE_GENERATION_ATTEMPTS):
|
for _ in range(MAX_CODE_GENERATION_ATTEMPTS):
|
||||||
code = _generate_session_code()
|
code = _generate_session_code()
|
||||||
@@ -77,7 +81,7 @@ def create_session(request: HttpRequest) -> JsonResponse:
|
|||||||
def join_session(request: HttpRequest) -> JsonResponse:
|
def join_session(request: HttpRequest) -> JsonResponse:
|
||||||
payload = _json_body(request)
|
payload = _json_body(request)
|
||||||
|
|
||||||
code = str(payload.get("code", "")).strip().upper()
|
code = _normalize_session_code(str(payload.get("code", "")))
|
||||||
nickname = str(payload.get("nickname", "")).strip()
|
nickname = str(payload.get("nickname", "")).strip()
|
||||||
|
|
||||||
if not code:
|
if not code:
|
||||||
@@ -118,7 +122,7 @@ def join_session(request: HttpRequest) -> JsonResponse:
|
|||||||
|
|
||||||
@require_GET
|
@require_GET
|
||||||
def session_detail(request: HttpRequest, code: str) -> JsonResponse:
|
def session_detail(request: HttpRequest, code: str) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -175,7 +179,7 @@ def start_round(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
if not category_slug:
|
if not category_slug:
|
||||||
return JsonResponse({"error": "category_slug is required"}, status=400)
|
return JsonResponse({"error": "category_slug is required"}, status=400)
|
||||||
|
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -234,7 +238,7 @@ def start_round(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def show_question(request: HttpRequest, code: str) -> JsonResponse:
|
def show_question(request: HttpRequest, code: str) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -294,7 +298,7 @@ def show_question(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
@require_POST
|
@require_POST
|
||||||
def submit_lie(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
def submit_lie(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
||||||
payload = _json_body(request)
|
payload = _json_body(request)
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
player_id = payload.get("player_id")
|
player_id = payload.get("player_id")
|
||||||
session_token = str(payload.get("session_token", "")).strip()
|
session_token = str(payload.get("session_token", "")).strip()
|
||||||
@@ -367,7 +371,7 @@ def submit_lie(request: HttpRequest, code: str, round_question_id: int) -> JsonR
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def mix_answers(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
def mix_answers(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -437,7 +441,7 @@ def mix_answers(request: HttpRequest, code: str, round_question_id: int) -> Json
|
|||||||
@require_POST
|
@require_POST
|
||||||
def submit_guess(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
def submit_guess(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
||||||
payload = _json_body(request)
|
payload = _json_body(request)
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
player_id = payload.get("player_id")
|
player_id = payload.get("player_id")
|
||||||
session_token = str(payload.get("session_token", "")).strip()
|
session_token = str(payload.get("session_token", "")).strip()
|
||||||
@@ -543,7 +547,7 @@ def submit_guess(request: HttpRequest, code: str, round_question_id: int) -> Jso
|
|||||||
@require_GET
|
@require_GET
|
||||||
@login_required
|
@login_required
|
||||||
def reveal_scoreboard(request: HttpRequest, code: str) -> JsonResponse:
|
def reveal_scoreboard(request: HttpRequest, code: str) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -577,7 +581,7 @@ def reveal_scoreboard(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def start_next_round(request: HttpRequest, code: str) -> JsonResponse:
|
def start_next_round(request: HttpRequest, code: str) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -609,7 +613,7 @@ def start_next_round(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def finish_game(request: HttpRequest, code: str) -> JsonResponse:
|
def finish_game(request: HttpRequest, code: str) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
@@ -651,7 +655,7 @@ def finish_game(request: HttpRequest, code: str) -> JsonResponse:
|
|||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def calculate_scores(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
def calculate_scores(request: HttpRequest, code: str, round_question_id: int) -> JsonResponse:
|
||||||
session_code = code.strip().upper()
|
session_code = _normalize_session_code(code)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
session = GameSession.objects.get(code=session_code)
|
session = GameSession.objects.get(code=session_code)
|
||||||
|
|||||||
Reference in New Issue
Block a user