COVERAGE: patch 91% → 96%+ — 603 tests, tasks.py at 100%

New/extended tests across billboard, dashboard, drama, epic, gameboard,
and lyric to cover previously untested branches: dev_login view, scroll
position endpoints, sky preview error paths, drama to_prose/to_activity
branches, consumer broadcast handlers, tarot deck draw/shuffle, astrology
model __str__, character model, sig reserve/ready/confirm views, natus
preview/save views, and the full tasks.py countdown scheduler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-04-17 23:23:28 -04:00
parent 7c03bded8d
commit 758c9c5377
10 changed files with 903 additions and 2 deletions

View File

@@ -8,7 +8,8 @@ from django.db import IntegrityError
from apps.lyric.models import Token, User
from apps.epic.models import (
DeckVariant, GateSlot, Room, RoomInvite, SigReservation, TableSeat, TarotCard,
AspectType, Character, DeckVariant, GateSlot, HouseLabel, Planet, Room, RoomInvite,
SigReservation, Sign, TableSeat, TarotCard,
debit_token, select_token, sig_deck_cards, levity_sig_cards, gravity_sig_cards,
sig_seat_order, active_sig_seat,
)
@@ -593,3 +594,112 @@ class RoomSkySelectStatusTest(TestCase):
self.room.save()
self.room.refresh_from_db()
self.assertIsNotNone(self.room.sig_select_started_at)
# ── TarotDeck.draw / shuffle ──────────────────────────────────────────────────
class TarotDeckDrawTest(TestCase):
def setUp(self):
self.user = User.objects.create(email="dealer@test.io")
self.room = Room.objects.create(name="R", owner=self.user)
def test_draw_raises_value_error_when_too_few_cards_remain(self):
from apps.epic.models import TarotDeck
deck_variant = DeckVariant.objects.first()
all_ids = list(TarotCard.objects.filter(deck_variant=deck_variant).values_list('id', flat=True))
td = TarotDeck.objects.create(
room=self.room,
deck_variant=deck_variant,
drawn_card_ids=all_ids,
)
with self.assertRaises(ValueError):
td.draw(1)
def test_shuffle_resets_drawn_card_ids(self):
from apps.epic.models import TarotDeck
deck_variant = DeckVariant.objects.first()
some_ids = list(TarotCard.objects.filter(deck_variant=deck_variant).values_list('id', flat=True)[:3])
td = TarotDeck.objects.create(
room=self.room,
deck_variant=deck_variant,
drawn_card_ids=some_ids,
)
td.shuffle()
td.refresh_from_db()
self.assertEqual(td.drawn_card_ids, [])
# ── sig_deck_cards with no equipped deck ─────────────────────────────────────
class SigDeckCardsNoEquippedDeckTest(TestCase):
def test_returns_empty_list_when_owner_has_no_equipped_deck(self):
user = User.objects.create(email="nodeck@test.io")
user.equipped_deck = None
user.save(update_fields=["equipped_deck"])
room = Room.objects.create(name="R", owner=user)
self.assertEqual(sig_deck_cards(room), [])
# ── Astrology model __str__ methods ──────────────────────────────────────────
class AstrologyModelStrTest(TestCase):
def test_zodiac_sign_str(self):
sign = Sign.objects.first()
if sign is None:
self.skipTest("No Sign rows")
self.assertEqual(str(sign), sign.name)
def test_planet_str(self):
planet = Planet.objects.first()
if planet is None:
self.skipTest("No Planet rows")
self.assertEqual(str(planet), planet.name)
def test_aspect_type_str(self):
aspect = AspectType.objects.first()
if aspect is None:
self.skipTest("No AspectType rows")
self.assertEqual(str(aspect), aspect.name)
def test_house_label_str(self):
label = HouseLabel.objects.first()
if label is None:
self.skipTest("No HouseLabel rows")
self.assertIn(str(label.number), str(label))
# ── Character model ───────────────────────────────────────────────────────────
class CharacterModelTest(TestCase):
def setUp(self):
self.user = User.objects.create(email="char@test.io")
self.room = Room.objects.create(name="R", owner=self.user)
self.seat = TableSeat.objects.create(room=self.room, gamer=self.user, slot_number=1, role="PC")
def test_draft_str(self):
char = Character.objects.create(seat=self.seat)
self.assertIn("draft", str(char))
def test_confirmed_str(self):
char = Character.objects.create(seat=self.seat, confirmed_at=timezone.now())
self.assertIn("confirmed", str(char))
def test_is_confirmed_false_for_draft(self):
char = Character.objects.create(seat=self.seat)
self.assertFalse(char.is_confirmed)
def test_is_confirmed_true_when_confirmed_at_set(self):
char = Character.objects.create(seat=self.seat, confirmed_at=timezone.now())
self.assertTrue(char.is_confirmed)
def test_is_active_true_when_confirmed_and_not_retired(self):
char = Character.objects.create(seat=self.seat, confirmed_at=timezone.now())
self.assertTrue(char.is_active)
def test_is_active_false_when_retired(self):
char = Character.objects.create(
seat=self.seat,
confirmed_at=timezone.now(),
retired_at=timezone.now(),
)
self.assertFalse(char.is_active)