| | """Unit tests for Profile models and repositories.""" |
| |
|
| | from __future__ import annotations |
| |
|
| | from datetime import date |
| | from decimal import Decimal |
| |
|
| | import pytest |
| | from django.db import IntegrityError |
| |
|
| | from apps.profiles.constants import COST_PER_CUBIC_YARD, ICE_PER_FOOT |
| | from apps.profiles.models import DailyProgress, Profile, WallSection |
| |
|
| |
|
| | @pytest.mark.django_db |
| | class TestProfileModel: |
| | """Test Profile model functionality.""" |
| |
|
| | def test_create_profile_success(self) -> None: |
| | """Test creating a profile with valid data.""" |
| | profile = Profile.objects.create( |
| | name="Northern Watch", |
| | team_lead="Jon Snow", |
| | is_active=True, |
| | ) |
| |
|
| | assert profile.id is not None |
| | assert profile.name == "Northern Watch" |
| | assert profile.team_lead == "Jon Snow" |
| | assert profile.is_active is True |
| | assert profile.created_at is not None |
| | assert profile.updated_at is not None |
| |
|
| | def test_profile_name_unique(self) -> None: |
| | """Test profile name must be unique.""" |
| | Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| |
|
| | with pytest.raises(IntegrityError): |
| | Profile.objects.create(name="Northern Watch", team_lead="Samwell Tarly") |
| |
|
| | def test_profile_str_representation(self) -> None: |
| | """Test profile string representation.""" |
| | profile = Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| |
|
| | assert str(profile) == "Northern Watch (led by Jon Snow)" |
| |
|
| |
|
| | @pytest.mark.django_db |
| | class TestWallSectionModel: |
| | """Test WallSection model functionality.""" |
| |
|
| | def test_create_wall_section_success(self) -> None: |
| | """Test creating a wall section with valid data.""" |
| | profile = Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| | wall_section = WallSection.objects.create( |
| | profile=profile, |
| | section_name="Tower 1-2", |
| | ) |
| |
|
| | assert wall_section.id is not None |
| | assert wall_section.profile == profile |
| | assert wall_section.section_name == "Tower 1-2" |
| |
|
| | def test_wall_section_str_representation(self) -> None: |
| | """Test wall section string representation.""" |
| | profile = Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| | wall_section = WallSection.objects.create( |
| | profile=profile, |
| | section_name="Tower 1-2", |
| | ) |
| |
|
| | assert str(wall_section) == "Tower 1-2 (Northern Watch)" |
| |
|
| |
|
| | @pytest.mark.django_db |
| | class TestDailyProgressModel: |
| | """Test DailyProgress model functionality.""" |
| |
|
| | def test_create_daily_progress_with_calculated_values(self) -> None: |
| | """Test creating daily progress with explicitly calculated ice and cost values.""" |
| | profile = Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| | wall_section = WallSection.objects.create( |
| | profile=profile, |
| | section_name="Tower 1-2", |
| | ) |
| |
|
| | feet_built = Decimal("10.00") |
| | ice_cubic_yards = feet_built * ICE_PER_FOOT |
| | cost_gold_dragons = ice_cubic_yards * COST_PER_CUBIC_YARD |
| |
|
| | progress = DailyProgress.objects.create( |
| | wall_section=wall_section, |
| | date=date(2025, 10, 20), |
| | feet_built=feet_built, |
| | ice_cubic_yards=ice_cubic_yards, |
| | cost_gold_dragons=cost_gold_dragons, |
| | ) |
| |
|
| | assert progress.ice_cubic_yards == Decimal("1950.00") |
| | assert progress.cost_gold_dragons == Decimal("3705000.00") |
| |
|
| | def test_daily_progress_unique_per_wall_section_and_date(self) -> None: |
| | """Test only one progress entry allowed per wall section per day.""" |
| | profile = Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| | wall_section = WallSection.objects.create( |
| | profile=profile, |
| | section_name="Tower 1-2", |
| | ) |
| |
|
| | DailyProgress.objects.create( |
| | wall_section=wall_section, |
| | date=date(2025, 10, 20), |
| | feet_built=Decimal("10.00"), |
| | ice_cubic_yards=Decimal("1950.00"), |
| | cost_gold_dragons=Decimal("3705000.00"), |
| | ) |
| |
|
| | with pytest.raises(IntegrityError): |
| | DailyProgress.objects.create( |
| | wall_section=wall_section, |
| | date=date(2025, 10, 20), |
| | feet_built=Decimal("5.00"), |
| | ice_cubic_yards=Decimal("975.00"), |
| | cost_gold_dragons=Decimal("1852500.00"), |
| | ) |
| |
|
| | def test_daily_progress_str_representation(self) -> None: |
| | """Test daily progress string representation.""" |
| | profile = Profile.objects.create(name="Northern Watch", team_lead="Jon Snow") |
| | wall_section = WallSection.objects.create( |
| | profile=profile, |
| | section_name="Tower 1-2", |
| | ) |
| |
|
| | progress = DailyProgress.objects.create( |
| | wall_section=wall_section, |
| | date=date(2025, 10, 20), |
| | feet_built=Decimal("10.00"), |
| | ice_cubic_yards=Decimal("1950.00"), |
| | cost_gold_dragons=Decimal("3705000.00"), |
| | ) |
| |
|
| | assert str(progress) == "Tower 1-2: 10.00 ft on 2025-10-20" |
| |
|