diff options
author | Matthew Lemon <y@yulqen.org> | 2024-05-15 19:09:26 +0100 |
---|---|---|
committer | Matthew Lemon <y@yulqen.org> | 2024-05-15 19:09:26 +0100 |
commit | ae42defca04b78516712c64be27ee5f91e1da03d (patch) | |
tree | e5a5b32993432668845b2e9675b728eb7a5e604e /pyblackbird_cc/resources | |
parent | a3826ecdf0bcb097446e97ecc88166a5606ce471 (diff) |
Migrates tests over from old project
Diffstat (limited to 'pyblackbird_cc/resources')
-rw-r--r-- | pyblackbird_cc/resources/tests/__init__.py | 0 | ||||
-rw-r--r-- | pyblackbird_cc/resources/tests/test_file_processing.py | 144 | ||||
-rw-r--r-- | pyblackbird_cc/resources/tests/test_forms.py | 60 | ||||
-rw-r--r-- | pyblackbird_cc/resources/tests/test_models.py | 75 | ||||
-rw-r--r-- | pyblackbird_cc/resources/tests/test_views.py | 155 | ||||
-rw-r--r-- | pyblackbird_cc/resources/tests/testdata/seven_page.pdf | bin | 0 -> 153396 bytes | |||
-rw-r--r-- | pyblackbird_cc/resources/tests/testdata/test_small_file.pdf | bin | 0 -> 14147 bytes | |||
-rw-r--r-- | pyblackbird_cc/resources/tests/testdata/two_page.pdf | bin | 0 -> 186265 bytes |
8 files changed, 434 insertions, 0 deletions
diff --git a/pyblackbird_cc/resources/tests/__init__.py b/pyblackbird_cc/resources/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pyblackbird_cc/resources/tests/__init__.py diff --git a/pyblackbird_cc/resources/tests/test_file_processing.py b/pyblackbird_cc/resources/tests/test_file_processing.py new file mode 100644 index 0000000..40cc5eb --- /dev/null +++ b/pyblackbird_cc/resources/tests/test_file_processing.py @@ -0,0 +1,144 @@ +from django.contrib.auth import get_user_model +from django.core.files.uploadedfile import InMemoryUploadedFile +from django.core.files.uploadedfile import SimpleUploadedFile +from django.core.files.uploadedfile import TemporaryUploadedFile +from django.test import TestCase +from django.urls import reverse + +from .. import services + +""" Explanation: +The type of uploaded file object (InMemoryUploadedFile, TemporaryUploadedFile, or SimpleUploadedFile) is determined by the size of +the uploaded file and the value of the FILE_UPLOAD_MAX_MEMORY_SIZE setting in Django. + +By default, FILE_UPLOAD_MAX_MEMORY_SIZE is set to 2.5 MB (2621440 bytes). This means that if the size of the uploaded file +is less than or equal to 2.5 MB, Django will use the MemoryFileUploadHandler to handle the file upload, and the resulting uploaded +file object will be an instance of InMemoryUploadedFile. + +If the size of the uploaded file exceeds the FILE_UPLOAD_MAX_MEMORY_SIZE threshold, Django will use the TemporaryFileUploadHandler to +handle the file upload, and the resulting uploaded file object will be an instance of TemporaryUploadedFile. In this case, the uploaded +file is temporarily stored on disk instead of being kept in memory. + +The SimpleUploadedFile is used when you manually create an uploaded file object in your code, such as in tests or when handling file +uploads programmatically. + +To test the behavior with different file sizes, you can try the following: + +Create a test file that is smaller than 2.5 MB and run the test. The uploaded file should be an instance of InMemoryUploadedFile. +Create a test file that is larger than 2.5 MB and run the test. The uploaded file should be an instance of TemporaryUploadedFile. +If you want to change the threshold size for using InMemoryUploadedFile, you can modify the FILE_UPLOAD_MAX_MEMORY_SIZE setting in your Django settings file. For example: +FILE_UPLOAD_MAX_MEMORY_SIZE = 5 * 1024 * 1024 # 5 MB + +With this setting, files up to 5 MB will be handled as InMemoryUploadedFile, and files larger than 5 MB will be handled as TemporaryUploadedFile. +Remember to test with files of different sizes to ensure that your application handles file uploads correctly based on your specific requirements and settings. + +We also test the integrity of the uploaded PDF file here by checking the number of pages in the file and whether it is a valid PDF file. +""" + + +class PDFFileUploadTestCase(TestCase): + def setUp(self): + self.url = reverse("resources:create_resource") + self.test_file_path = "pyblackbird_cc/resources/tests/testdata/test_small_file.pdf" + + # Create a test user + self.email = "testuser@example.com" + self.password = "testpassword" + self.user = get_user_model().objects.create_user( + email=self.email, + password=self.password, + ) + + def test_file_upload(self): + """ + Test that a file can be uploaded successfully using our create_resource view. + """ + self.client.login( + email=self.email, + password=self.password, + ) # Log in the test user + + with open(self.test_file_path, "rb") as file: + uploaded_file = SimpleUploadedFile( + "test_file.pdf", + file.read(), + content_type="application/pdf", + ) + + response = self.client.post(self.url, {"pdf_files": [uploaded_file]}) + + # Check if the response is OK + self.assertEqual(response.status_code, 200) + + def test_file_upload_with_upload_handlers(self): + """ + This test does not test my code but the behavior of the Django file upload handlers. + """ + self.client.login( + email=self.email, + password=self.password, + ) # Log in the test user + + with open(self.test_file_path, "rb") as file: + uploaded_file = SimpleUploadedFile( + "test_file.pdf", + file.read(), + content_type="application/pdf", + ) + + response = self.client.post(self.url, {"pdf_files": [uploaded_file]}) + + self.assertEqual(response.status_code, 200) + + # Check if the uploaded file was handled by MemoryFileUploadHandler or TemporaryFileUploadHandler + uploaded_files = response.wsgi_request.FILES.getlist("pdf_files") + self.assertEqual(len(uploaded_files), 1) + + # We should expect an instance of InMemoryUploadedFile here because test_small_file.pdf is less than 2.5 MB + self.assertIsInstance( + uploaded_files[0], + (SimpleUploadedFile, TemporaryUploadedFile, InMemoryUploadedFile), + ) + + def test_uploaded_pdf_file_metadata(self): + """ + This test does not test my application code, but rather tests the + behavior of the Django file upload handlers. + """ + self.client.login( + email=self.email, + password=self.password, + ) # Log in the test user + + with open(self.test_file_path, "rb") as file: + uploaded_file = SimpleUploadedFile( + "test_file.pdf", + file.read(), + content_type="application/pdf", + ) + + response = self.client.post(self.url, {"pdf_files": [uploaded_file]}) + + self.assertEqual( + response.status_code, + 200, + ) + + # Extract metadata from the uploaded file + pdf_metadata_from_path = services.get_pdf_metadata_from_path(self.test_file_path) + + # Get the number of pages in the PDF - is 4 + self.assertEqual(pdf_metadata_from_path.n_pages, 4) + + # Get the file size in bytes + self.assertGreater(pdf_metadata_from_path.file_size, 0) + + self.assertLess( + pdf_metadata_from_path.file_size, + 5 * 1024 * 1024, + ) # Assuming a maximum file size of 5 MB + + # self.assertTrue(services.export_pdf_pages_as_images_temp_dir(self.test_file_path)) + # capture the output of the export_pdf_pages_as_images_temp_dir function coroutine + files = list(services.export_pages_as_images(self.test_file_path)) + self.assertEqual(len(files), 4) diff --git a/pyblackbird_cc/resources/tests/test_forms.py b/pyblackbird_cc/resources/tests/test_forms.py new file mode 100644 index 0000000..1ca823f --- /dev/null +++ b/pyblackbird_cc/resources/tests/test_forms.py @@ -0,0 +1,60 @@ +import unittest + +from django.core.files.uploadedfile import SimpleUploadedFile +from django.test import TestCase + +from ..forms import ResourceCreateForm +from ..models import ResourceCategory +from ..models import ResourceType + + +@unittest.skip("Skipping this test for now as it is broken") +class ResourceCreateFormTest(TestCase): + def setUp(self): + self.resource_type = ResourceType.objects.create(name="Test Resource Type") + self.resource_category = ResourceCategory.objects.create(name="Test Resource Category") + + def test_clean_pdf_files_validation_error(self): + # Create a list of dummy PDF files + pdf_files = [ + SimpleUploadedFile(f"file{i}.pdf", b"file_content", content_type="application/pdf") + for i in range(11) + ] + + # Create a list of dummy thumbnail files + thumbnail_files = [ + SimpleUploadedFile( + f"thumbnail{i}.jpg", + b"thumbnail_content", + content_type="image/jpeg", + ) + for i in range(6) + ] + + # Create a form instance with the dummy PDF files and thumbnail files + form_data = { + "name": "Test Resource", + "description": "Test Description", + "resource_type": self.resource_type.id, + "age_range": "5-7", + "curriculum": "English", + "main_resource_category": self.resource_category.id, + } + form_files = { + "pdf_files": pdf_files, + "thumbnail_files": thumbnail_files, + } + form = ResourceCreateForm(data=form_data, files=form_files) + + # Validate the form + is_valid = form.is_valid() + + # Check if the validation errors are raised for pdf_files and thumbnail_files + self.assertFalse(is_valid) + self.assertIn("pdf_files", form.errors) + self.assertEqual(form.errors["pdf_files"], ["Please select up to 10 PDF files."]) + self.assertIn("thumbnail_files", form.errors) + self.assertEqual( + form.errors["thumbnail_files"], + ["Please select up to 5 thumbnail files."], + ) diff --git a/pyblackbird_cc/resources/tests/test_models.py b/pyblackbird_cc/resources/tests/test_models.py new file mode 100644 index 0000000..c7ed4d2 --- /dev/null +++ b/pyblackbird_cc/resources/tests/test_models.py @@ -0,0 +1,75 @@ +import unittest +from unittest.mock import patch + +from django.test import TestCase + +from ..models import PDFPageSnapshot +from ..models import PDFResource +from ..models import Resource +from ..models import ResourceCategory +from ..models import ResourceType +from ..views import ResourceInfo +from ..views import _extract_metadata_from_resource + + +class ResourceModelTest(TestCase): + def test_string_representation(self): + resource = Resource(name="Test Resource") + self.assertEqual(str(resource), "Test Resource") + + +@unittest.skip("Skipping this test for now as it is broken") +class TestExtractMetadata(TestCase): + @patch("resources.views.get_presigned_obj_url") + def test_extract_metadata_from_resource(self, mock_get_url): + # Create mock instances of ResourceType and ResourceCategory + mock_resource_type = ResourceType.objects.create(name="Test Type") + mock_main_category = ResourceCategory.objects.create(name="Test Main Category") + + mock_resource = Resource( + name="Test Resource", + thumbnail_filenames=["thumb.jpg", "thumb2.jpg"], + created_at="2022-01-01", + updated_at="2022-01-02", + resource_type=mock_resource_type, + main_resource_category=mock_main_category, + age_range="5-7", + ) + mock_get_url.return_value = "https://example.com/url" + result = _extract_metadata_from_resource(mock_resource) + self.assertIsInstance(result, ResourceInfo) + self.assertEqual(result.name, "Test Resource") + self.assertEqual(result.pdf_filenames, "test.pdf") + self.assertEqual(result.thumbnail_filenames, ["thumb.jpg", "thumb2.jpg"]) + self.assertEqual(result.created, "2022-01-01") + self.assertEqual(result.updated, "2022-01-02") + + +@unittest.skip("These tests will not run because they rely upon the view to get file size, etc.") +class TestPDFResourceModel(TestCase): + def setUp(self): + self.resource_type = ResourceType.objects.create(name="Test Resource Type") + self.resource_category = ResourceCategory.objects.create(name="Test Resource Category") + self.resource = Resource.objects.create( + name="Test Resource", + resource_type=self.resource_type, + main_resource_category=self.resource_category, + age_range="5-7", + curriculum="English", + description="Test Description", + ) + self.pdf_resource = PDFResource.objects.create( + resource=self.resource, + file_name="resources/tests/testdata/test_small_file.pdf", + ) + self.pdf_page_snapshot = PDFPageSnapshot.objects.create( + name="Test Thumbnail Image", + file_name="test_resource_1.jpg", + pdf_file=self.pdf_resource, + ) + + def test_pdf_resource_string_representation(self): + self.assertEqual(str(self.resource), "Test Resource") + + def test_get_pdf_snapshot_filenames(self): + self.assertEqual(self.pdf_resource.snapshot_file_names(), ["test_resource_1.jpg"]) diff --git a/pyblackbird_cc/resources/tests/test_views.py b/pyblackbird_cc/resources/tests/test_views.py new file mode 100644 index 0000000..e71b3a2 --- /dev/null +++ b/pyblackbird_cc/resources/tests/test_views.py @@ -0,0 +1,155 @@ +import unittest + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import User +from django.core.files.uploadedfile import SimpleUploadedFile +from django.test import RequestFactory +from django.test import TestCase +from django.urls import reverse + +from .. import services +from ..models import ResourceCategory +from ..models import ResourceType +from ..views import create_resource + + +class PDFFileUploadTestCase(TestCase): + def setUp(self): + self.url = reverse("resources:create_resource") + self.two_page_pdf = "pyblackbird_cc/resources/tests/testdata/two_page.pdf" + self.seven_page_pdf = "pyblackbird_cc/resources/tests/testdata/seven_page.pdf" + + # Create a test user + self.email = "testuser@example.com" + self.password = "testpassword" + self.user = get_user_model().objects.create_user( + email=self.email, + password=self.password, + ) + + # Log in the test user + self.client.login(email=self.email, password=self.password) + + # Open the test files and create SimpleUploadedFile objects + with open(self.two_page_pdf, "rb") as file: + self.uploaded_two_page_pdf = SimpleUploadedFile( + "two_page.pdf", + file.read(), + content_type="application/pdf", + ) + with open(self.seven_page_pdf, "rb") as file: + self.uploaded_seven_page_pdf = SimpleUploadedFile( + "seven_page.pdf", + file.read(), + content_type="application/pdf", + ) + + def tearDown(self): + # Close the SimpleUploadedFile objects + self.uploaded_two_page_pdf.close() + self.uploaded_seven_page_pdf.close() + + def test_file_upload_is_pdf(self): + """ + Test that a file can be uploaded successfully using our create_resource view. + """ + response = self.client.post( + self.url, + {"pdf_files": [self.uploaded_two_page_pdf, self.uploaded_seven_page_pdf]}, + ) + + two_page_metadata = services.get_pdf_metadata_from_path(self.two_page_pdf) + seven_page_metadata = services.get_pdf_metadata_from_path(self.seven_page_pdf) + image_files_two_pager = list(services.export_pages_as_images(self.two_page_pdf)) + image_files_seven_pager = list( + services.export_pages_as_images(self.seven_page_pdf), + ) + + self.assertEqual(two_page_metadata.n_pages, 2) + self.assertEqual(seven_page_metadata.n_pages, 7) + self.assertGreater(two_page_metadata.file_size, 0) + self.assertGreater(seven_page_metadata.file_size, 0) + self.assertEqual(len(image_files_two_pager), 2) + self.assertEqual(len(image_files_seven_pager), 7) + self.assertEqual(response.status_code, 200) + + +@unittest.skip("Currently not able to mock S3 API at this point") +class TestCreateResourceUsingResourceFactory(TestCase): + def setUp(self): + self.factory = RequestFactory() + self.user = User.objects.create_user( + username="testuser", + password="testpassword", + ) + self.two_page_pdf = "resources/tests/testdata/two_page.pdf" + self.seven_page_pdf = "resources/tests/testdata/seven_page.pdf" + + # Create resource type + self.resource_type = ResourceType.objects.create(name="Test Resource Type") + + # Create resource categories + self.main_resource_category = ResourceCategory.objects.create( + name="Test Main Category", + ) + self.additional_resource_category = ResourceCategory.objects.create( + name="Test Additional Category", + ) + + def test_post_pdf(self): + # Open the test files and create SimpleUploadedFile objects + with open(self.two_page_pdf, "rb") as file: + uploaded_two_page_pdf = SimpleUploadedFile( + "two_page.pdf", + file.read(), + content_type="application/pdf", + ) + with open(self.seven_page_pdf, "rb") as file: + uploaded_seven_page_pdf = SimpleUploadedFile( + "seven_page.pdf", + file.read(), + content_type="application/pdf", + ) + + # Create a thumbnail file (you can use a dummy file for testing) + thumbnail_file = SimpleUploadedFile( + "thumbnail.jpg", + b"thumbnail_content", + content_type="image/jpeg", + ) + + # Prepare the form data + form_data = { + "name": "Test Resource", + "description": "Test Description", + "resource_type": self.resource_type.id, + "age_range": "5-7", + "curriculum": "English", + "main_resource_category": self.main_resource_category.id, + "additional_resource_category": self.additional_resource_category.id, + "pdf_files": [uploaded_two_page_pdf, uploaded_seven_page_pdf], + "thumbnail_files": [thumbnail_file], + } + + # Prepare the form files + form_files = { + "pdf_files": [uploaded_two_page_pdf, uploaded_seven_page_pdf], + "thumbnail_files": [thumbnail_file], + } + + # Create the request object with form data and files + request = self.factory.post("/create/", data=form_data) + request.user = self.user + + # TODO mock the call to the Spaces S3 service inside the view + + # Call the create_resource view function + response = create_resource(request) + + # Assert the response status code + self.assertEqual( + response.status_code, + 302, + ) # Assuming a successful form submission redirects (status code 302) + + # Add more assertions as needed diff --git a/pyblackbird_cc/resources/tests/testdata/seven_page.pdf b/pyblackbird_cc/resources/tests/testdata/seven_page.pdf Binary files differnew file mode 100644 index 0000000..991a26d --- /dev/null +++ b/pyblackbird_cc/resources/tests/testdata/seven_page.pdf diff --git a/pyblackbird_cc/resources/tests/testdata/test_small_file.pdf b/pyblackbird_cc/resources/tests/testdata/test_small_file.pdf Binary files differnew file mode 100644 index 0000000..9a990c8 --- /dev/null +++ b/pyblackbird_cc/resources/tests/testdata/test_small_file.pdf diff --git a/pyblackbird_cc/resources/tests/testdata/two_page.pdf b/pyblackbird_cc/resources/tests/testdata/two_page.pdf Binary files differnew file mode 100644 index 0000000..9c74944 --- /dev/null +++ b/pyblackbird_cc/resources/tests/testdata/two_page.pdf |