Coverage for src / mesh / tests / views / test_submission_views.py: 100%
246 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 __future__ import annotations
3from mesh.models.filters import FilterSet
4from mesh.models.orm.editorial_models import EditorSubmissionRight
5from mesh.models.orm.factories import (
6 JournalSectionFactory,
7 ReviewFactory,
8 SubmissionFactory,
9 SubmissionVersionFactory,
10 UserFactory,
11)
12from mesh.models.orm.journal_models import JournalSection
13from mesh.models.orm.submission_models import Submission, SubmissionState
14from mesh.models.orm.user_models import User
15from mesh.models.roles.editor import Editor
16from mesh.models.roles.journal_manager import JournalManager
17from mesh.models.submission_status import SubmissionStatus
18from mesh.tests.base_test_case import BaseTestCase
19from mesh.views import views_submission
20from mesh.views.components.review_summary import (
21 CountWithTotal,
22 ReviewSummary,
23 build_review_summary,
24)
25from mesh.views.components.submission_list import SubmissionListConfig
27submission_todo_1: Submission | None = None
28submission_todo_2: Submission | None = None
29submission_waiting_1: Submission | None = None
30submission_waiting_2: Submission | None = None
31submission_waiting_3: Submission | None = None
32submission_done_1: Submission | None = None
33submission_error_1: Submission | None = None
34journal_section: JournalSection | None = None
37def create_global_submissions():
38 global submission_todo_1
39 global submission_todo_2
40 global submission_waiting_1
41 global submission_waiting_2
42 global submission_waiting_3
43 global submission_done_1
44 global submission_error_1
45 global journal_section
46 journal_section = JournalSectionFactory.create()
47 submission_todo_1 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
48 submission_todo_2 = SubmissionFactory.create(
49 state=SubmissionState.REVISION_REQUESTED.value, journal_section=journal_section
50 )
51 submission_waiting_1 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
52 submission_waiting_2 = SubmissionFactory.create(state=SubmissionState.SUBMITTED)
53 submission_waiting_3 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
54 submission_done_1 = SubmissionFactory.create(
55 state=SubmissionState.ON_REVIEW.value, journal_section=journal_section
56 )
57 submission_error_1 = SubmissionFactory.create(state=SubmissionState.REJECTED.value)
59 SubmissionVersionFactory.create(submission=submission_todo_1, submitted=True)
60 SubmissionVersionFactory.create(submission=submission_todo_2, submitted=True)
61 SubmissionVersionFactory.create(submission=submission_waiting_1, submitted=True)
62 SubmissionVersionFactory.create(submission=submission_waiting_2, submitted=True)
63 SubmissionVersionFactory.create(submission=submission_waiting_3, submitted=True)
64 SubmissionVersionFactory.create(submission=submission_done_1, submitted=True)
65 SubmissionVersionFactory.create(submission=submission_error_1, submitted=True)
68def generate_grouped_function(role):
69 _submission_todo_1 = role.get_submissions().get(pk=submission_todo_1.pk)
70 _submission_todo_2 = role.get_submissions().get(pk=submission_todo_2.pk)
71 _submission_waiting_1 = role.get_submissions().get(pk=submission_waiting_1.pk)
72 _submission_waiting_2 = role.get_submissions().get(pk=submission_waiting_2.pk)
73 _submission_waiting_3 = role.get_submissions().get(pk=submission_waiting_3.pk)
74 _submission_done_1 = role.get_submissions().get(pk=submission_done_1.pk)
75 _submission_error_1 = role.get_submissions().get(pk=submission_error_1.pk)
77 def grouped_submissions_per_status(submissions, role_handler):
78 return {
79 SubmissionStatus.TODO: [_submission_todo_1, _submission_todo_2],
80 SubmissionStatus.WAITING: [
81 _submission_waiting_1,
82 _submission_waiting_2,
83 _submission_waiting_3,
84 ],
85 SubmissionStatus.DONE: [_submission_done_1],
86 SubmissionStatus.ERROR: [_submission_error_1],
87 }
89 return grouped_submissions_per_status
92def submission_list_config_in_filters():
93 return [
94 SubmissionListConfig(
95 key=SubmissionStatus.TODO,
96 title="Requires action",
97 html_classes="todo",
98 in_filters=False,
99 ),
100 SubmissionListConfig(
101 key=SubmissionStatus.WAITING,
102 title="Waiting for other's input",
103 html_classes="waiting",
104 ),
105 SubmissionListConfig(
106 key=SubmissionStatus.DONE,
107 title="Done",
108 html_classes="done",
109 ),
110 ]
113def submission_list_config_display():
114 return [
115 SubmissionListConfig(
116 key=SubmissionStatus.TODO,
117 title="Requires action",
118 html_classes="todo",
119 display=False,
120 ),
121 SubmissionListConfig(
122 key=SubmissionStatus.WAITING,
123 title="Waiting for other's input",
124 html_classes="waiting",
125 ),
126 SubmissionListConfig(
127 key=SubmissionStatus.DONE,
128 title="Done",
129 html_classes="done",
130 ),
131 ]
134class SubmissionViewsTestCase(BaseTestCase):
135 class_used_models = [Submission, JournalSection, User]
137 @classmethod
138 def setUpClass(cls) -> None:
139 super().setUpClass()
140 cls.user = UserFactory.create(journal_manager=True)
141 create_global_submissions()
143 def test_group_submissions_per_status(self):
144 role = JournalManager(self.user)
146 submissions = role.get_submissions()
148 grouped_submissions = views_submission.group_submissions_per_status(submissions, role)
149 self.assertEqual(len(grouped_submissions), 3)
151 group = grouped_submissions[SubmissionStatus.TODO]
152 self.assertEqual(len(group), 5)
154 group = grouped_submissions[SubmissionStatus.WAITING]
155 self.assertEqual(len(group), 1)
157 group = grouped_submissions[SubmissionStatus.DONE]
158 self.assertEqual(len(group), 1)
160 # @patch.object(
161 # JournalManagerRights,
162 # "get_submission_list_config",
163 # Mock(return_value=base_submission_list_config()),
164 # )
165 def test_submissions_list_grouping(self):
166 role = JournalManager(self.user)
168 grouped_submissions_per_status = generate_grouped_function(role)
170 request = self.dummy_request("/")
172 context = views_submission.prepare_submissions_lists(
173 role, request, group_submissions_ftor=grouped_submissions_per_status
174 )
176 submissions_config = context["submissions_config"]
177 self.assertEqual(len(submissions_config), 3)
179 config = submissions_config[0]
180 self.assertEqual(config.key, SubmissionStatus.TODO)
181 self.assertEqual(len(config.all_submissions), 2)
182 self.assertEqual(len(config.submissions), 2)
184 config = submissions_config[1]
185 self.assertEqual(config.key, SubmissionStatus.WAITING)
186 self.assertEqual(len(config.all_submissions), 3)
187 self.assertEqual(len(config.submissions), 3)
189 config = submissions_config[2]
190 self.assertEqual(config.key, SubmissionStatus.DONE)
191 self.assertEqual(len(config.all_submissions), 1)
192 self.assertEqual(len(config.submissions), 1)
194 submission_count = context["submission_count"]
195 self.assertEqual(submission_count, CountWithTotal(value=6, total=6))
197 # @patch.object(
198 # JournalManagerRights,
199 # "get_submission_list_config",
200 # Mock(return_value=base_submission_list_config()),
201 # )
202 def test_submissions_list_filtering(self):
203 role = JournalManager(self.user)
204 # Test single filter
205 query_params = {"_filter_state": [SubmissionState.ON_REVIEW.value]}
206 request = self.request_factory.get("/", data=query_params)
208 grouped_submissions_per_status = generate_grouped_function(role)
210 context = views_submission.prepare_submissions_lists(
211 role, request, group_submissions_ftor=grouped_submissions_per_status
212 )
214 submissions_config = context["submissions_config"]
215 self.assertEqual(len(submissions_config), 3)
217 config = submissions_config[0]
218 self.assertEqual(config.key, SubmissionStatus.TODO)
219 self.assertEqual(len(config.all_submissions), 2)
220 self.assertEqual(len(config.submissions), 1)
222 config = submissions_config[1]
223 self.assertEqual(config.key, SubmissionStatus.WAITING)
224 self.assertEqual(len(config.all_submissions), 3)
225 self.assertEqual(len(config.submissions), 2)
227 config = submissions_config[2]
228 self.assertEqual(config.key, SubmissionStatus.DONE)
229 self.assertEqual(len(config.all_submissions), 1)
230 self.assertEqual(len(config.submissions), 1)
232 query_params = {"_filter_state": [SubmissionState.REVISION_REQUESTED.value]}
233 request = self.request_factory.get("/", data=query_params)
235 context = views_submission.prepare_submissions_lists(
236 role, request, group_submissions_ftor=grouped_submissions_per_status
237 )
239 submissions_config = context["submissions_config"]
240 self.assertEqual(len(submissions_config), 3)
242 config = submissions_config[0]
243 self.assertEqual(config.key, SubmissionStatus.TODO)
244 self.assertEqual(len(config.all_submissions), 2)
245 self.assertEqual(len(config.submissions), 1)
247 config = submissions_config[1]
248 self.assertEqual(config.key, SubmissionStatus.WAITING)
249 self.assertEqual(len(config.all_submissions), 3)
250 self.assertEqual(len(config.submissions), 0)
252 config = submissions_config[2]
253 self.assertEqual(config.key, SubmissionStatus.DONE)
254 self.assertEqual(len(config.all_submissions), 1)
255 self.assertEqual(len(config.submissions), 0)
257 # Test single filter with multiple values
258 query_params = {
259 "_filter_state": [
260 SubmissionState.REVISION_REQUESTED.value,
261 SubmissionState.ON_REVIEW.value,
262 ]
263 }
264 request = self.request_factory.get("/", data=query_params)
266 context = views_submission.prepare_submissions_lists(
267 role, request, group_submissions_ftor=grouped_submissions_per_status
268 )
270 submissions_config = context["submissions_config"]
271 self.assertEqual(len(submissions_config), 3)
273 config = submissions_config[0]
274 self.assertEqual(config.key, SubmissionStatus.TODO)
275 self.assertEqual(len(config.all_submissions), 2)
276 self.assertEqual(len(config.submissions), 2)
278 config = submissions_config[1]
279 self.assertEqual(config.key, SubmissionStatus.WAITING)
280 self.assertEqual(len(config.all_submissions), 3)
281 self.assertEqual(len(config.submissions), 2)
283 config = submissions_config[2]
284 self.assertEqual(config.key, SubmissionStatus.DONE)
285 self.assertEqual(len(config.all_submissions), 1)
286 self.assertEqual(len(config.submissions), 1)
288 # Test multiple filters behaviour
289 query_params = {
290 "_filter_state": [
291 SubmissionState.REVISION_REQUESTED.value,
292 SubmissionState.ON_REVIEW.value,
293 ],
294 "_filter_journal_section": [journal_section.pk],
295 }
296 request = self.request_factory.get("/", data=query_params)
298 context = views_submission.prepare_submissions_lists(
299 role, request, group_submissions_ftor=grouped_submissions_per_status
300 )
302 submissions_config = context["submissions_config"]
303 self.assertEqual(len(submissions_config), 3)
305 config = submissions_config[0]
306 self.assertEqual(config.key, SubmissionStatus.TODO)
307 self.assertEqual(len(config.all_submissions), 2)
308 self.assertEqual(len(config.submissions), 1)
310 config = submissions_config[1]
311 self.assertEqual(config.key, SubmissionStatus.WAITING)
312 self.assertEqual(len(config.all_submissions), 3)
313 self.assertEqual(len(config.submissions), 0)
315 config = submissions_config[2]
316 self.assertEqual(config.key, SubmissionStatus.DONE)
317 self.assertEqual(len(config.all_submissions), 1)
318 self.assertEqual(len(config.submissions), 1)
320 filters: FilterSet = context["filters"]
321 filter = filters.get_filter("state")
322 self.assertEqual(len(filter.values), 3)
323 self.assertEqual(len(filter.active_values), 2)
325 def test_submissions_list_filtering_settings(self):
326 role = JournalManager(self.user)
327 # Test single filter
328 query_params = {"_filter_state": [SubmissionState.ON_REVIEW.value]}
329 request = self.request_factory.get("/", data=query_params)
331 grouped_submissions_per_status = generate_grouped_function(role)
333 # with patch.object(
334 # JournalManagerRights,
335 # "get_submission_list_config",
336 # Mock(return_value=base_submission_list_config()),
337 # ):
339 context = views_submission.prepare_submissions_lists(
340 role, request, group_submissions_ftor=grouped_submissions_per_status
341 )
343 filters = context["filters"]
344 filter = filters.get_filter("state")
345 self.assertEqual(len(filter.values), 3)
347 # with patch.object(
348 # JournalManagerRights,
349 # "get_submission_list_config",
350 # Mock(return_value=base_config),
351 # ):
353 context = views_submission.prepare_submissions_lists(
354 role,
355 request,
356 list_config_ftor=submission_list_config_in_filters,
357 group_submissions_ftor=grouped_submissions_per_status,
358 )
360 filters = context["filters"]
361 filter = filters.get_filter("state")
362 self.assertEqual(len(filter.values), 2)
364 submissions_config = context["submissions_config"]
366 config = submissions_config[0]
367 self.assertEqual(config.key, SubmissionStatus.TODO)
368 self.assertEqual(len(config.all_submissions), 2)
369 self.assertEqual(len(config.submissions), 2)
371 config = submissions_config[1]
372 self.assertEqual(config.key, SubmissionStatus.WAITING)
373 self.assertEqual(len(config.all_submissions), 3)
374 self.assertEqual(len(config.submissions), 2)
376 submission_count = context["submission_count"]
377 self.assertEqual(submission_count, CountWithTotal(value=3, total=4))
379 # with patch.object(
380 # JournalManagerRights,
381 # "get_submission_list_config",
382 # Mock(return_value=base_config),
383 # ):
385 context = views_submission.prepare_submissions_lists(
386 role,
387 request,
388 list_config_ftor=submission_list_config_display,
389 group_submissions_ftor=grouped_submissions_per_status,
390 )
392 filters: FilterSet = context["filters"]
393 filter = filters.get_filter("state")
394 self.assertEqual(len(filter.values), 3)
396 submissions_config = context["submissions_config"]
398 config = submissions_config[0]
399 self.assertEqual(config.key, SubmissionStatus.TODO)
400 self.assertEqual(len(config.all_submissions), 2)
401 self.assertEqual(len(config.submissions), 0)
403 config = submissions_config[1]
404 self.assertEqual(config.key, SubmissionStatus.WAITING)
405 self.assertEqual(len(config.all_submissions), 3)
406 self.assertEqual(len(config.submissions), 2)
408 def test_review_summary(self):
409 submission = SubmissionFactory.create(state=SubmissionState.SUBMITTED)
410 EditorSubmissionRight.objects.create(user=self.user, submission=submission)
411 role = Editor(self.user)
413 submission = role.get_submissions().get(pk=submission.pk)
415 review_summary = build_review_summary(submission)
416 self.assertEqual(review_summary.current_version, 0)
418 version = SubmissionVersionFactory.create(submission=submission, submitted=False)
420 submission = role.get_submissions().get(pk=submission.pk)
422 # Version is not yet submitted : Editor should not be allowed to view it
423 review_summary = build_review_summary(submission)
424 expected = ReviewSummary(
425 current_version=0,
426 reviewers_count=CountWithTotal(value=0, total=0),
427 reports_count=CountWithTotal(value=0, total=0),
428 )
429 self.assertEqual(expected, review_summary)
431 version.submitted = True
432 version.save()
433 submission = role.get_submissions().get(pk=submission.pk)
434 review_summary = build_review_summary(submission)
435 expected = ReviewSummary(
436 current_version=1,
437 reviewers_count=CountWithTotal(value=0, total=0),
438 reports_count=CountWithTotal(value=0, total=0),
439 )
440 self.assertEqual(expected, review_summary)
442 ReviewFactory.create(version=version)
444 submission = role.get_submissions().get(pk=submission.pk)
446 review_summary = build_review_summary(submission)
447 expected = ReviewSummary(
448 current_version=1,
449 reviewers_count=CountWithTotal(value=0, total=1),
450 reports_count=CountWithTotal(value=0, total=0),
451 )
452 self.assertEqual(expected, review_summary)
454 version_2 = SubmissionVersionFactory.create(submission=submission)
456 # Version is not yet submitted : Editor should not be allowed to view it
457 submission = role.get_submissions().get(pk=submission.pk)
459 review_summary = build_review_summary(submission)
460 expected = ReviewSummary(
461 current_version=1,
462 reviewers_count=CountWithTotal(value=0, total=1),
463 reports_count=CountWithTotal(value=0, total=0),
464 )
465 self.assertEqual(expected, review_summary)
467 version_2.submitted = True
468 version_2.save()
470 submission = role.get_submissions().get(pk=submission.pk)
472 review_summary = build_review_summary(submission)
473 expected = ReviewSummary(
474 current_version=2,
475 reviewers_count=CountWithTotal(value=0, total=0),
476 reports_count=CountWithTotal(value=0, total=0),
477 )
478 self.assertEqual(expected, review_summary)
480 ReviewFactory.create(version=version_2, accepted=False)
481 ReviewFactory.create(version=version_2)
482 ReviewFactory.create(version=version_2, accepted=True)
483 ReviewFactory.create(version=version_2, accepted=True, submitted=True)
485 submission = role.get_submissions().get(pk=submission.pk)
487 review_summary = build_review_summary(submission)
488 expected = ReviewSummary(
489 current_version=2,
490 reviewers_count=CountWithTotal(value=3, total=4),
491 reports_count=CountWithTotal(value=1, total=2),
492 )
493 self.assertEqual(expected, review_summary)