from datetime import UTC, datetime, timedelta import pytest from glitchup_bot.services import digest_builder from glitchup_bot.services.sync_service import IssueSnapshot @pytest.mark.asyncio async def test_build_digest_aggregates_projects(monkeypatch): now = datetime.now(UTC) issues = [ IssueSnapshot( 1, "backend-production", "New backend issue", None, "error", "unresolved", now - timedelta(days=1), now, 12, True, None, "2026.03.20", ), IssueSnapshot( 2, "frontend-production", "Old frontend issue", None, "error", "unresolved", now - timedelta(days=10), now, 3, False, None, None, ), ] monkeypatch.setattr( digest_builder, "_load_issues", lambda *args, **kwargs: _async_value(issues) ) text = await digest_builder.build_digest() assert "новых групп проблем: 1" in text assert "regressions: 1" in text assert "старых групп > 7 дней: 1" in text assert "backend-production" in text assert "Old frontend issue" in text assert "12 событий" in text @pytest.mark.asyncio async def test_build_today_summary_limits_to_today(monkeypatch): now = datetime.now(UTC) issues = [ IssueSnapshot( 1, "backend-production", "Today issue", None, "error", "unresolved", now - timedelta(hours=2), now, 2, False, None, None, ), IssueSnapshot( 2, "backend-production", "Old issue", None, "error", "unresolved", now - timedelta(days=2), now, 1, False, None, None, ), ] monkeypatch.setattr( digest_builder, "_load_issues", lambda *args, **kwargs: _async_value(issues) ) text = await digest_builder.build_today_summary() assert "Сегодня: 1 групп проблем" in text assert "событий за сегодня: 2" in text assert "Today issue" in text assert "Old issue" not in text @pytest.mark.asyncio async def test_build_project_summary(monkeypatch): now = datetime.now(UTC) issues = [ IssueSnapshot( 1, "backend-production", "Project issue", None, "error", "unresolved", now, now, 5, False, "https://glitchtip.example.com/issues/1", None, ) ] monkeypatch.setattr( digest_builder, "_load_issues", lambda *args, **kwargs: _async_value(issues) ) text = await digest_builder.build_project_summary("backend-production") assert "backend-production" in text assert "Project issue" in text assert "всего событий: 5" in text @pytest.mark.asyncio async def test_build_top_and_stale(monkeypatch): now = datetime.now(UTC) issues = [ IssueSnapshot( 1, "backend-production", "Loud issue", None, "error", "unresolved", now - timedelta(days=9), now, 99, False, None, None, ), IssueSnapshot( 2, "frontend-production", "Quiet issue", None, "error", "unresolved", now - timedelta(days=1), now, 3, False, None, None, ), ] monkeypatch.setattr( digest_builder, "_load_issues", lambda *args, **kwargs: _async_value(issues) ) top_text = await digest_builder.build_top_issues() stale_text = await digest_builder.build_stale_issues() assert "Loud issue" in top_text assert "99" in top_text assert "Loud issue" in stale_text assert "9 дн." in stale_text @pytest.mark.asyncio async def test_build_release_summary_and_detail(monkeypatch): now = datetime.now(UTC) issues = [ IssueSnapshot( 1, "backend-production", "Release issue", None, "error", "unresolved", now, now, 15, True, None, "2026.03.27", ), IssueSnapshot( 2, "frontend-production", "Another issue", None, "error", "unresolved", now, now, 5, False, None, "2026.03.27", ), ] monkeypatch.setattr( digest_builder, "_load_issues", lambda *args, **kwargs: _async_value(issues) ) summary = await digest_builder.build_release_summary() detail = await digest_builder.build_release_detail("2026.03.27") assert "2026.03.27" in summary assert "2 групп" in summary assert "Release issue" in detail @pytest.mark.asyncio async def test_build_today_summary_groups_similar_titles(monkeypatch): now = datetime.now(UTC) issues = [ IssueSnapshot( 1, "backend-production", ( "2026-03-30 10:59:52.605 | ERROR | logging:callHandlers:1762 - " "The garbage collector is trying to clean up" ), None, "error", "unresolved", now - timedelta(hours=2), now - timedelta(minutes=5), 1, False, None, None, ), IssueSnapshot( 2, "backend-production", ( "2026-03-30 09:59:26.932 | ERROR | logging:callHandlers:1762 - " "The garbage collector is trying to clean up" ), None, "error", "unresolved", now - timedelta(hours=1), now, 1, False, None, None, ), ] monkeypatch.setattr( digest_builder, "_load_issues", lambda *args, **kwargs: _async_value(issues) ) text = await digest_builder.build_today_summary() assert "Сегодня: 1 групп проблем" in text assert "событий за сегодня: 2" in text assert "2 повторов" in text assert "The garbage collector is trying to clean up" in text async def _async_value(value): return value