Test external calendar caching

This commit is contained in:
Antoine Bartuccio 2025-01-05 01:32:54 +01:00
parent fa7f5d24b0
commit eb3db134f8

View File

@ -1,11 +1,15 @@
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
from typing import Callable
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
import pytest import pytest
from django.conf import settings from django.conf import settings
from django.http import HttpResponse
from django.test.client import Client from django.test.client import Client
from django.urls import reverse from django.urls import reverse
from django.utils import timezone
from com.calendar import IcsCalendar from com.calendar import IcsCalendar
@ -20,13 +24,29 @@ class MockResponse:
return self.value.encode("utf8") return self.value.encode("utf8")
def accel_redirect_to_file(response: HttpResponse) -> Path | None:
redirect = Path(response.headers.get("X-Accel-Redirect", ""))
if not redirect.is_relative_to(Path("/") / settings.MEDIA_ROOT.stem):
return None
return settings.MEDIA_ROOT / redirect.relative_to(
Path("/") / settings.MEDIA_ROOT.stem
)
@pytest.mark.django_db @pytest.mark.django_db
class TestExternalCalendar: class TestExternalCalendar:
@pytest.fixture @pytest.fixture
def mock_request(self): def mock_request(self):
request = MagicMock() mock = MagicMock()
with patch("urllib3.request", request): with patch("urllib3.request", mock):
yield request yield mock
@pytest.fixture
def mock_current_time(self):
mock = MagicMock()
original = timezone.now
with patch("django.utils.timezone.now", mock):
yield mock, original
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def clear_cache(self): def clear_cache(self):
@ -44,11 +64,45 @@ class TestExternalCalendar:
mock_request.return_value = external_response mock_request.return_value = external_response
response = client.get(reverse("api:calendar_external")) response = client.get(reverse("api:calendar_external"))
assert response.status_code == 200 assert response.status_code == 200
redirect = Path(response.headers.get("X-Accel-Redirect", "")) out_file = accel_redirect_to_file(response)
assert redirect.is_relative_to(Path("/") / settings.MEDIA_ROOT.stem) assert out_file is not None
out_file = settings.MEDIA_ROOT / redirect.relative_to(
Path("/") / settings.MEDIA_ROOT.stem
)
assert out_file.exists() assert out_file.exists()
with open(out_file, "r") as f: with open(out_file, "r") as f:
assert f.read() == external_response.value assert f.read() == external_response.value
def test_fetch_caching(
self,
client: Client,
mock_request: MagicMock,
mock_current_time: tuple[MagicMock, Callable[[], datetime]],
):
fake_current_time, original_timezone = mock_current_time
start_time = original_timezone()
fake_current_time.return_value = start_time
external_response = MockResponse(200, "Definitely an ICS")
mock_request.return_value = external_response
with open(
accel_redirect_to_file(client.get(reverse("api:calendar_external"))), "r"
) as f:
assert f.read() == external_response.value
mock_request.return_value = MockResponse(200, "This should be ignored")
with open(
accel_redirect_to_file(client.get(reverse("api:calendar_external"))), "r"
) as f:
assert f.read() == external_response.value
mock_request.assert_called_once()
fake_current_time.return_value = start_time + timedelta(hours=1, seconds=1)
external_response = MockResponse(200, "This won't be ignored")
mock_request.return_value = external_response
with open(
accel_redirect_to_file(client.get(reverse("api:calendar_external"))), "r"
) as f:
assert f.read() == external_response.value
assert mock_request.call_count == 2