from redmine_reporter.utils import ( get_month_name_from_range, get_version, hours_to_human, ) def test_hours_to_human_zero(): assert hours_to_human(0) == "0ч" assert hours_to_human(-1) == "0ч" def test_hours_to_human_whole_hours(): assert hours_to_human(1.0) == "1ч" assert hours_to_human(8.0) == "8ч" def test_hours_to_human_minutes_only(): assert hours_to_human(0.75) == "45м" assert hours_to_human(0.5) == "30м" def test_hours_to_human_mixed(): assert hours_to_human(2.5) == "2ч 30м" assert hours_to_human(1.5) == "1ч 30м" def test_hours_to_human_rounding(): assert hours_to_human(3.1666) == "3ч 10м" # 190 минут -> 3ч 10м def test_get_month_name_from_range(): assert get_month_name_from_range("2026-01-01", "2026-01-31") == "Январь" assert get_month_name_from_range("2025-12-01", "2026-02-15") == "Февраль" def test_get_month_name_from_range_all_months(): months = [ "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь", ] for i, name in enumerate(months, start=1): to_date = f"2026-{i:02d}-01" assert get_month_name_from_range("2026-01-01", to_date) == name def test_get_month_name_from_range_invalid_fallback(): """Невалидная дата -- возвращается 'Январь'.""" assert get_month_name_from_range("invalid", "also_invalid") == "Январь" def test_get_version_with_attribute(): class MockIssue: fixed_version = "v2.5.0" assert get_version(MockIssue()) == "v2.5.0" def test_get_version_without_attribute(): class MockIssue: pass assert get_version(MockIssue()) == "" def test_get_version_none_attribute(): class MockIssue: fixed_version = None assert get_version(MockIssue()) == "" def test_get_version_with_redminelib_version_object(): """redminelib Version: str() возвращает ID, .name — человекочитаемое имя.""" class MockVersion: """Имитирует redminelib.resources.Version — str() даёт ID.""" def __init__(self, vid, name): self.id = vid self.name = name def __str__(self): return str(self.id) class MockIssue: fixed_version = MockVersion(42, "v2.5.0") assert get_version(MockIssue()) == "v2.5.0" def test_get_version_falls_back_to_str_when_no_name(): """Если у объекта версии нет .name — fallback на str().""" class MockVersionNoName: def __str__(self): return "fallback-id" class MockIssue: fixed_version = MockVersionNoName() assert get_version(MockIssue()) == "fallback-id"