Coverage for src/mesh/tests/roles/test_editor.py: 100%
281 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
1from datetime import datetime, timedelta
2from unittest.mock import patch
4from mesh.model.roles.editor import Editor, EditorRights, get_section_editors
6from ...model.submission_status import SubmissionStatus
7from ...models.editorial_models import EditorSectionRight, EditorSubmissionRight
8from ...models.factories import (
9 JournalSectionFactory,
10 ReviewFactory,
11 SubmissionAuthorFactory,
12 SubmissionFactory,
13 SubmissionVersionFactory,
14 UserFactory,
15)
16from ...models.journal_models import JournalSection
17from ...models.submission_models import Submission, SubmissionMainFile, SubmissionState
18from ...models.user_models import User
19from ..base_test_case import BaseTestCase
22class EditorTestCase(BaseTestCase):
23 used_models = [
24 EditorSubmissionRight,
25 EditorSectionRight,
26 Submission,
27 JournalSection,
28 ]
29 class_used_models = [User]
31 @classmethod
32 def setUpClass(cls) -> None:
33 super().setUpClass()
34 cls.user_author = UserFactory.create()
35 cls.user_editor = UserFactory.create()
37 def test_submissions_from_direct_right(self):
38 submission_1 = SubmissionFactory.create()
39 submission_2 = SubmissionFactory.create() # noqa
41 role = Editor(self.user_editor)
42 self.assertFalse(role.active)
44 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission_1)
45 role = Editor(self.user_editor)
46 self.assertTrue(role.active)
47 rights = role.rights
49 self.assertEqual(len(rights.submissions), 1)
50 self.assertEqual(rights.submissions[0], submission_1)
52 submission_1.created_by = self.user_editor
53 submission_1.save()
54 role = Editor(self.user_editor)
55 self.assertTrue(role.active)
56 rights = role.rights
57 self.assertEqual(len(rights.submissions), 1)
58 self.assertEqual(rights.submissions[0], submission_1)
60 def test_submissions_from_journal_sections(self):
61 journal_section_1 = JournalSectionFactory.create()
62 journal_section_2 = JournalSectionFactory.create(parent=journal_section_1)
63 journal_section_3 = JournalSectionFactory.create()
65 submission_1 = SubmissionFactory.create(
66 journal_section=journal_section_1, state=SubmissionState.SUBMITTED.value
67 )
68 submission_2 = SubmissionFactory.create(
69 journal_section=journal_section_2, state=SubmissionState.SUBMITTED.value
70 )
71 submission_3 = SubmissionFactory.create( # noqa
72 journal_section=journal_section_3, state=SubmissionState.SUBMITTED.value
73 )
75 EditorSectionRight.objects.create(user=self.user_editor, journal_section=journal_section_1)
76 role = Editor(self.user_editor)
77 self.assertTrue(role.active)
78 rights = role.rights
80 self.assertEqual(len(rights.submissions), 2)
81 self.assertIn(submission_1, rights.submissions)
82 self.assertIn(submission_2, rights.submissions)
84 # Self-made submission are not available to the editor.
85 submission_1.created_by = self.user_editor
86 submission_1.save()
87 role = Editor(self.user_editor)
88 self.assertTrue(role.active)
89 rights = role.rights
90 self.assertEqual(len(rights.submissions), 1)
91 self.assertIn(submission_2, rights.submissions)
93 # OPENED submissions are not availabe to anyone but to its author.
94 submission_2.state = SubmissionState.OPENED.value
95 submission_2.save()
96 role = Editor(self.user_editor)
97 # Editor role is actve if it has rights over any journal_section or any submissions
98 self.assertTrue(role.active)
99 rights = role.rights
100 self.assertEqual(len(rights.submissions), 0)
102 def test_all_submissions(self):
103 journal_section_1 = JournalSectionFactory.create()
104 journal_section_2 = JournalSectionFactory.create(parent=journal_section_1)
105 journal_section_3 = JournalSectionFactory.create()
107 submission_1 = SubmissionFactory.create(
108 journal_section=journal_section_1, state=SubmissionState.SUBMITTED.value
109 )
110 submission_2 = SubmissionFactory.create(
111 journal_section=journal_section_2, state=SubmissionState.SUBMITTED.value
112 )
113 submission_3 = SubmissionFactory.create( # noqa
114 journal_section=journal_section_3, state=SubmissionState.SUBMITTED.value
115 )
116 submission_4 = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
117 submission_5 = SubmissionFactory.create( # noqa
118 journal_section=journal_section_1,
119 state=SubmissionState.SUBMITTED.value,
120 created_by=self.user_editor,
121 )
123 EditorSectionRight.objects.create(user=self.user_editor, journal_section=journal_section_1)
124 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission_4)
126 rights = EditorRights(self.user_editor)
127 self.assertEqual(len(rights.submissions), 3)
128 self.assertIn(submission_1, rights.submissions)
129 self.assertIn(submission_2, rights.submissions)
130 self.assertIn(submission_4, rights.submissions)
132 # All the following tests are rights exclusive to the Editor+ roles.
133 # We just ensure they resolve to True when the editor has rights over the submission.
134 def test_can_invite_reviewer(self):
135 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
136 version = SubmissionVersionFactory.create(submission=submission, submitted=True)
137 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
139 rights = EditorRights(self.user_editor)
140 self.assertFalse(rights.can_invite_reviewer(version))
142 version.review_open = True
143 self.assertTrue(rights.can_invite_reviewer(version))
145 def test_can_access_version(self):
146 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
147 version = SubmissionVersionFactory.create(submission=submission)
148 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
150 rights = EditorRights(self.user_editor)
151 self.assertFalse(rights.can_access_version(version))
153 version.submitted = True
154 self.assertTrue(rights.can_access_version(version))
156 def test_managed_users(self):
157 User.objects.all().delete()
158 user_editor = UserFactory.create()
159 user_author_1 = UserFactory.create()
160 user_author_2 = UserFactory.create()
161 user_reviewer = UserFactory.create()
162 user_editor_2 = UserFactory.create()
163 user_editor_3 = UserFactory.create()
164 user_journal_manager = UserFactory.create(journal_manager=True)
165 user_admin = UserFactory.create(is_superuser=True) # noqa
167 submission_1 = SubmissionFactory.create(
168 created_by=user_author_1, state=SubmissionState.SUBMITTED.value
169 )
170 version_1 = SubmissionVersionFactory(submission=submission_1, submitted=True)
171 submission_2 = SubmissionFactory.create(
172 created_by=user_author_2, state=SubmissionState.SUBMITTED.value
173 )
174 review = ReviewFactory.create(reviewer=user_reviewer, version=version_1) # noqa
176 EditorSubmissionRight.objects.create(user=user_editor, submission=submission_1)
177 EditorSubmissionRight.objects.create(user=user_editor_2, submission=submission_2)
179 journal_section = JournalSectionFactory.create(created_by=user_journal_manager)
180 EditorSectionRight.objects.create(journal_section=journal_section, user=user_editor_3)
182 rights = EditorRights(user_editor)
183 self.assertEqual(len(rights.managed_users), 3)
184 self.assertIn(user_author_1, rights.managed_users)
185 self.assertIn(user_author_2, rights.managed_users)
186 self.assertIn(user_reviewer, rights.managed_users)
188 def test_can_impersonate(self):
189 rights = EditorRights(self.user_editor)
190 self.assertTrue(rights.can_impersonate())
192 def test_can_access_submission_log(self):
193 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
194 rights = EditorRights(self.user_editor)
195 self.assertFalse(rights.can_access_submission_log(submission))
197 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
198 rights = EditorRights(self.user_editor)
199 self.assertTrue(rights.can_access_submission_log(submission))
201 def test_can_create_editorial_decision(self):
202 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
203 rights = EditorRights(self.user_editor)
204 self.assertFalse(rights.can_create_editorial_decision(submission))
206 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
207 rights = EditorRights(self.user_editor)
208 self.assertTrue(rights.can_create_editorial_decision(submission))
210 submission.state = SubmissionState.ON_REVIEW.value
211 submission.save()
212 rights = EditorRights(self.user_editor)
213 self.assertTrue(rights.can_create_editorial_decision(submission))
215 submission.state = SubmissionState.REVISION_REQUESTED.value
216 submission.save()
217 rights = EditorRights(self.user_editor)
218 self.assertTrue(rights.can_create_editorial_decision(submission))
220 submission.state = SubmissionState.REVISION_SUBMITTED.value
221 submission.save()
222 rights = EditorRights(self.user_editor)
223 self.assertTrue(rights.can_create_editorial_decision(submission))
225 submission.state = SubmissionState.ACCEPTED.value
226 submission.save()
227 rights = EditorRights(self.user_editor)
228 self.assertTrue(rights.can_create_editorial_decision(submission))
230 submission.state = SubmissionState.REJECTED.value
231 submission.save()
232 rights = EditorRights(self.user_editor)
233 self.assertTrue(rights.can_create_editorial_decision(submission))
235 def test_can_start_review_process(self):
236 submission = SubmissionFactory.create()
238 rights = EditorRights(self.user_editor)
239 with patch.object(Submission, "is_reviewable", True):
240 self.assertFalse(rights.can_start_review_process(submission))
242 with patch.object(Submission, "is_reviewable", False):
243 self.assertFalse(rights.can_start_review_process(submission))
245 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
246 rights = EditorRights(self.user_editor)
247 with patch.object(Submission, "is_reviewable", True):
248 self.assertTrue(rights.can_start_review_process(submission))
250 with patch.object(Submission, "is_reviewable", False):
251 self.assertFalse(rights.can_start_review_process(submission))
253 def test_can_assign_editor(self):
254 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
255 rights = EditorRights(self.user_editor)
256 self.assertFalse(rights.can_assign_editor(submission))
258 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
259 rights = EditorRights(self.user_editor)
260 self.assertTrue(rights.can_assign_editor(submission))
262 def test_can_filter_submissions(self):
263 rights = EditorRights(self.user_editor)
264 self.assertTrue(rights.can_filter_submissions())
266 def test_can_access_journal_sections(self):
267 rights = EditorRights(self.user_editor)
268 self.assertTrue(rights.can_access_journal_sections())
270 def test_can_edit_review_file_right(self):
271 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
272 version = SubmissionVersionFactory.create(submission=submission, submitted=True)
273 review = ReviewFactory.create(version=version)
274 rights = EditorRights(self.user_editor)
275 self.assertFalse(rights.can_edit_review_file_right(review))
277 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
278 rights = EditorRights(self.user_editor)
279 self.assertTrue(rights.can_edit_review_file_right(review))
281 def test_editor_submission_status(self):
282 """
283 Test the editor status wrt. the whole submission workflow
284 """
285 submission = SubmissionFactory.create(author_agreement=True)
286 version = SubmissionVersionFactory.create(
287 submission=submission, submitted=False, review_open=False
288 )
289 SubmissionAuthorFactory.create(submission=submission)
290 SubmissionMainFile.objects.create(file=self.dummy_file, attached_to=version)
292 # No rights over the submission
293 submission = Submission.objects.get(pk=submission.pk)
294 rights = EditorRights(self.user_editor)
295 status = rights.get_submission_status(submission)
296 self.assertEqual(status.status, SubmissionStatus.ERROR)
298 # OPENED submission
299 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
300 rights = EditorRights(self.user_editor)
301 status = rights.get_submission_status(submission)
302 self.assertEqual(status.status, SubmissionStatus.ERROR)
304 # SUBMITTED submission
305 request = self.dummy_request()
306 request.user = submission.created_by
307 submission.submit(submission.created_by)
308 submission = Submission.objects.get(pk=submission.pk)
309 status = rights.get_submission_status(submission)
310 self.assertEqual(status.status, SubmissionStatus.TODO)
312 # UNDER REVIEW submission with no reviews
313 request.user = self.user_editor
314 # submission.start_review_process(self.user_editor)
315 submission = Submission.objects.get(pk=submission.pk)
316 status = rights.get_submission_status(submission)
317 self.assertEqual(status.status, SubmissionStatus.TODO)
319 # UNDER REVIEW with pending answer
320 review = ReviewFactory.create(version=version)
321 submission = Submission.objects.get(pk=submission.pk)
322 status = rights.get_submission_status(submission)
323 self.assertEqual(status.status, SubmissionStatus.WAITING)
325 # UNDER REVIEW with 1 pending review & 1 overdue review
326 yesterday = (datetime.utcnow() - timedelta(days=1)).date()
327 review_overdue = ReviewFactory.create(version=version, date_response_due=yesterday)
328 submission = Submission.objects.get(pk=submission.pk)
329 status = rights.get_submission_status(submission)
330 self.assertEqual(status.status, SubmissionStatus.TODO)
332 # UNDER REVIEW with 1 pending review, 1 pending answer
333 review_overdue.date_response_due = (datetime.utcnow() + timedelta(days=1)).date()
334 review_overdue.accepted = True
335 review_overdue.save()
336 submission = Submission.objects.get(pk=submission.pk)
337 status = rights.get_submission_status(submission)
338 self.assertEqual(status.status, SubmissionStatus.WAITING)
340 # UNDER REVIEW with all reviews submitted or declined
341 review.accepted = False
342 review.save()
343 review_overdue.submitted = True
344 review_overdue.save()
345 submission = Submission.objects.get(pk=submission.pk)
346 status = rights.get_submission_status(submission)
347 self.assertEqual(status.status, SubmissionStatus.TODO)
349 # REVISIIONS REQUESTED submission
350 submission.state = SubmissionState.REVISION_REQUESTED.value
351 submission.save()
352 submission = Submission.objects.get(pk=submission.pk)
353 status = rights.get_submission_status(submission)
354 self.assertEqual(status.status, SubmissionStatus.WAITING)
355 version.review_open = False
356 version.save()
358 # REVISIONS SUBMITTED submission
359 version_2 = SubmissionVersionFactory.create(
360 submission=submission, submitted=False, review_open=False
361 )
362 SubmissionMainFile.objects.create(file=self.dummy_file, attached_to=version_2)
363 submission = Submission.objects.get(pk=submission.pk)
364 request.user = self.user_author
365 submission.submit(self.user_author)
366 submission = Submission.objects.get(pk=submission.pk)
367 status = rights.get_submission_status(submission)
368 self.assertEqual(status.status, SubmissionStatus.TODO)
370 # ACCEPTED submission
371 submission.state = SubmissionState.ACCEPTED.value
372 submission.save()
373 submission = Submission.objects.get(pk=submission.pk)
374 status = rights.get_submission_status(submission)
375 self.assertEqual(status.status, SubmissionStatus.DONE)
377 # REJECTED submission
378 submission.state = SubmissionState.REJECTED.value
379 submission.save()
380 submission = Submission.objects.get(pk=submission.pk)
381 status = rights.get_submission_status(submission)
382 self.assertEqual(status.status, SubmissionStatus.DONE)
385class EditorUtilsTestCase(BaseTestCase):
386 def test_section_editors(self):
387 journal_section_1 = JournalSectionFactory.create()
388 journal_section_2 = JournalSectionFactory.create(parent=journal_section_1)
389 journal_section_3 = JournalSectionFactory.create(parent=journal_section_1)
390 journal_section_4 = JournalSectionFactory.create(parent=journal_section_2)
392 submission = SubmissionFactory.create(journal_section=journal_section_4)
394 user_editor_1 = UserFactory.create()
395 user_editor_2 = UserFactory.create()
396 user_editor_3 = UserFactory.create()
397 user_editor_4 = UserFactory.create()
399 EditorSectionRight.objects.create(journal_section=journal_section_1, user=user_editor_1)
400 EditorSectionRight.objects.create(journal_section=journal_section_2, user=user_editor_2)
401 EditorSectionRight.objects.create(journal_section=journal_section_3, user=user_editor_3)
402 EditorSectionRight.objects.create(journal_section=journal_section_4, user=user_editor_4)
404 EditorSubmissionRight.objects.create(submission=submission, user=user_editor_3)
406 section_editors = get_section_editors(submission)
407 self.assertEqual(len(section_editors), 3)
408 self.assertIn(user_editor_1, section_editors)
409 self.assertIn(user_editor_2, section_editors)
410 self.assertIn(user_editor_4, section_editors)