281 lines
6.7 KiB
Python
281 lines
6.7 KiB
Python
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
|