Updated backend to include stat endpoint that gives hourly results instead of daily

This commit is contained in:
alexjanousekGSA
2025-02-24 12:26:22 -05:00
parent 9b378230da
commit 9bb8b31b65
6 changed files with 300 additions and 8 deletions

View File

@@ -7,6 +7,7 @@ from app.dao.date_util import (
get_calendar_year_for_datetime,
get_month_start_and_end_date_in_utc,
get_new_years,
generate_hourly_range,
)
@@ -75,3 +76,44 @@ def test_get_month_start_and_end_date_in_utc(month, year, expected_start, expect
)
def test_get_calendar_year_for_datetime(dt, fy):
assert get_calendar_year_for_datetime(dt) == fy
def test_generate_hourly_range_with_end_date():
start_date = datetime(2025, 2, 18, 12, 0)
end_date = datetime(2025, 2, 18, 15, 0)
result = list(generate_hourly_range(start_date, end_date=end_date))
expected = [
datetime(2025, 2, 18, 12, 0),
datetime(2025, 2, 18, 13, 0),
datetime(2025, 2, 18, 14, 0),
datetime(2025, 2, 18, 15, 0),
]
assert result == expected, f"Expected {expected}, but got {result}"
def test_generate_hourly_range_with_hours():
start_date = datetime(2025, 2, 18, 12, 0)
result = list(generate_hourly_range(start_date, hours=3))
expected = [
datetime(2025, 2, 18, 12, 0),
datetime(2025, 2, 18, 13, 0),
datetime(2025, 2, 18, 14, 0),
]
assert result == expected, f"Expected {expected}, but got {result}"
def test_generate_hourly_range_with_zero_hours():
start_date = datetime(2025, 2, 18, 12, 0)
result = list(generate_hourly_range(start_date, hours=0))
assert result == [], f"Expected an empty list, but got {result}"
def test_generate_hourly_range_with_end_date_before_start():
start_date = datetime(2025, 2, 18, 12, 0)
end_date = datetime(2025, 2, 18, 10, 0)
result = list(generate_hourly_range(start_date, end_date=end_date))
assert result == [], f"Expected empty list, but got {result}"

View File

@@ -0,0 +1,109 @@
from datetime import datetime
from unittest.mock import Mock
import pytest
from app.dao.services_dao import get_specific_hours_stats
from app.enums import StatisticsType
from app.models import TemplateType
def generate_expected_hourly_output(requested_sms_hours):
"""
Generates expected output only for hours where notifications exist.
Removes empty hours from the output to match function behavior.
"""
output = {}
for hour in requested_sms_hours:
output[hour] = {
TemplateType.SMS: {
StatisticsType.REQUESTED: 1,
StatisticsType.DELIVERED: 0,
StatisticsType.FAILURE: 0,
StatisticsType.PENDING: 0,
},
TemplateType.EMAIL: {
StatisticsType.REQUESTED: 0,
StatisticsType.DELIVERED: 0,
StatisticsType.FAILURE: 0,
StatisticsType.PENDING: 0,
},
}
return output
def create_mock_notification(notification_type, status, timestamp, count=1):
"""
Creates a mock notification object with the required attributes.
"""
mock = Mock()
mock.notification_type = notification_type
mock.status = status
mock.timestamp = timestamp.replace(minute=0, second=0, microsecond=0)
mock.count = count
return mock
test_cases = [
# Single notification at 14:00 (Only 14:00 is expected in output)
(
[create_mock_notification(
TemplateType.SMS,
StatisticsType.REQUESTED,
datetime(2025, 2, 18, 14, 15, 0),
)],
datetime(2025, 2, 18, 12, 0),
6,
generate_expected_hourly_output(
["2025-02-18T14:00:00Z"]
),
),
# Notification at 17:59 (Only 17:00 is expected in output)
(
[create_mock_notification(
TemplateType.SMS,
StatisticsType.REQUESTED,
datetime(2025, 2, 18, 17, 59, 59),
)],
datetime(2025, 2, 18, 15, 0),
3,
generate_expected_hourly_output(
["2025-02-18T17:00:00Z"]
),
),
# No notifications at all (Expect empty `{}`)
(
[],
datetime(2025, 2, 18, 10, 0),
4,
{},
),
# Two notifications at 09:00 and 11:00 (Only those hours expected)
(
[
create_mock_notification(TemplateType.SMS, StatisticsType.REQUESTED, datetime(2025, 2, 18, 9, 30, 0)),
create_mock_notification(TemplateType.SMS, StatisticsType.REQUESTED, datetime(2025, 2, 18, 11, 45, 0)),
],
datetime(2025, 2, 18, 8, 0),
5,
generate_expected_hourly_output(
["2025-02-18T09:00:00Z", "2025-02-18T11:00:00Z"]
),
),
]
@pytest.mark.parametrize(
"mocked_notifications, start_date, hours, expected_output",
test_cases,
)
def test_get_specific_hours(mocked_notifications, start_date, hours, expected_output):
"""
Tests get_specific_hours_stats to ensure it correctly aggregates hourly statistics.
"""
results = get_specific_hours_stats(
mocked_notifications,
start_date,
hours=hours
)
assert results == expected_output, f"Expected {expected_output}, but got {results}"