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

1import os 

2from unittest.mock import patch 

3 

4from django.core.exceptions import ValidationError 

5from django.core.files.uploadedfile import SimpleUploadedFile 

6from django.db import DatabaseError 

7 

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 

12 

13 

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 """ 

20 

21 used_models = [Submission] 

22 

23 def setUp(self): 

24 super().setUp() 

25 self.reset_user_files_directory() 

26 self.version = SubmissionVersionFactory.create() 

27 

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() 

33 

34 # Check that the original name is saved 

35 self.assertEqual(file_wrapper.name, self.dummy_file.name) 

36 

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 ) 

42 

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() 

48 

49 # Check that the original name is saved 

50 self.assertEqual(file_wrapper_2.name, self.dummy_file.name) 

51 

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 ) 

58 

59 def test_validate_file_extension(self): 

60 SubmissionAdditionalFile.file_extensions = [".pdf"] 

61 SubmissionAdditionalFile.validate_file_extension(self.dummy_file) 

62 

63 SubmissionAdditionalFile.file_extensions = [] 

64 SubmissionAdditionalFile.validate_file_extension(self.dummy_file) 

65 

66 SubmissionAdditionalFile.file_extensions = [".docx"] 

67 self.assertRaises( 

68 ValidationError, SubmissionAdditionalFile.validate_file_extension, self.dummy_file 

69 ) 

70 

71 def test_validate_file_size(self): 

72 SubmissionAdditionalFile.file_max_size = 10**6 

73 SubmissionAdditionalFile.validate_file_size(self.dummy_file) 

74 

75 SubmissionAdditionalFile.file_max_size = 1 

76 self.assertRaises( 

77 ValidationError, SubmissionAdditionalFile.validate_file_size, self.dummy_file 

78 ) 

79 

80 def test_validate_file_name_length(self): 

81 SubmissionAdditionalFile.file_name_max_length = 100 

82 SubmissionAdditionalFile.validate_file_name_length(self.dummy_file) 

83 

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 ) 

88 

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) 

94 

95 SubmissionAdditionalFile.file_extensions = [".docx"] 

96 self.assertRaises( 

97 ValidationError, SubmissionAdditionalFile.run_file_validators, self.dummy_file 

98 ) 

99 

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 ) 

106 

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 ) 

113 

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() 

124 

125 file_wrapper_request = SubmissionAdditionalFile.reverse_file_path(file_wrapper.file.name) 

126 self.assertEqual(file_wrapper.pk, file_wrapper_request.pk) # type:ignore 

127 

128 path = SubmissionAdditionalFile.get_upload_path(file_wrapper, "UNKNOWN.pdf") 

129 self.assertIsNone(SubmissionAdditionalFile.reverse_file_path(path)) 

130 

131 self.assertIsNone(SubmissionAdditionalFile.reverse_file_path("my_path/UNKNOWN.pdf")) 

132 

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() 

138 

139 path: str = file_wrapper.file.path # type:ignore 

140 self.assertTrue(os.path.isfile(path)) 

141 

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 

146 

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)) 

151 

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 

157 

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() 

163 

164 path: str = file_wrapper.file.path # type:ignore 

165 self.assertTrue(os.path.isfile(path)) 

166 

167 file_wrapper.delete() 

168 self.assertFalse(os.path.exists(path)) 

169 

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() 

176 

177 path: str = file_wrapper.file.path # type:ignore 

178 self.assertTrue(os.path.isfile(path)) 

179 

180 self.assertRaises(DatabaseError, file_wrapper.delete) 

181 self.assertTrue(os.path.isfile(path)) 

182 

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" 

187 

188 self.assertEqual( 

189 get_upload_path_from_model(file_wrapper, filename), 

190 SubmissionAdditionalFile.get_upload_path(file_wrapper, filename), 

191 )