Coverage for src/mesh/tests/models/test_file_models.py: 100%
108 statements
« prev ^ index » next coverage.py v7.9.0, created at 2026-02-04 09:42 +0000
« prev ^ index » next coverage.py v7.9.0, created at 2026-02-04 09:42 +0000
1import os
2from unittest.mock import patch
4from django.core.exceptions import ValidationError
5from django.core.files.uploadedfile import SimpleUploadedFile
6from django.db import DatabaseError
8from ...models.factories import SubmissionVersionFactory
9from ...models.file_models import get_upload_path_from_model
10from ...models.submission_models import Submission, SubmissionAdditionalFile
11from ..base_test_case import BaseTestCase
14class BaseFileWrapperTestCase(BaseTestCase):
15 """
16 Tests for `BaseFileWrapperModel` class.
17 We use the `SubmissionAdditionalFile` class in the tests because
18 `BaseFileWrapperModel` is an abstract model.
19 """
21 used_models = [Submission]
23 def setUp(self):
24 super().setUp()
25 self.reset_user_files_directory()
26 self.version = SubmissionVersionFactory.create()
28 def test_file_path(self):
29 file_wrapper = SubmissionAdditionalFile()
30 file_wrapper.attached_to = self.version
31 file_wrapper.file = self.dummy_file # type:ignore
32 file_wrapper.save()
34 # Check that the original name is saved
35 self.assertEqual(file_wrapper.name, self.dummy_file.name)
37 # Check that the upload path is the one from get_upload_path
38 self.assertEqual(
39 SubmissionAdditionalFile.get_upload_path(file_wrapper, self.dummy_file.name),
40 file_wrapper.file.name,
41 )
43 # Check creating a file with the same name
44 file_wrapper_2 = SubmissionAdditionalFile()
45 file_wrapper_2.attached_to = self.version
46 file_wrapper_2.file = self.dummy_file # type:ignore
47 file_wrapper_2.save()
49 # Check that the original name is saved
50 self.assertEqual(file_wrapper_2.name, self.dummy_file.name)
52 # The actual file path/name should be different: the second file having the
53 # same initial path and name as the first one, it should have been renamed correctly.
54 self.assertNotEqual(
55 SubmissionAdditionalFile.get_upload_path(file_wrapper_2, self.dummy_file.name),
56 file_wrapper_2.file.name,
57 )
59 def test_validate_file_extension(self):
60 SubmissionAdditionalFile.file_extensions = [".pdf"]
61 SubmissionAdditionalFile.validate_file_extension(self.dummy_file)
63 SubmissionAdditionalFile.file_extensions = []
64 SubmissionAdditionalFile.validate_file_extension(self.dummy_file)
66 SubmissionAdditionalFile.file_extensions = [".docx"]
67 self.assertRaises(
68 ValidationError, SubmissionAdditionalFile.validate_file_extension, self.dummy_file
69 )
71 def test_validate_file_size(self):
72 SubmissionAdditionalFile.file_max_size = 10**6
73 SubmissionAdditionalFile.validate_file_size(self.dummy_file)
75 SubmissionAdditionalFile.file_max_size = 1
76 self.assertRaises(
77 ValidationError, SubmissionAdditionalFile.validate_file_size, self.dummy_file
78 )
80 def test_validate_file_name_length(self):
81 SubmissionAdditionalFile.file_name_max_length = 100
82 SubmissionAdditionalFile.validate_file_name_length(self.dummy_file)
84 self.dummy_file.name = "".join("a" for a in range(97)) + ".pdf"
85 self.assertRaises(
86 ValidationError, SubmissionAdditionalFile.validate_file_name_length, self.dummy_file
87 )
89 def test_base_run_file_validators(self):
90 SubmissionAdditionalFile.file_extensions = [".pdf"]
91 SubmissionAdditionalFile.file_max_size = 10**6
92 SubmissionAdditionalFile.file_name_max_length = 100
93 SubmissionAdditionalFile.run_file_validators(self.dummy_file)
95 SubmissionAdditionalFile.file_extensions = [".docx"]
96 self.assertRaises(
97 ValidationError, SubmissionAdditionalFile.run_file_validators, self.dummy_file
98 )
100 SubmissionAdditionalFile.file_extensions = [".pdf"]
101 SubmissionAdditionalFile.run_file_validators(self.dummy_file)
102 SubmissionAdditionalFile.file_max_size = 1
103 self.assertRaises(
104 ValidationError, SubmissionAdditionalFile.run_file_validators, self.dummy_file
105 )
107 SubmissionAdditionalFile.file_max_size = 10**6
108 SubmissionAdditionalFile.run_file_validators(self.dummy_file)
109 SubmissionAdditionalFile.file_name_max_length = 1
110 self.assertRaises(
111 ValidationError, SubmissionAdditionalFile.run_file_validators, self.dummy_file
112 )
114 def test_reverse_file_path(self):
115 """
116 SHOULD BE TESTED FOR EVERY CLASS inheriting the BaseFileWrapperModel.
117 One should test saving a file, then ensuring that reverse_file_path returns
118 the correct file when supplied with the file path.
119 """
120 file_wrapper = SubmissionAdditionalFile()
121 file_wrapper.attached_to = self.version
122 file_wrapper.file = self.dummy_file # type:ignore
123 file_wrapper.save()
125 file_wrapper_request = SubmissionAdditionalFile.reverse_file_path(file_wrapper.file.name)
126 self.assertEqual(file_wrapper.pk, file_wrapper_request.pk) # type:ignore
128 path = SubmissionAdditionalFile.get_upload_path(file_wrapper, "UNKNOWN.pdf")
129 self.assertIsNone(SubmissionAdditionalFile.reverse_file_path(path))
131 self.assertIsNone(SubmissionAdditionalFile.reverse_file_path("my_path/UNKNOWN.pdf"))
133 def test_file_update(self):
134 file_wrapper = SubmissionAdditionalFile()
135 file_wrapper.attached_to = self.version
136 file_wrapper.file = self.dummy_file # type:ignore
137 file_wrapper.save()
139 path: str = file_wrapper.file.path # type:ignore
140 self.assertTrue(os.path.isfile(path))
142 new_file = SimpleUploadedFile(
143 "my_new_file.pdf", b"My new contentes", content_type="application/pdf"
144 )
145 file_wrapper.file = new_file # type:ignore
147 # DB save fails -> the original file should not have been deleted
148 with patch("django.db.models.Model.save", side_effect=DatabaseError("Error")):
149 self.assertRaises(DatabaseError, file_wrapper.save)
150 self.assertTrue(os.path.isfile(path))
152 # DB save succeeds -> the original file should have been deleted from
153 # the filesystem.
154 file_wrapper.save()
155 self.assertFalse(os.path.exists(path))
156 self.assertTrue(os.path.isfile(file_wrapper.file.path)) # type:ignore
158 def test_delete(self):
159 file_wrapper = SubmissionAdditionalFile()
160 file_wrapper.attached_to = self.version
161 file_wrapper.file = self.dummy_file # type:ignore
162 file_wrapper.save()
164 path: str = file_wrapper.file.path # type:ignore
165 self.assertTrue(os.path.isfile(path))
167 file_wrapper.delete()
168 self.assertFalse(os.path.exists(path))
170 # Ensure the file is not deleted if the DB deletion fails
171 with patch("django.db.models.Model.delete", side_effect=DatabaseError("Error")):
172 file_wrapper = SubmissionAdditionalFile()
173 file_wrapper.attached_to = self.version
174 file_wrapper.file = self.dummy_file # type:ignore
175 file_wrapper.save()
177 path: str = file_wrapper.file.path # type:ignore
178 self.assertTrue(os.path.isfile(path))
180 self.assertRaises(DatabaseError, file_wrapper.delete)
181 self.assertTrue(os.path.isfile(path))
183 def test_get_upload_path_from_model(self):
184 file_wrapper = SubmissionAdditionalFile()
185 file_wrapper.attached_to = self.version
186 filename = "my_file.pdf"
188 self.assertEqual(
189 get_upload_path_from_model(file_wrapper, filename),
190 SubmissionAdditionalFile.get_upload_path(file_wrapper, filename),
191 )