Coverage for src / mesh / tests / roles / test_editor.py: 100%
298 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-08-11 09:47 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-08-11 09:47 +0000
1from datetime import datetime, timedelta
2from unittest.mock import patch
4from mesh.models.orm.editorial_models import EditorSectionRight, EditorSubmissionRight
5from mesh.models.orm.factories import (
6 JournalSectionFactory,
7 ReviewFactory,
8 SubmissionAuthorFactory,
9 SubmissionFactory,
10 SubmissionVersionFactory,
11 UserFactory,
12)
13from mesh.models.orm.journal_models import JournalSection
14from mesh.models.orm.submission_models import Submission, SubmissionMainFile, SubmissionState
15from mesh.models.orm.user_models import User
16from mesh.models.roles.editor import Editor, get_section_editors
17from mesh.models.submission_status import SubmissionStatus
18from mesh.tests.base_test_case import BaseTestCase
21class EditorTestCase(BaseTestCase):
22 used_models = [
23 EditorSubmissionRight,
24 EditorSectionRight,
25 Submission,
26 JournalSection,
27 ]
28 class_used_models = [User]
30 @classmethod
31 def setUpClass(cls) -> None:
32 super().setUpClass()
33 cls.user_author = UserFactory.create()
34 cls.user_editor = UserFactory.create()
36 def test_submissions_from_direct_right(self):
37 submission_1 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
38 _submission_2 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
40 role = Editor(self.user_editor)
41 # self.assertFalse(role.active)
43 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission_1)
44 role = Editor(self.user_editor)
45 # self.assertTrue(role.active)
47 submissions = role.get_submissions()
48 self.assertEqual(len(submissions), 1)
49 self.assertEqual(submissions[0], submission_1)
51 # If the editor is also an author, he must have no admin rights over his publications
52 # TODO: is this good ?
53 submission_1.created_by = self.user_editor
54 submission_1.save()
55 role = Editor(self.user_editor)
57 submissions = role.get_submissions()
59 self.assertEqual(len(submissions), 0)
60 # self.assertEqual(submissions[0], submission_1)
62 def test_submissions_from_journal_sections(self):
63 journal_section_1 = JournalSectionFactory.create()
64 journal_section_2 = JournalSectionFactory.create(parent=journal_section_1)
65 journal_section_3 = JournalSectionFactory.create()
67 submission_1 = SubmissionFactory.create(
68 journal_section=journal_section_1, state=SubmissionState.SUBMITTED.value
69 )
70 submission_2 = SubmissionFactory.create(
71 journal_section=journal_section_2, state=SubmissionState.SUBMITTED.value
72 )
73 submission_3 = SubmissionFactory.create( # noqa
74 journal_section=journal_section_3, state=SubmissionState.SUBMITTED.value
75 )
77 EditorSectionRight.objects.create(user=self.user_editor, journal_section=journal_section_1)
78 role = Editor(self.user_editor)
79 # self.assertTrue(role.active)
81 submissions = role.get_submissions()
83 self.assertEqual(len(submissions), 2)
84 self.assertIn(submission_1, submissions)
85 self.assertIn(submission_2, submissions)
87 # Self-made submission are not available to the editor.
88 submission_1.created_by = self.user_editor
89 submission_1.save()
90 role = Editor(self.user_editor)
91 # self.assertTrue(role.active)
93 submissions = role.get_submissions()
94 self.assertEqual(len(submissions), 1)
95 self.assertIn(submission_2, submissions)
97 # OPENED submissions are not availabe to anyone but to its author.
98 submission_2.state = SubmissionState.OPENED.value
99 submission_2.save()
100 role = Editor(self.user_editor)
101 # Editor role is actve if it has rights over any journal_section or any submissions
102 # self.assertTrue(role.active)
104 submissions = role.get_submissions()
106 self.assertEqual(submissions.count(), 0)
108 def test_all_submissions(self):
109 journal_section_1 = JournalSectionFactory.create()
110 journal_section_2 = JournalSectionFactory.create(parent=journal_section_1)
111 journal_section_3 = JournalSectionFactory.create()
113 submission_1 = SubmissionFactory.create(
114 journal_section=journal_section_1, state=SubmissionState.SUBMITTED.value
115 )
116 submission_2 = SubmissionFactory.create(
117 journal_section=journal_section_2, state=SubmissionState.SUBMITTED.value
118 )
119 submission_3 = SubmissionFactory.create( # noqa
120 journal_section=journal_section_3, state=SubmissionState.SUBMITTED.value
121 )
122 submission_4 = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
123 submission_5 = SubmissionFactory.create( # noqa
124 journal_section=journal_section_1,
125 state=SubmissionState.SUBMITTED.value,
126 created_by=self.user_editor,
127 )
129 EditorSectionRight.objects.create(user=self.user_editor, journal_section=journal_section_1)
130 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission_4)
132 role = Editor(self.user_editor)
134 submissions = role.get_submissions()
136 self.assertEqual(len(submissions), 3)
137 self.assertIn(submission_1, submissions)
138 self.assertIn(submission_2, submissions)
139 self.assertIn(submission_4, submissions)
141 # All the following tests are rights exclusive to the Editor+ roles.
142 # We just ensure they resolve to True when the editor has rights over the submission.
143 def test_can_invite_reviewer(self):
144 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
145 version = SubmissionVersionFactory.create(submission=submission, submitted=True)
146 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
148 role = Editor(self.user_editor)
150 submission = role.get_submissions().get(pk=submission.pk)
151 self.assertIn(version, submission.versions_censored)
152 version = next(v for v in submission.versions_censored if v == version)
154 self.assertFalse(role.can_invite_reviewer(version))
156 version.review_open = True
157 version.save()
159 submission = role.get_submissions().get(pk=submission.pk)
160 self.assertIn(version, submission.versions_censored)
161 version = next(v for v in submission.versions_censored if v == version)
163 self.assertTrue(role.can_invite_reviewer(version))
165 def test_can_access_version(self):
166 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
167 version = SubmissionVersionFactory.create(submission=submission)
168 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
169 role = Editor(self.user_editor)
171 submission = role.get_submissions().get(pk=submission.pk)
173 self.assertFalse(role.can_access_version(version))
174 self.assertNotIn(version, submission.versions_censored)
175 version.submitted = True
176 version.save()
178 submission = role.get_submissions().get(pk=submission.pk)
179 self.assertIn(version, submission.versions_censored)
180 version = next(v for v in submission.versions_censored if v == version)
181 self.assertTrue(role.can_access_version(version))
183 def test_managed_users(self):
184 User.objects.all().delete()
185 user_editor = UserFactory.create()
186 user_author_1 = UserFactory.create()
187 user_author_2 = UserFactory.create()
188 user_reviewer = UserFactory.create()
189 user_editor_2 = UserFactory.create()
190 user_editor_3 = UserFactory.create()
191 user_journal_manager = UserFactory.create(journal_manager=True)
192 user_admin = UserFactory.create(is_superuser=True) # noqa
194 submission_1 = SubmissionFactory.create(
195 created_by=user_author_1, state=SubmissionState.SUBMITTED.value
196 )
197 version_1 = SubmissionVersionFactory(submission=submission_1, submitted=True)
198 submission_2 = SubmissionFactory.create(
199 created_by=user_author_2, state=SubmissionState.SUBMITTED.value
200 )
201 review = ReviewFactory.create(reviewer=user_reviewer, version=version_1) # noqa
203 EditorSubmissionRight.objects.create(user=user_editor, submission=submission_1)
204 EditorSubmissionRight.objects.create(user=user_editor_2, submission=submission_2)
206 journal_section = JournalSectionFactory.create(created_by=user_journal_manager)
207 EditorSectionRight.objects.create(journal_section=journal_section, user=user_editor_3)
209 role = Editor(user_editor)
210 managed_users = role.get_managed_users()
211 self.assertEqual(len(managed_users), 3)
212 self.assertIn(user_author_1, managed_users)
213 self.assertIn(user_author_2, managed_users)
214 self.assertIn(user_reviewer, managed_users)
216 def test_can_impersonate(self):
217 role = Editor(self.user_editor)
218 self.assertTrue(role.can_impersonate())
220 def test_can_access_submission_log(self):
221 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
222 role = Editor(self.user_editor)
223 with self.assertRaises(Submission.DoesNotExist):
224 submission = role.get_submissions().get(pk=submission.pk)
225 # self.assertFalse(role.can_access_submission_log(submission))
227 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
228 role = Editor(self.user_editor)
230 submission = role.get_submissions().get(pk=submission.pk)
231 self.assertTrue(role.can_access_submission_log(submission))
233 def test_can_create_editorial_decision(self):
234 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
235 role = Editor(self.user_editor)
236 with self.assertRaises(Submission.DoesNotExist):
237 submission = role.get_submissions().get(pk=submission.pk)
238 # self.assertFalse(role.can_create_editorial_decision(submission))
240 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
241 role = Editor(self.user_editor)
243 submission = role.get_submissions().get(pk=submission.pk)
244 self.assertTrue(role.can_create_editorial_decision(submission))
246 submission.state = SubmissionState.ON_REVIEW.value
247 submission.save()
248 role = Editor(self.user_editor)
250 submission = role.get_submissions().get(pk=submission.pk)
251 self.assertTrue(role.can_create_editorial_decision(submission))
253 submission.state = SubmissionState.REVISION_REQUESTED.value
254 submission.save()
255 role = Editor(self.user_editor)
257 submission = role.get_submissions().get(pk=submission.pk)
258 self.assertTrue(role.can_create_editorial_decision(submission))
260 submission.state = SubmissionState.REVISION_SUBMITTED.value
261 submission.save()
262 role = Editor(self.user_editor)
264 submission = role.get_submissions().get(pk=submission.pk)
265 self.assertTrue(role.can_create_editorial_decision(submission))
267 submission.state = SubmissionState.ACCEPTED.value
268 submission.save()
269 role = Editor(self.user_editor)
271 submission = role.get_submissions().get(pk=submission.pk)
272 self.assertTrue(role.can_create_editorial_decision(submission))
274 submission.state = SubmissionState.REJECTED.value
275 submission.save()
276 role = Editor(self.user_editor)
278 submission = role.get_submissions().get(pk=submission.pk)
279 self.assertTrue(role.can_create_editorial_decision(submission))
281 def test_can_start_review_process(self):
282 submission = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
284 role = Editor(self.user_editor)
285 with self.assertRaises(Submission.DoesNotExist):
286 submission = role.get_submissions().get(pk=submission.pk)
287 # with patch.object(submission, "is_reviewable", lambda _: True):
288 # self.assertFalse(role.can_start_review_process(submission))
290 # with patch.object(submission, "is_reviewable", lambda _: False):
291 # self.assertFalse(role.can_start_review_process(submission))
293 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
294 role = Editor(self.user_editor)
296 submission = role.get_submissions().get(pk=submission.pk)
297 with patch.object(Submission, "is_reviewable", lambda _: True):
298 self.assertTrue(role.can_start_review_process(submission))
300 with patch.object(Submission, "is_reviewable", lambda _: False):
301 self.assertFalse(role.can_start_review_process(submission))
303 def test_can_assign_editor(self):
304 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
305 role = Editor(self.user_editor)
306 with self.assertRaises(Submission.DoesNotExist):
307 submission = role.get_submissions().get(pk=submission.pk)
308 # self.assertFalse(role.can_assign_editor(submission))
310 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
311 role = Editor(self.user_editor)
313 submission = role.get_submissions().get(pk=submission.pk)
314 self.assertTrue(role.can_assign_editor(submission))
316 def test_can_filter_submissions(self):
317 role = Editor(self.user_editor)
318 self.assertTrue(role.can_filter_submissions())
320 def test_can_access_journal_sections(self):
321 role = Editor(self.user_editor)
322 self.assertTrue(role.can_access_journal_sections())
324 def test_can_edit_review_file_right(self):
325 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED.value)
326 version = SubmissionVersionFactory.create(submission=submission, submitted=True)
327 review = ReviewFactory.create(version=version, submitted=True)
328 role = Editor(self.user_editor)
329 with self.assertRaises(Submission.DoesNotExist):
330 submission = role.get_submissions().get(pk=submission.pk)
331 # self.assertFalse(role.can_edit_review_file_right(review))
333 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
334 role = Editor(self.user_editor)
336 submission = role.get_submissions().get(pk=submission.pk)
337 version = next(v for v in submission.versions_censored if v == version)
338 review = next(r for r in version.reviews_censored if r == review)
339 self.assertTrue(role.can_edit_review_file_right(review, submission=submission))
341 def test_editor_submission_status(self):
342 """
343 Test the editor status wrt. the whole submission workflow
344 """
345 submission = SubmissionFactory.create(author_agreement=True)
346 version = SubmissionVersionFactory.create(
347 submission=submission, submitted=False, review_open=False
348 )
349 SubmissionAuthorFactory.create(submission=submission)
350 SubmissionMainFile.objects.create(file=self.dummy_file, attached_to=version)
352 # No rights over the submission
353 role = Editor(self.user_editor)
354 with self.assertRaises(Submission.DoesNotExist):
355 submission = role.get_submissions().get(pk=submission.pk)
357 # status = role.get_submission_status(submission)
358 # self.assertEqual(status.status, SubmissionStatus.ERROR)
360 # OPENED submission
361 EditorSubmissionRight.objects.create(user=self.user_editor, submission=submission)
362 role = Editor(self.user_editor)
363 with self.assertRaises(Submission.DoesNotExist):
364 submission = role.get_submissions().get(pk=submission.pk)
365 # status = role.get_submission_status(submission)
366 # self.assertEqual(status.status, SubmissionStatus.ERROR)
368 # SUBMITTED submission
369 request = self.dummy_request()
370 request.user = submission.created_by
371 submission.submit(submission.created_by)
373 submission = role.get_submissions().get(pk=submission.pk)
374 status = role.get_submission_status(submission)
375 self.assertEqual(status.status, SubmissionStatus.TODO)
377 # UNDER REVIEW submission with no reviews
378 # request.user = self.user_editor
379 # submission.start_review_process(self.user_editor)
380 # with patch.object(role, "authors_string_annotate", Value("SQLITE_NOT_SUPPORTED")):
381 # submission = role.get_submissions().get(pk=submission.pk)
382 # status = role.get_submission_status(submission)
383 # self.assertEqual(status.status, SubmissionStatus.TODO)
385 # UNDER REVIEW with pending answer
386 review = ReviewFactory.create(version=version)
388 submission = role.get_submissions().get(pk=submission.pk)
389 status = role.get_submission_status(submission)
390 self.assertEqual(status.status, SubmissionStatus.WAITING)
392 # UNDER REVIEW with 1 pending review & 1 overdue review
393 yesterday = (datetime.utcnow() - timedelta(days=1)).date()
394 review_overdue = ReviewFactory.create(version=version, date_response_due=yesterday)
396 submission = role.get_submissions().get(pk=submission.pk)
397 status = role.get_submission_status(submission)
398 self.assertEqual(status.status, SubmissionStatus.TODO)
400 # UNDER REVIEW with 1 pending review, 1 pending answer
401 review_overdue.date_response_due = (datetime.utcnow() + timedelta(days=1)).date()
402 review_overdue.accepted = True
403 review_overdue.save()
405 submission = role.get_submissions().get(pk=submission.pk)
406 status = role.get_submission_status(submission)
407 self.assertEqual(status.status, SubmissionStatus.WAITING)
409 # UNDER REVIEW with all reviews submitted or declined
410 review.accepted = False
411 review.save()
412 review_overdue.submitted = True
413 review_overdue.save()
415 submission = role.get_submissions().get(pk=submission.pk)
416 status = role.get_submission_status(submission)
417 self.assertEqual(status.status, SubmissionStatus.TODO)
419 # REVISIIONS REQUESTED submission
420 submission.state = SubmissionState.REVISION_REQUESTED.value
421 submission.save()
423 submission = role.get_submissions().get(pk=submission.pk)
424 status = role.get_submission_status(submission)
425 self.assertEqual(status.status, SubmissionStatus.WAITING)
426 version.review_open = False
427 version.save()
429 # REVISIONS SUBMITTED submission
430 version_2 = SubmissionVersionFactory.create(
431 submission=submission, submitted=False, review_open=False
432 )
433 SubmissionMainFile.objects.create(file=self.dummy_file, attached_to=version_2)
434 submission = Submission.objects.get(pk=submission.pk)
435 request.user = self.user_author
436 submission.submit(self.user_author)
438 submission = role.get_submissions().get(pk=submission.pk)
439 status = role.get_submission_status(submission)
440 self.assertEqual(status.status, SubmissionStatus.TODO)
442 # ACCEPTED submission
443 submission.state = SubmissionState.ACCEPTED.value
444 submission.save()
446 submission = role.get_submissions().get(pk=submission.pk)
447 status = role.get_submission_status(submission)
448 self.assertEqual(status.status, SubmissionStatus.DONE)
450 # REJECTED submission
451 submission.state = SubmissionState.REJECTED.value
452 submission.save()
454 submission = role.get_submissions().get(pk=submission.pk)
455 status = role.get_submission_status(submission)
456 self.assertEqual(status.status, SubmissionStatus.DONE)
459class EditorUtilsTestCase(BaseTestCase):
460 def test_section_editors(self):
461 journal_section_1 = JournalSectionFactory.create()
462 journal_section_2 = JournalSectionFactory.create(parent=journal_section_1)
463 journal_section_3 = JournalSectionFactory.create(parent=journal_section_1)
464 journal_section_4 = JournalSectionFactory.create(parent=journal_section_2)
466 submission = SubmissionFactory.create(journal_section=journal_section_4)
468 user_editor_1 = UserFactory.create()
469 user_editor_2 = UserFactory.create()
470 user_editor_3 = UserFactory.create()
471 user_editor_4 = UserFactory.create()
473 EditorSectionRight.objects.create(journal_section=journal_section_1, user=user_editor_1)
474 EditorSectionRight.objects.create(journal_section=journal_section_2, user=user_editor_2)
475 EditorSectionRight.objects.create(journal_section=journal_section_3, user=user_editor_3)
476 EditorSectionRight.objects.create(journal_section=journal_section_4, user=user_editor_4)
478 EditorSubmissionRight.objects.create(submission=submission, user=user_editor_3)
480 section_editors = get_section_editors(submission)
481 self.assertEqual(len(section_editors), 3)
482 self.assertIn(user_editor_1, section_editors)
483 self.assertIn(user_editor_2, section_editors)
484 self.assertIn(user_editor_4, section_editors)