from datetime import datetime, timedelta, timezone import pytest from ninja.errors import HttpError from apps.analytics.api.views import ( _auto_granularity, _filters_payload, _normalize_entry_year, _parse_boundary, _point_group_from_rows, _require_staff, ) pytestmark = pytest.mark.unit @pytest.mark.parametrize( ("value", "expected"), [(None, "نامشخص"), ("۱۴۰۴", "1404"), ("404", "1404"), ("94", "1394"), ("bad", "نامشخص")], ) def test_year_normalization(value, expected): assert _normalize_entry_year(value) == expected def test_date_filters_validate_and_choose_granularity(): assert _parse_boundary(None) is None with pytest.raises(HttpError): _parse_boundary("not-a-date") start = _parse_boundary("2026-01-01") end = _parse_boundary("2026-01-31", is_end=True) assert start < end assert _auto_granularity(start, end) == "day" assert _auto_granularity(start, start + timedelta(days=90)) == "week" assert _auto_granularity(None, end) == "month" assert _filters_payload(start, end, include_granularity=True)["granularity"] == "day" def test_point_group_sorts_and_counts_remainder(): result = _point_group_from_rows( [{"label": "B", "value": 1}, {"label": "A", "value": 3}, {"label": None, "value": 0}], limit=1, ) assert result["top_items"] == [{"label": "A", "value": 3}] assert result["other_count"] == 2 assert result["total_count"] == 3 def test_staff_guard_rejects_anonymous_and_nonstaff(): with pytest.raises(HttpError): _require_staff(None) with pytest.raises(HttpError): _require_staff(type("User", (), {"is_staff": False, "is_superuser": False})()) _require_staff(type("User", (), {"is_staff": True, "is_superuser": False})())