Files
AdventureLog/backend/server/integrations/tests/test_immich_view.py

144 lines
5.6 KiB
Python

from unittest.mock import MagicMock, patch
from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.test import APIRequestFactory, force_authenticate
from integrations.models import ImmichIntegration
from integrations.views.immich_view import ImmichIntegrationView
User = get_user_model()
class ImmichViewTests(TestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.user = User.objects.create_user(username='immich-user', password='test-pass')
self.integration = ImmichIntegration.objects.create(
user=self.user,
server_url='http://immich.example.com/api',
api_key='test-api-key',
)
self.view = ImmichIntegrationView.as_view({'get': 'search'})
self.album_view = ImmichIntegrationView.as_view({'get': 'album'})
@patch('integrations.views.immich_view.requests.post')
def test_search_by_date_uses_iso8601_datetime_range(self, mock_post):
mock_response = MagicMock()
mock_response.ok = True
mock_response.json.return_value = {
'assets': {
'items': [{'id': 'asset-1'}],
}
}
mock_post.return_value = mock_response
request = self.factory.get('/api/integrations/immich/search/', {'date': '2024-06-15'})
force_authenticate(request, user=self.user)
response = self.view(request)
self.assertEqual(response.status_code, 200)
mock_post.assert_called_once()
_, kwargs = mock_post.call_args
self.assertEqual(kwargs['json']['takenAfter'], '2024-06-15T00:00:00.000Z')
self.assertEqual(kwargs['json']['takenBefore'], '2024-06-16T00:00:00.000Z')
self.assertEqual(kwargs['json']['visibility'], 'timeline')
self.assertEqual(kwargs['json']['page'], 1)
self.assertEqual(kwargs['json']['size'], 1000)
@patch('integrations.views.immich_view.requests.get')
@patch('integrations.views.immich_view.requests.post')
def test_album_falls_back_to_metadata_search_without_inline_assets(self, mock_post, mock_get):
mock_get_response = MagicMock()
mock_get_response.json.return_value = {
'id': 'album-1',
'albumName': 'Trip Photos',
}
mock_get.return_value = mock_get_response
mock_post_response = MagicMock()
mock_post_response.ok = True
mock_post_response.json.return_value = {
'assets': {
'items': [{'id': 'asset-1'}, {'id': 'asset-2'}],
}
}
mock_post.return_value = mock_post_response
request = self.factory.get('/api/integrations/immich/albums/album-1/')
force_authenticate(request, user=self.user)
response = self.album_view(request, albumid='album-1')
self.assertEqual(response.status_code, 200)
mock_post.assert_called_once()
_, kwargs = mock_post.call_args
self.assertEqual(kwargs['json']['albumIds'], ['album-1'])
self.assertEqual(kwargs['json']['visibility'], 'timeline')
self.assertEqual(len(response.data['results']), 2)
@patch('integrations.views.immich_view.requests.get')
@patch('integrations.views.immich_view.requests.post')
def test_album_metadata_search_paginates_past_first_page(self, mock_post, mock_get):
mock_get_response = MagicMock()
mock_get_response.json.return_value = {
'id': 'album-1',
'albumName': 'Large Album',
}
mock_get.return_value = mock_get_response
first_page_response = MagicMock()
first_page_response.ok = True
first_page_response.json.return_value = {
'assets': {
'items': [{'id': f'asset-{index}'} for index in range(1000)],
'nextPage': '2',
}
}
second_page_response = MagicMock()
second_page_response.ok = True
second_page_response.json.return_value = {
'assets': {
'items': [{'id': 'asset-1000'}, {'id': 'asset-1001'}],
'nextPage': None,
}
}
mock_post.side_effect = [first_page_response, second_page_response]
request = self.factory.get('/api/integrations/immich/albums/album-1/')
force_authenticate(request, user=self.user)
response = self.album_view(request, albumid='album-1')
self.assertEqual(response.status_code, 200)
self.assertEqual(mock_post.call_count, 2)
first_call_kwargs = mock_post.call_args_list[0].kwargs
second_call_kwargs = mock_post.call_args_list[1].kwargs
self.assertEqual(first_call_kwargs['json']['page'], 1)
self.assertEqual(second_call_kwargs['json']['page'], 2)
self.assertEqual(len(response.data['results']), 25)
self.assertEqual(response.data['count'], 1002)
@patch('integrations.views.immich_view.requests.get')
def test_album_uses_inline_assets_when_available(self, mock_get):
mock_get_response = MagicMock()
mock_get_response.json.return_value = {
'id': 'album-1',
'albumName': 'Trip Photos',
'assets': [{'id': 'asset-legacy-1'}],
}
mock_get.return_value = mock_get_response
request = self.factory.get('/api/integrations/immich/albums/album-1/')
force_authenticate(request, user=self.user)
with patch('integrations.views.immich_view.requests.post') as mock_post:
response = self.album_view(request, albumid='album-1')
self.assertEqual(response.status_code, 200)
mock_post.assert_not_called()
self.assertEqual(len(response.data['results']), 1)