diff --git a/infra/staging/smoke_suite.sh b/infra/staging/smoke_suite.sh index 11d7c36..debd645 100755 --- a/infra/staging/smoke_suite.sh +++ b/infra/staging/smoke_suite.sh @@ -50,6 +50,12 @@ PY echo "[smoke] healthz check: ${BASE_URL}/healthz" curl -fsS "${BASE_URL}/healthz" >/dev/null || { SMOKE_FAIL_MESSAGE="healthz check failed" fail "healthz check failed"; } +echo "[smoke] migration consistency check" +( + cd "${APP_DIR}" + .venv/bin/python manage.py migrate --check --noinput +) || { SMOKE_FAIL_MESSAGE="schema drift: unapplied migrations in staging" fail "schema drift: unapplied migrations in staging"; } + echo "[smoke] gameplay flow via management command" ( cd "${APP_DIR}" diff --git a/lobby/management/commands/smoke_staging.py b/lobby/management/commands/smoke_staging.py index c672028..d2aff7f 100644 --- a/lobby/management/commands/smoke_staging.py +++ b/lobby/management/commands/smoke_staging.py @@ -72,7 +72,13 @@ class Command(BaseCommand): nick = player["nickname"] lie_res = Client().post( f"/lobby/sessions/{code}/questions/{round_question_id}/lies/submit", - data=json.dumps({"player_id": player["id"], "text": f"Lie from {nick}"}), + data=json.dumps( + { + "player_id": player["id"], + "session_token": player["session_token"], + "text": f"Lie from {nick}", + } + ), content_type="application/json", ) if lie_res.status_code != 201: @@ -94,7 +100,13 @@ class Command(BaseCommand): selected = next((a for a in answers if a.get("player_id") != player["id"]), answers[0]) guess_res = Client().post( f"/lobby/sessions/{code}/questions/{round_question_id}/guesses/submit", - data=json.dumps({"player_id": player["id"], "selected_text": selected["text"]}), + data=json.dumps( + { + "player_id": player["id"], + "session_token": player["session_token"], + "selected_text": selected["text"], + } + ), content_type="application/json", ) if guess_res.status_code != 201: diff --git a/lobby/tests.py b/lobby/tests.py index c2f642b..6516313 100644 --- a/lobby/tests.py +++ b/lobby/tests.py @@ -1,6 +1,7 @@ from datetime import timedelta from django.contrib.auth import get_user_model +from django.core.management import call_command from django.test import TestCase from django.urls import reverse from django.utils import timezone @@ -925,3 +926,12 @@ class SessionDetailRoundQuestionTests(TestCase): payload = response.json() self.assertEqual(payload["round_question"]["id"], round_question.id) self.assertEqual(payload["round_question"]["prompt"], self.question.prompt) + + +class SmokeStagingCommandTests(TestCase): + def test_smoke_staging_command_runs_full_flow(self): + call_command("smoke_staging") + + session = GameSession.objects.latest("created_at") + self.assertEqual(session.status, GameSession.Status.FINISHED) + self.assertEqual(Player.objects.filter(session=session).count(), 3)