diff --git a/src/apps/gameboard/tests/integrated/test_views.py b/src/apps/gameboard/tests/integrated/test_views.py
index da04e6f..4726b6a 100644
--- a/src/apps/gameboard/tests/integrated/test_views.py
+++ b/src/apps/gameboard/tests/integrated/test_views.py
@@ -726,3 +726,74 @@ class MySeaSpreadFormTemplateTest(TestCase):
self.assertIn('id="id_sea_del"', html)
self.assertIn("sea-reversal-hint", html)
self.assertIn("25% reversals", html)
+
+
+class MySeaDeckDataViewTest(TestCase):
+ """Sprint 5 iter 4a — view-level deck-data contract. `my_sea` view
+ embeds a shuffled deck (levity + gravity halves, current user's
+ significator excluded, reversal pre-rolled at ~25%) as JSON via
+ the `sea_deck_data` context key + `{{ ...|json_script }}` filter
+ in the template."""
+
+ def setUp(self):
+ from apps.epic.models import personal_sig_cards
+ self.user = User.objects.create(email="deck@test.io")
+ self.client.force_login(self.user)
+ self.target = personal_sig_cards(self.user)[0]
+ self.user.significator = self.target
+ self.user.save(update_fields=["significator"])
+
+ def test_context_sea_deck_data_has_two_polarity_halves(self):
+ response = self.client.get(reverse("my_sea"))
+ deck = response.context["sea_deck_data"]
+ self.assertIn("levity", deck)
+ self.assertIn("gravity", deck)
+ self.assertIsInstance(deck["levity"], list)
+ self.assertIsInstance(deck["gravity"], list)
+
+ def test_deck_data_excludes_user_significator(self):
+ response = self.client.get(reverse("my_sea"))
+ deck = response.context["sea_deck_data"]
+ all_ids = (
+ {c["id"] for c in deck["levity"]}
+ | {c["id"] for c in deck["gravity"]}
+ )
+ self.assertNotIn(self.target.id, all_ids)
+
+ def test_deck_data_halves_are_disjoint(self):
+ response = self.client.get(reverse("my_sea"))
+ deck = response.context["sea_deck_data"]
+ levity_ids = {c["id"] for c in deck["levity"]}
+ gravity_ids = {c["id"] for c in deck["gravity"]}
+ self.assertEqual(levity_ids & gravity_ids, set())
+
+ def test_deck_data_cards_carry_corner_rank_suit_icon_and_reversed(self):
+ # Card dict shape mirrors the gameroom `sea_deck` endpoint so
+ # iter 4b's persistence/render path can reuse the JSON contract.
+ response = self.client.get(reverse("my_sea"))
+ deck = response.context["sea_deck_data"]
+ any_card = (deck["levity"] + deck["gravity"])[0]
+ for key in ("id", "corner_rank", "suit_icon", "reversed"):
+ with self.subTest(key=key):
+ self.assertIn(key, any_card)
+ self.assertIsInstance(any_card["reversed"], bool)
+
+ def test_template_embeds_deck_as_json_script(self):
+ # Embed mechanism: `{{ sea_deck_data|json_script:"id_my_sea_deck" }}`
+ # gives a `