import datetime from django.contrib.auth import get_user_model from django.test import TestCase from django.utils import timezone from members.models import Member from teams.models import Season, Team, TeamMembership, TeamPicture, TeamRole User = get_user_model() # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def make_member(email, first="Test", last="User"): user = User.objects.create_user(username=email, email=email, first_name=first, last_name=last) return user.member def make_season(start=datetime.date(2025, 9, 1), end=datetime.date(2026, 8, 31)): return Season.objects.create(start_date=start, end_date=end) def make_role(name="Player", abbreviation="P", admin_role=False): return TeamRole.objects.create(name=name, abbreviation=abbreviation, admin_role=admin_role) def make_team(name="Test Team"): return Team.objects.create(name=name) # --------------------------------------------------------------------------- # Season # --------------------------------------------------------------------------- class SeasonStrTest(TestCase): def test_str(self): season = Season(start_date=datetime.date(2025, 9, 1), end_date=datetime.date(2026, 8, 31)) self.assertEqual(str(season), "Season '25 - '26") class SeasonIsCurrentTest(TestCase): def setUp(self): today = timezone.now().date() self.season = Season.objects.create( start_date=today - datetime.timedelta(days=30), end_date=today + datetime.timedelta(days=30), ) def test_is_current_true(self): self.assertTrue(self.season.is_current) def test_is_current_false_past(self): past = Season.objects.create(start_date=datetime.date(2020, 1, 1), end_date=datetime.date(2020, 12, 31)) self.assertFalse(past.is_current) def test_is_current_false_future(self): future = Season.objects.create(start_date=datetime.date(2099, 1, 1), end_date=datetime.date(2099, 12, 31)) self.assertFalse(future.is_current) class SeasonDateRangeTest(TestCase): def test_date_range(self): start, end = datetime.date(2025, 9, 1), datetime.date(2026, 8, 31) season = Season(start_date=start, end_date=end) self.assertEqual(season.date_range, (start, end)) class SeasonForDateTest(TestCase): def setUp(self): self.start = datetime.date(2025, 9, 1) self.end = datetime.date(2026, 8, 31) self.season = Season.objects.create(start_date=self.start, end_date=self.end) def test_for_date_returns_season(self): self.assertEqual(Season.for_date(datetime.date(2026, 1, 15)), self.season) def test_for_date_values_only(self): self.assertEqual(Season.for_date(datetime.date(2026, 1, 15), values_only=True), (self.start, self.end)) def test_for_date_defaults_to_today(self): today = timezone.now().date() season_today = Season.objects.create( start_date=today - datetime.timedelta(days=1), end_date=today + datetime.timedelta(days=364), ) self.assertEqual(Season.for_date(), season_today) class SeasonGenerateDefaultTest(TestCase): def test_generate_year_duration(self): season = Season.generate_default(day=1, month=9, duration="1y") self.assertEqual(season.start_date, datetime.date(2026, 9, 1)) self.assertEqual(season.end_date, datetime.date(2027, 8, 31)) def test_generate_month_duration(self): season = Season.generate_default(day=1, month=9, duration="3m") self.assertEqual(season.start_date, datetime.date(2026, 9, 1)) self.assertEqual(season.end_date, datetime.date(2026, 11, 30)) def test_generate_invalid_duration_raises(self): with self.assertRaises(ValueError): Season.generate_default(day=1, month=9, duration="invalid") def test_generate_persists_to_db(self): Season.generate_default(day=1, month=9, duration="1y") self.assertEqual(Season.objects.count(), 1) class SeasonAddMonthsTest(TestCase): def test_add_months_normal(self): self.assertEqual(Season._add_months(datetime.date(2025, 1, 1), 3), datetime.date(2025, 4, 1)) def test_add_months_year_rollover(self): self.assertEqual(Season._add_months(datetime.date(2025, 11, 1), 3), datetime.date(2026, 2, 1)) def test_add_months_day_clamp(self): self.assertEqual(Season._add_months(datetime.date(2025, 1, 31), 1), datetime.date(2025, 2, 28)) def test_add_months_twelve(self): self.assertEqual(Season._add_months(datetime.date(2025, 9, 1), 12), datetime.date(2026, 9, 1)) # --------------------------------------------------------------------------- # TeamRole # --------------------------------------------------------------------------- class TeamRoleStrTest(TestCase): def test_str(self): role = TeamRole(name="Coach", abbreviation="C") self.assertEqual(str(role), "Coach (C)") def test_default_flags(self): role = TeamRole.objects.create(name="Player", abbreviation="P") self.assertFalse(role.staff_role) self.assertFalse(role.admin_role) self.assertEqual(role.sort_order, 10) # --------------------------------------------------------------------------- # Team # --------------------------------------------------------------------------- class TeamStrTest(TestCase): def test_str(self): team = Team(name="Red Dragons") self.assertEqual(str(team), "Red Dragons") class TeamInitialsTest(TestCase): def test_single_word(self): self.assertEqual(Team(name="Falcons").initials, "F") def test_two_words(self): self.assertEqual(Team(name="Red Dragons").initials, "RD") def test_more_than_two_words_uses_first_two(self): self.assertEqual(Team(name="The Red Dragons").initials, "TR") class TeamGetShortNameTest(TestCase): def test_returns_short_name_when_set(self): team = Team(name="Red Dragons", short_name="RD") self.assertEqual(team.get_short_name(), "RD") def test_falls_back_to_name_when_none(self): team = Team(name="Red Dragons", short_name=None) self.assertEqual(team.get_short_name(), "Red Dragons") def test_falls_back_to_name_when_empty_string(self): team = Team(name="Red Dragons", short_name="") self.assertEqual(team.get_short_name(), "Red Dragons") class TeamMemberCountTest(TestCase): def setUp(self): today = timezone.now().date() self.season = Season.objects.create( start_date=today - datetime.timedelta(days=30), end_date=today + datetime.timedelta(days=335), ) self.team = make_team() self.role = make_role() self.member1 = make_member("m1@test.com", "Alice", "One") self.member2 = make_member("m2@test.com", "Bob", "Two") def test_member_count(self): TeamMembership.objects.create(team=self.team, member=self.member1, season=self.season, role=self.role) TeamMembership.objects.create(team=self.team, member=self.member2, season=self.season, role=self.role) self.assertEqual(self.team.member_count, 2) def test_member_count_zero_when_empty(self): self.assertEqual(self.team.member_count, 0) # --------------------------------------------------------------------------- # TeamMembership # --------------------------------------------------------------------------- class TeamMembershipStrTest(TestCase): def setUp(self): today = timezone.now().date() self.season = Season.objects.create( start_date=today - datetime.timedelta(days=30), end_date=today + datetime.timedelta(days=335), ) self.team = make_team("Blue Hawks") self.role = make_role("Forward", "F") self.member = make_member("player@test.com", "John", "Doe") self.membership = TeamMembership.objects.create( team=self.team, member=self.member, season=self.season, role=self.role ) def test_str(self): self.assertEqual(str(self.membership), "Blue Hawks - John Doe (F)") def test_unique_number_constraint(self): from django.db import IntegrityError member2 = make_member("player2@test.com", "Jane", "Doe") TeamMembership.objects.create(team=self.team, member=member2, season=self.season, role=self.role, number=7) with self.assertRaises(IntegrityError): TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, role=self.role, number=7) def test_captain_default_false(self): self.assertFalse(self.membership.captain) self.assertFalse(self.membership.alternate_captain) # --------------------------------------------------------------------------- # TeamPicture # --------------------------------------------------------------------------- class TeamPictureStrTest(TestCase): def setUp(self): self.season = Season.objects.create( start_date=datetime.date(2025, 9, 1), end_date=datetime.date(2026, 8, 31), ) self.team = make_team("Green Eagles") self.picture = TeamPicture(team=self.team, season=self.season, picture="teams/picture/green-eagles/2025/photo.jpg") def test_str(self): self.assertEqual(str(self.picture), "Green Eagles - 2025")