import pytest from apps.gamification.rules import earned_badges, level_progress, level_for_points pytestmark = pytest.mark.unit @pytest.mark.parametrize( ("points", "level_id"), [ (0, "companion"), (29, "companion"), (30, "contributor"), (149, "contributor"), (150, "ally"), (300, "ally"), (750, "influencer"), (1500, "pioneer"), ], ) def test_level_for_points_uses_fixed_lifetime_thresholds(points, level_id): assert level_for_points(points)["id"] == level_id def test_level_progress_reports_points_needed_and_percent_to_next_level(): progress = level_progress(90) assert progress["current_level"]["id"] == "contributor" assert progress["next_level"]["id"] == "ally" assert progress["points_to_next"] == 60 assert progress["progress_percent"] == 50 def test_highest_level_has_no_next_level_or_remaining_progress(): progress = level_progress(2000) assert progress["current_level"]["id"] == "pioneer" assert progress["next_level"] is None assert progress["points_to_next"] == 0 assert progress["progress_percent"] == 100 def test_earned_badges_include_every_reached_global_and_activity_milestone(): badges = earned_badges( total_points=300, activity_counts={"attendance": 5, "posts": 25, "comments": 4, "likes": 50}, ) badge_ids = {badge["id"] for badge in badges} assert {"level-companion", "level-contributor", "level-ally"} <= badge_ids assert { "attendance-1", "attendance-5", "post-1", "post-5", "post-10", "post-25", "comment-1", "likes-1", "likes-10", "likes-50", } <= badge_ids assert "comment-5" not in badge_ids assert not any(badge_id.startswith("save-") for badge_id in badge_ids)