| """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" |
|
|