aboutsummaryrefslogtreecommitdiffstats
path: root/alphabetlearning/resources/tests
diff options
context:
space:
mode:
Diffstat (limited to 'alphabetlearning/resources/tests')
-rw-r--r--alphabetlearning/resources/tests/__init__.py0
-rw-r--r--alphabetlearning/resources/tests/test_file_processing.py134
-rw-r--r--alphabetlearning/resources/tests/test_forms.py74
-rw-r--r--alphabetlearning/resources/tests/test_models.py120
-rw-r--r--alphabetlearning/resources/tests/test_views.py190
-rw-r--r--alphabetlearning/resources/tests/testdata/seven_page.pdfbin0 -> 153396 bytes
-rw-r--r--alphabetlearning/resources/tests/testdata/test_small_file.pdfbin0 -> 14147 bytes
-rw-r--r--alphabetlearning/resources/tests/testdata/two_page.pdfbin0 -> 186265 bytes
8 files changed, 518 insertions, 0 deletions
diff --git a/alphabetlearning/resources/tests/__init__.py b/alphabetlearning/resources/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/alphabetlearning/resources/tests/__init__.py
diff --git a/alphabetlearning/resources/tests/test_file_processing.py b/alphabetlearning/resources/tests/test_file_processing.py
new file mode 100644
index 0000000..e09a135
--- /dev/null
+++ b/alphabetlearning/resources/tests/test_file_processing.py
@@ -0,0 +1,134 @@
+from pathlib import Path
+
+from django.conf import settings
+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
+from ..utils import _get_pdf_collection_type
+
+
+def test_detect_snapshotted_pdf_collection():
+ single_pdf_single_page = [["toss"]]
+ single_pdf_multi_page = [["toss2", "toss8"]]
+ multi_pdf_single_page = [["toss"], ["toss2"]]
+ multi_pdf_multi_page = [["toss", "toss2"], ["toss", "toss2"]]
+
+ assert _get_pdf_collection_type(single_pdf_single_page) == "SINGLE_PDF_SINGLE_PAGE"
+ assert _get_pdf_collection_type(single_pdf_multi_page) == "SINGLE_PDF_MULTI_PAGE"
+ assert _get_pdf_collection_type(multi_pdf_single_page) == "MULTI_PDF_SINGLE_PAGE"
+ assert _get_pdf_collection_type(multi_pdf_multi_page) == "MULTI_PDF_MULTI_PAGE"
+
+
+class PDFFileUploadTestCase(TestCase):
+ def setUp(self):
+ self.url = reverse("resources:create_resource")
+ self.test_file_path = Path(
+ settings.BASE_DIR / "alphabetlearning" / "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/alphabetlearning/resources/tests/test_forms.py b/alphabetlearning/resources/tests/test_forms.py
new file mode 100644
index 0000000..aebc110
--- /dev/null
+++ b/alphabetlearning/resources/tests/test_forms.py
@@ -0,0 +1,74 @@
+import pytest
+from django.core.files.uploadedfile import SimpleUploadedFile
+from django.db import IntegrityError
+from django.test import TestCase
+from django.utils.datastructures import MultiValueDict
+
+from alphabetlearning.resources.factories import ResourceModelFactory
+from alphabetlearning.resources.forms import ResourceCreateForm
+from alphabetlearning.resources.models import ResourceCategory
+from alphabetlearning.resources.models import ResourceType
+
+
+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")
+ self.form_data = {
+ "name": "Test Resource",
+ "description": "Test Description",
+ "card_description": "Test Card Description",
+ "resource_type": self.resource_type.id,
+ "age_range": "Reception (4-5yrs)",
+ "curriculum": "English",
+ "feature_slot": 1,
+ "main_resource_category": self.resource_category.id,
+ }
+ self.pdf_files = [
+ # use the correct PDF file header - this should pass validation
+ SimpleUploadedFile(
+ f"file{i}.pdf",
+ b"\x25\x50\x44\x46\x2d",
+ content_type="application/pdf",
+ )
+ for i in range(11)
+ ]
+ self.thumbnail_files = [
+ # use the correct JPG file header - this should pass validation
+ SimpleUploadedFile(
+ f"thumbnail{i}.jpg",
+ b"\xff\xd8\xff\xdb",
+ content_type="image/jpeg",
+ )
+ # 5 is the max number currently set in ALLOWED_THUMBNAILS
+ for i in range(5)
+ ]
+ # This needs to be a MultiValueDict for the test to mimic production code
+ # see clean_pdf_files - self.files.getlist()
+ self.form_files = MultiValueDict(
+ {"pdf_files": self.pdf_files, "thumbnail_files": self.thumbnail_files},
+ )
+
+ def test_form_valid(self):
+ form = ResourceCreateForm(data=self.form_data, files=self.form_files)
+ assert form.is_valid()
+
+ @pytest.mark.django_db()
+ def test_featured_slots_must_be_unique(self):
+ r1 = ResourceModelFactory(feature_slot=1)
+ with pytest.raises(IntegrityError):
+ ResourceModelFactory(feature_slot=1)
+
+ @pytest.mark.django_db()
+ def test_featured_slots_allowable(self):
+ form_data = {
+ "name": "Test Resource",
+ "description": "Test Description",
+ "resource_type": self.resource_type.id,
+ "age_range": "5-7",
+ "curriculum": "English",
+ "feature_slot": 4,
+ "main_resource_category": self.resource_category.id,
+ }
+ form = ResourceCreateForm(data=form_data, files=self.form_files)
+ assert not form.is_valid()
diff --git a/alphabetlearning/resources/tests/test_models.py b/alphabetlearning/resources/tests/test_models.py
new file mode 100644
index 0000000..0fd589a
--- /dev/null
+++ b/alphabetlearning/resources/tests/test_models.py
@@ -0,0 +1,120 @@
+import unittest
+from unittest.mock import patch
+
+import pytest
+from django.db import IntegrityError
+from django.test import TestCase
+
+from alphabetlearning.resources.factories import PDFPageSnapshotModelFactory
+from alphabetlearning.resources.factories import ResourceModelFactory
+from alphabetlearning.resources.models import PDFPageSnapshot
+from alphabetlearning.resources.models import PDFResource
+from alphabetlearning.resources.models import Resource
+from alphabetlearning.resources.models import ResourceCategory
+from alphabetlearning.resources.models import ResourceType
+from alphabetlearning.resources.views import ResourceInfo
+from alphabetlearning.resources.views import _extract_metadata_from_resource
+
+
+@pytest.mark.django_db()
+def test_resource_model(resources):
+ r1 = resources[0]
+ pdf_on_rw = r1.pdf_resources.first()
+ pdf_page_snapshot = PDFPageSnapshotModelFactory(pdf_file=pdf_on_rw)
+
+ assert Resource.objects.filter(id=r1.id).exists()
+ assert any("test_" in name for name in r1.get_pdf_file_names())
+ assert len(r1.get_pdf_file_names()) == 3
+ assert "pdf_page_snapshot_" in r1.get_pdf_snapshot_file_names()[0]
+
+
+@pytest.mark.django_db()
+def test_can_add_feature_slots_to_resource():
+ r = ResourceModelFactory()
+ r.feature_slot = 1
+ r.save()
+ assert r.feature_slot == 1
+
+
+@pytest.mark.django_db()
+def test_resource_slot_int_must_be_unique():
+ """
+ Test that a resource feature slot must be unique.
+ """
+ r1 = ResourceModelFactory()
+ r2 = ResourceModelFactory()
+ r1.feature_slot = 1
+ r1.save()
+ r2.feature_slot = 1
+ with pytest.raises(IntegrityError):
+ r2.save()
+
+
+class ResourceModelTest(TestCase):
+ def test_string_representation(self):
+ resource = Resource(name="Test Resource")
+ assert 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)
+ assert result.name == "Test Resource"
+ assert result.pdf_filenames == "test.pdf"
+ assert result.thumbnail_filenames in ["thumb.jpg", "thumb2.jpg"]
+ assert result.created == "2022-01-01"
+ assert 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"])
+
+
+@pytest.mark.django_db()
+def test_get_urls_of_resource_snapshot_images(resource):
+ assert len(resource.thumbnail_filenames) == 3
+ # crude but it does the job; concatenating a list of URLS into one long sting...
+ assert "https://ams3.digitaloceanspaces.com" in "".join(resource.thumbnail_urls())
diff --git a/alphabetlearning/resources/tests/test_views.py b/alphabetlearning/resources/tests/test_views.py
new file mode 100644
index 0000000..b57e79d
--- /dev/null
+++ b/alphabetlearning/resources/tests/test_views.py
@@ -0,0 +1,190 @@
+import unittest
+from pathlib import Path
+
+import pytest
+from django.conf import settings
+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 alphabetlearning.resources import services
+from alphabetlearning.resources.forms import ResourceCreateForm
+from alphabetlearning.resources.models import ResourceCategory
+from alphabetlearning.resources.models import ResourceType
+from alphabetlearning.resources.views import create_resource
+
+pytestmark = pytest.mark.django_db
+
+
+def test_create_featured_resource_view(client):
+ url = reverse("resources:create_featured")
+ response = client.get(url)
+ assert response.status_code == 302
+
+
+def test_create_resource_view(client):
+ url = reverse("resources:create_resource")
+ response = client.get(url)
+ assert response.status_code == 302
+
+
+@pytest.mark.django_db
+def test_create_resource_has_form(client):
+ User = get_user_model()
+ user = User.objects.create_user(email="testuser@example.com", password="12345")
+ client.login(email="testuser@example.com", password="12345")
+
+ url = reverse("resources:create_resource")
+ response = client.get(url)
+ assert response.status_code == 200
+ assert "form" in response.context
+ assert isinstance(response.context["form"], ResourceCreateForm)
+
+
+class PDFFileUploadTestCase(TestCase):
+ def setUp(self):
+ self.url = reverse("resources:create_resource")
+ self.two_page_pdf = Path(
+ settings.BASE_DIR / "alphabetlearning" / "resources/tests/testdata/two_page.pdf"
+ )
+ self.seven_page_pdf = Path(
+ settings.BASE_DIR / "alphabetlearning" / "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/alphabetlearning/resources/tests/testdata/seven_page.pdf b/alphabetlearning/resources/tests/testdata/seven_page.pdf
new file mode 100644
index 0000000..991a26d
--- /dev/null
+++ b/alphabetlearning/resources/tests/testdata/seven_page.pdf
Binary files differ
diff --git a/alphabetlearning/resources/tests/testdata/test_small_file.pdf b/alphabetlearning/resources/tests/testdata/test_small_file.pdf
new file mode 100644
index 0000000..9a990c8
--- /dev/null
+++ b/alphabetlearning/resources/tests/testdata/test_small_file.pdf
Binary files differ
diff --git a/alphabetlearning/resources/tests/testdata/two_page.pdf b/alphabetlearning/resources/tests/testdata/two_page.pdf
new file mode 100644
index 0000000..9c74944
--- /dev/null
+++ b/alphabetlearning/resources/tests/testdata/two_page.pdf
Binary files differ