From 6f7dba89cf10e9acab74ffe7a5bbd18ea9a4c893 Mon Sep 17 00:00:00 2001 From: ezkat <50319957+ezkat@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:47:49 +0200 Subject: [PATCH] Fix image processing --- resources/models/resource.py | 2 +- resources/tests/conftest.py | 42 ++++++++++++++++++- resources/tests/test_resource_api.py | 63 +++++++++++++++++++++++++--- resources/tests/utils.py | 20 +++++++++ 4 files changed, 119 insertions(+), 8 deletions(-) diff --git a/resources/models/resource.py b/resources/models/resource.py index 6619418ff..2d58a310d 100644 --- a/resources/models/resource.py +++ b/resources/models/resource.py @@ -1036,7 +1036,7 @@ def _process_image(self): save_kwargs = {} with Image.open(self.image) as img: if img.size > (1920, 1080): - img.thumbnail((1920, 1080), Image.ANTIALIAS) + img.thumbnail((1920, 1080), Image.LANCZOS) self.cropping = None setattr(self, '_processing_required', True) elif img.size < (128, 128): diff --git a/resources/tests/conftest.py b/resources/tests/conftest.py index 4f5202505..676a63909 100644 --- a/resources/tests/conftest.py +++ b/resources/tests/conftest.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import pytest import datetime +import base64 from django.contrib.auth import get_user_model from django.contrib.auth.models import Group from django.utils import timezone @@ -14,6 +15,7 @@ from resources.models import ReservationMetadataSet, ReservationMetadataField from munigeo.models import Municipality from maintenance.models import MaintenanceMessage, MaintenanceMode +from .utils import get_test_image_data, get_test_image_payload @pytest.fixture def api_client(): @@ -668,4 +670,42 @@ def resource_with_active_reservations(resource_in_unit): end=datetime.datetime(year=2115, month=4, day=4, hour=i+1, minute=0, second=0)) \ for i in range(1,11) ]) - return resource_in_unit \ No newline at end of file + return resource_in_unit + + +@pytest.fixture +def resource_create_data( + purpose, test_unit, + space_resource_type): + image = get_test_image_data() + return { + "public": True, + "purposes": [ + purpose.id + ], + "name": { + "fi": "Test Resource API", + "en": "Test Resource API", + "sv": "Test Resource API", + }, + "description": { + "fi": "Test Resource created through API", + "en": "Test Resource created through API", + "sv": "Test Resource created through API" + }, + "reservation_info": { + "fi": "Test Resource reservation information", + "en": "Test Resource reservation information", + "sv": "Test Resource reservation information" + }, + "need_manual_confirmation": False, + "min_period": "00:30:00", + "max_period": "01:00:00", + "slot_size": "00:15:00", + "authentication": "strong", + "people_capacity": "10", + "terms_of_use": [], + "unit": test_unit.pk, + "type": space_resource_type.pk, + "images": [get_test_image_payload(image=image)] + } diff --git a/resources/tests/test_resource_api.py b/resources/tests/test_resource_api.py index a106e92ea..8a6ca7628 100644 --- a/resources/tests/test_resource_api.py +++ b/resources/tests/test_resource_api.py @@ -1,5 +1,6 @@ import datetime import pytest +import base64 from copy import deepcopy from django.urls import reverse from django.contrib.auth import get_user_model @@ -10,13 +11,21 @@ from freezegun import freeze_time from guardian.shortcuts import assign_perm, remove_perm -from resources.models.resource import Resource +from resources.models.resource import ( + Resource, ResourceImage, InvalidImage +) from ..enums import UnitAuthorizationLevel, UnitGroupAuthorizationLevel -from resources.models import (Day, Equipment, Period, Reservation, ReservationMetadataSet, ResourceEquipment, - ResourceType, Unit, UnitAuthorization, UnitGroup) -from .utils import assert_response_objects, check_only_safe_methods_allowed, is_partial_dict_in_list, MAX_QUERIES - +from resources.models import ( + Day, Equipment, Period, Reservation, + ReservationMetadataSet, ResourceEquipment, + ResourceType, Unit, UnitGroup +) +from .utils import ( + assert_response_objects, check_only_safe_methods_allowed, + is_partial_dict_in_list, MAX_QUERIES, + get_test_image_data, get_test_image_payload +) @pytest.fixture def list_url(): @@ -1332,4 +1341,46 @@ def test_resource_mass_cancel_reservation_permitted_for_admin_user( response = staff_api_client.delete(url, data=payload, HTTP_ACCEPT_LANGUAGE='en') assert response.status_code == 204 - assert resource_with_active_reservations.reservations.current().count() == 0 \ No newline at end of file + assert resource_with_active_reservations.reservations.current().count() == 0 + + +@pytest.mark.django_db +@pytest.mark.parametrize('image_size, gets_processed', ( + ((128, 128), False), + ((1980, 1200), True), +)) +def test_resource_create_through_api( + staff_api_client, staff_user, + resource_create_data, list_url, + image_size, gets_processed +): + url = f'{list_url[:-1]}/new/' + assign_perm('resources.add_resource', staff_user) + staff_api_client.force_authenticate(user=staff_user) + image = get_test_image_data(image_size) + resource_create_data['images'] = [get_test_image_payload(image)] + response = staff_api_client.post(url, data=resource_create_data) + assert response.status_code == 201 + resource = Resource.objects.get(pk=response.data['id']) + + resource_image = resource.images.first().image + + if gets_processed: + assert (resource_image.width, resource_image.height) < (1921, 1081) + else: + assert (resource_image.width, resource_image.height) == image_size + + +@pytest.mark.django_db +def test_resource_create_through_api_invalid_image( + staff_api_client, staff_user, + resource_create_data, list_url +): + image = get_test_image_data((64, 64)) + + url = f'{list_url[:-1]}/new/' + assign_perm('resources.add_resource', staff_user) + staff_api_client.force_authenticate(user=staff_user) + resource_create_data['images'] = [get_test_image_payload(image)] + with pytest.raises(InvalidImage): + staff_api_client.post(url, data=resource_create_data) diff --git a/resources/tests/utils.py b/resources/tests/utils.py index bede61185..1a629b7fd 100644 --- a/resources/tests/utils.py +++ b/resources/tests/utils.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import datetime +import base64 from django.core.exceptions import ValidationError from django.core.files.base import ContentFile @@ -197,3 +198,22 @@ def check_keys(data, expected_keys): def is_partial_dict_in_list(partial, dicts): partial_items = partial.items() return any([partial_items <= d.items() for d in dicts]) + + +def get_test_image_payload( + image, *, + type = "main", + caption = "test caption", + name = "test_image.jpg"): + return { + "type": type, + "caption": { + "fi": caption, + "sv": caption, + "en": caption + }, + "image": { + "name": name, + "data": base64.b64encode(image).decode() + } + }