Files
RosterChief/teams/tests.py
Bernard Siebens 076a9cacbc feat(teams): add teams app with roster and staff assignments
Introduce the teams app: Team and Position (both club-scoped, with
per-club unique names), TeamMembership (season-scoped roster with jersey
number + captain flags, unique member and jersey per team/season), and
StaffAssignment (coaching/staff, filtered to staff positions). All
uniqueness expressed as UniqueConstraints.

Register every model in the admin (with roster + staff inlines on Team)
and cover the models with tests. Fix two model bugs surfaced by the
system check: StaffAssignment.position reused TeamMembership's reverse
accessor (Position.team_memberships) and duplicated its constraint name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 16:47:52 +02:00

113 lines
5.2 KiB
Python

import datetime
from django.db import IntegrityError
from django.db.models import ProtectedError
from django.test import TestCase
from club.models import Club, Season
from members.models import Member
from .models import Position, StaffAssignment, Team, TeamMembership
class TeamsTestCase(TestCase):
def setUp(self):
self.club = Club.objects.create(name="Ajax United", slug="ajax-united")
self.season = Season.objects.create(
club=self.club,
start_date=datetime.date(2026, 8, 1),
end_date=datetime.date(2027, 5, 31),
)
self.team = Team.objects.create(club=self.club, name="First Team", short_name="1st")
self.forward = Position.objects.create(club=self.club, name="Forward", short_name="FW")
self.coach = Position.objects.create(club=self.club, name="Head Coach", short_name="HC", staff_position=True)
self.member = Member.objects.create(first_name="Jane", last_name="Doe")
class TeamModelTests(TeamsTestCase):
def test_str_returns_name(self):
self.assertEqual(str(self.team), "First Team")
def test_team_name_is_unique_per_club(self):
with self.assertRaises(IntegrityError):
Team.objects.create(club=self.club, name="First Team", short_name="dup")
def test_same_team_name_allowed_in_other_club(self):
other = Club.objects.create(name="Rival FC", slug="rival-fc")
Team.objects.create(club=other, name="First Team", short_name="1st")
self.assertEqual(Team.objects.filter(name="First Team").count(), 2)
class PositionModelTests(TeamsTestCase):
def test_str_returns_name(self):
self.assertEqual(str(self.forward), "Forward")
def test_defaults(self):
self.assertFalse(self.forward.staff_position)
self.assertEqual(self.forward.ordering, 0)
def test_positions_ordered_by_ordering_then_name(self):
keeper = Position.objects.create(club=self.club, name="Keeper", short_name="GK", ordering=1)
ordered = list(Position.objects.filter(club=self.club).values_list("name", flat=True))
# ordering=0 entries first (alphabetical), then ordering=1.
self.assertEqual(ordered, ["Forward", "Head Coach", "Keeper"])
self.assertEqual(keeper.ordering, 1)
def test_position_name_is_unique_per_club(self):
with self.assertRaises(IntegrityError):
Position.objects.create(club=self.club, name="Forward", short_name="dup")
class TeamMembershipModelTests(TeamsTestCase):
def test_can_create_roster_entry(self):
entry = TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, position=self.forward, jersey_number=9)
self.assertEqual(entry.position, self.forward)
self.assertFalse(entry.is_captain)
self.assertEqual(str(entry), "First Team - Jane Doe")
self.assertEqual(list(self.team.roster.all()), [entry])
def test_member_is_unique_per_team_and_season(self):
TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, position=self.forward, jersey_number=9)
with self.assertRaises(IntegrityError):
TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, position=self.forward, jersey_number=10)
def test_jersey_number_is_unique_per_team_and_season(self):
TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, position=self.forward, jersey_number=9)
other = Member.objects.create(first_name="John", last_name="Smith")
with self.assertRaises(IntegrityError):
TeamMembership.objects.create(team=self.team, member=other, season=self.season, position=self.forward, jersey_number=9)
def test_season_is_protected_while_referenced(self):
TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, position=self.forward)
with self.assertRaises(ProtectedError):
self.season.delete()
class StaffAssignmentModelTests(TeamsTestCase):
def test_can_assign_staff(self):
assignment = StaffAssignment.objects.create(team=self.team, member=self.member, season=self.season, position=self.coach)
self.assertEqual(assignment.position, self.coach)
self.assertEqual(str(assignment), "First Team - Jane Doe")
self.assertEqual(list(self.team.staff_assignments.all()), [assignment])
def test_member_is_unique_per_team_and_season(self):
StaffAssignment.objects.create(team=self.team, member=self.member, season=self.season, position=self.coach)
with self.assertRaises(IntegrityError):
StaffAssignment.objects.create(team=self.team, member=self.member, season=self.season, position=self.coach)
def test_roster_and_staff_use_separate_reverse_accessors(self):
TeamMembership.objects.create(team=self.team, member=self.member, season=self.season, position=self.forward)
coach_member = Member.objects.create(first_name="Coach", last_name="Carter")
StaffAssignment.objects.create(team=self.team, member=coach_member, season=self.season, position=self.coach)
self.assertEqual(self.forward.team_memberships.count(), 1)
self.assertEqual(self.coach.staff_assignments.count(), 1)