diff --git a/src/apps/epic/tests/integrated/test_views.py b/src/apps/epic/tests/integrated/test_views.py index a35c95c..3abc03c 100644 --- a/src/apps/epic/tests/integrated/test_views.py +++ b/src/apps/epic/tests/integrated/test_views.py @@ -1265,8 +1265,23 @@ class SigReserveViewTest(TestCase): response = self._reserve(action="release") self.assertEqual(response.status_code, 200) + def test_release_while_ready_records_sig_unready(self): + """Releasing a ready reservation implicitly acts as WAIT NVM and records SIG_UNREADY.""" + self._reserve() + res = SigReservation.objects.get(room=self.room, gamer=self.gamers[0]) + res.ready = True + res.save() + self._reserve(action="release") + self.assertTrue(self.room.events.filter( + actor=self.gamers[0], verb=GameEvent.SIG_UNREADY + ).exists()) + # ── guards ──────────────────────────────────────────────────────────── + def test_reserve_non_post_returns_405(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 405) + def test_reserve_requires_login(self): self.client.logout() response = self._reserve() @@ -1348,6 +1363,10 @@ class SigReadyViewTest(TestCase): # ── guards ──────────────────────────────────────────────────────────── + def test_sig_ready_non_post_returns_405(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 405) + def test_sig_ready_requires_login(self): self.client.logout() response = self._post() @@ -1384,6 +1403,13 @@ class SigReadyViewTest(TestCase): response = self._post(action="ready") self.assertEqual(response.status_code, 200) + def test_sig_ready_already_ready_is_idempotent(self): + """Re-posting ready when already ready returns 200 without re-triggering countdown.""" + self.reservations[0].ready = True + self.reservations[0].save() + response = self._post(action="ready") + self.assertEqual(response.status_code, 200) + # ── unready ────────────────────────────────────────────────────────── def test_sig_unready_sets_ready_false(self): @@ -1419,6 +1445,14 @@ class SigReadyViewTest(TestCase): self._post(action="ready") mock_notify.assert_not_called() + def test_sig_unready_invalid_seconds_defaults_to_12(self): + """Non-numeric seconds_remaining falls back to 12.""" + self.reservations[0].ready = True + self.reservations[0].save() + self._post(action="unready", seconds_remaining="abc") + self.reservations[0].refresh_from_db() + self.assertEqual(self.reservations[0].countdown_remaining, 12) + def test_sig_unready_saves_seconds_remaining_on_all_polarity_reservations(self): for res in self.reservations: res.ready = True @@ -1493,6 +1527,10 @@ class SigConfirmViewTest(TestCase): # ── guards ──────────────────────────────────────────────────────────── + def test_sig_confirm_non_post_returns_405(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 405) + def test_sig_confirm_requires_login(self): self.client.logout() response = self._post() @@ -1645,108 +1683,6 @@ def _make_sig_room(owner, *extra_gamers): return room, seat_map -class SigReserveViewTest(TestCase): - def setUp(self): - self.user = User.objects.create(email="pc@sig.io") - self.client.force_login(self.user) - self.room, self.seats = _make_sig_room(self.user) - self.card = TarotCard.objects.first() - - def test_non_post_returns_405(self): - response = self.client.get(reverse("epic:sig_reserve", kwargs={"room_id": self.room.id})) - self.assertEqual(response.status_code, 405) - - def test_reserve_action_succeeds(self): - response = self.client.post( - reverse("epic:sig_reserve", kwargs={"room_id": self.room.id}), - {"action": "reserve", "card_id": str(self.card.pk)}, - ) - self.assertEqual(response.status_code, 200) - self.assertTrue(SigReservation.objects.filter(room=self.room, gamer=self.user).exists()) - - def test_release_action_removes_reservation(self): - SigReservation.objects.create( - room=self.room, gamer=self.user, card=self.card, - polarity=SigReservation.LEVITY, seat=self.seats["PC"], - ) - response = self.client.post( - reverse("epic:sig_reserve", kwargs={"room_id": self.room.id}), - {"action": "release"}, - ) - self.assertEqual(response.status_code, 200) - self.assertFalse(SigReservation.objects.filter(room=self.room, gamer=self.user).exists()) - - -class SigReadyViewTest(TestCase): - def setUp(self): - self.user = User.objects.create(email="pc@ready.io") - self.client.force_login(self.user) - self.room, self.seats = _make_sig_room(self.user) - self.card = ( - TarotCard.objects.filter(arcana=TarotCard.MIDDLE).first() - or TarotCard.objects.first() - ) - self.res = SigReservation.objects.create( - room=self.room, gamer=self.user, card=self.card, - polarity=SigReservation.LEVITY, seat=self.seats["PC"], - ) - - def test_non_post_returns_405(self): - response = self.client.get(reverse("epic:sig_ready", kwargs={"room_id": self.room.id})) - self.assertEqual(response.status_code, 405) - - def test_ready_action_sets_ready_flag(self): - response = self.client.post( - reverse("epic:sig_ready", kwargs={"room_id": self.room.id}), - {"action": "ready"}, - ) - self.assertEqual(response.status_code, 200) - self.res.refresh_from_db() - self.assertTrue(self.res.ready) - - def test_ready_action_idempotent_when_already_ready(self): - self.res.ready = True - self.res.save() - response = self.client.post( - reverse("epic:sig_ready", kwargs={"room_id": self.room.id}), - {"action": "ready"}, - ) - self.assertEqual(response.status_code, 200) - - def test_unready_action_saves_seconds_remaining(self): - self.res.ready = True - self.res.save() - response = self.client.post( - reverse("epic:sig_ready", kwargs={"room_id": self.room.id}), - {"action": "unready", "seconds_remaining": "7"}, - ) - self.assertEqual(response.status_code, 200) - self.res.refresh_from_db() - self.assertEqual(self.res.countdown_remaining, 7) - - def test_unready_action_handles_invalid_seconds_remaining(self): - self.res.ready = True - self.res.save() - response = self.client.post( - reverse("epic:sig_ready", kwargs={"room_id": self.room.id}), - {"action": "unready", "seconds_remaining": "abc"}, - ) - self.assertEqual(response.status_code, 200) - self.res.refresh_from_db() - self.assertEqual(self.res.countdown_remaining, 12) - - -class SigConfirmViewTest(TestCase): - def setUp(self): - self.user = User.objects.create(email="pc@confirm.io") - self.client.force_login(self.user) - self.room, self.seats = _make_sig_room(self.user) - - def test_non_post_returns_405(self): - response = self.client.get(reverse("epic:sig_confirm", kwargs={"room_id": self.room.id})) - self.assertEqual(response.status_code, 405) - - class SelectSigViewTest(TestCase): def setUp(self): self.user = User.objects.create(email="pc@selsig.io") @@ -1838,6 +1774,25 @@ class NatusPreviewViewTest(TestCase): self.assertNotIn("Earth", data["elements"]) +# ── tarot_deal ──────────────────────────────────────────────────────────────── + +class TarotDealViewTest(TestCase): + def setUp(self): + self.user = User.objects.create(email="dealer@test.io") + self.client.force_login(self.user) + self.room, _ = _make_sig_room(self.user) + + def test_non_post_redirects_to_tarot_deck(self): + response = self.client.get( + reverse("epic:tarot_deal", kwargs={"room_id": self.room.id}) + ) + self.assertRedirects( + response, + reverse("epic:tarot_deck", kwargs={"room_id": self.room.id}), + fetch_redirect_response=False, + ) + + # ── natus_save (epic) ───────────────────────────────────────────────────────── class NatusSaveViewTest(TestCase):