Coverage for src/mesh/tests/views/test_submission_views.py: 100%
223 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 __future__ import annotations
3from unittest.mock import patch
5from mesh.model.filters import Filter, FilterSet
6from mesh.model.roles.role_handler import RoleHandler
8from ...model.submission_status import SubmissionStatus
9from ...models.factories import (
10 JournalSectionFactory,
11 ReviewFactory,
12 SubmissionFactory,
13 SubmissionVersionFactory,
14 UserFactory,
15)
16from ...models.journal_models import JournalSection
17from ...models.submission_models import Submission, SubmissionState
18from ...models.user_models import User
19from ...views import views_submission
20from ...views.components.review_summary import CountWithTotal, ReviewSummary, build_review_summary
21from ...views.components.submission_list import SubmissionListConfig
22from ..base_test_case import BaseTestCase
24submission_todo_1: Submission | None = None
25submission_todo_2: Submission | None = None
26submission_waiting_1: Submission | None = None
27submission_waiting_2: Submission | None = None
28submission_waiting_3: Submission | None = None
29submission_done_1: Submission | None = None
30submission_error_1: Submission | None = None
31journal_section: JournalSection | None = None
34def create_global_submissions():
35 global submission_todo_1
36 global submission_todo_2
37 global submission_waiting_1
38 global submission_waiting_2
39 global submission_waiting_3
40 global submission_done_1
41 global submission_error_1
42 global journal_section
43 journal_section = JournalSectionFactory.create()
44 submission_todo_1 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
45 submission_todo_2 = SubmissionFactory.create(
46 state=SubmissionState.REVISION_REQUESTED.value, journal_section=journal_section
47 )
48 submission_waiting_1 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
49 submission_waiting_2 = SubmissionFactory.create(state=SubmissionState.SUBMITTED)
50 submission_waiting_3 = SubmissionFactory.create(state=SubmissionState.ON_REVIEW.value)
51 submission_done_1 = SubmissionFactory.create(
52 state=SubmissionState.ON_REVIEW.value, journal_section=journal_section
53 )
54 submission_error_1 = SubmissionFactory.create(state=SubmissionState.REJECTED.value)
56 SubmissionVersionFactory.create(submission=submission_todo_1, submitted=True)
57 SubmissionVersionFactory.create(submission=submission_todo_2, submitted=True)
58 SubmissionVersionFactory.create(submission=submission_waiting_1, submitted=True)
59 SubmissionVersionFactory.create(submission=submission_waiting_2, submitted=True)
60 SubmissionVersionFactory.create(submission=submission_waiting_3, submitted=True)
61 SubmissionVersionFactory.create(submission=submission_done_1, submitted=True)
62 SubmissionVersionFactory.create(submission=submission_error_1, submitted=True)
65def grouped_submissions_per_status(submissions, role_handler):
66 return {
67 SubmissionStatus.TODO: [submission_todo_1, submission_todo_2],
68 SubmissionStatus.WAITING: [
69 submission_waiting_1,
70 submission_waiting_2,
71 submission_waiting_3,
72 ],
73 SubmissionStatus.DONE: [submission_done_1],
74 SubmissionStatus.ERROR: [submission_error_1],
75 }
78def submission_list_config_in_filters():
79 return [
80 SubmissionListConfig(
81 key=SubmissionStatus.TODO,
82 title="Requires action",
83 html_classes="todo",
84 in_filters=False,
85 ),
86 SubmissionListConfig(
87 key=SubmissionStatus.WAITING,
88 title="Waiting for other's input",
89 html_classes="waiting",
90 ),
91 SubmissionListConfig(
92 key=SubmissionStatus.DONE,
93 title="Done",
94 html_classes="done",
95 ),
96 ]
99def submission_list_config_display():
100 return [
101 SubmissionListConfig(
102 key=SubmissionStatus.TODO,
103 title="Requires action",
104 html_classes="todo",
105 display=False,
106 ),
107 SubmissionListConfig(
108 key=SubmissionStatus.WAITING,
109 title="Waiting for other's input",
110 html_classes="waiting",
111 ),
112 SubmissionListConfig(
113 key=SubmissionStatus.DONE,
114 title="Done",
115 html_classes="done",
116 ),
117 ]
120class SubmissionViewsTestCase(BaseTestCase):
121 class_used_models = [Submission, JournalSection, User]
123 @classmethod
124 def setUpClass(cls) -> None:
125 super().setUpClass()
126 cls.user = UserFactory.create(journal_manager=True)
127 create_global_submissions()
129 def test_group_submissions_per_status(self):
130 submissions = Submission.objects.get_submissions().all()
131 role_handler = RoleHandler(self.user)
133 grouped_submissions = views_submission.group_submissions_per_status(
134 submissions, role_handler
135 )
136 self.assertEqual(len(grouped_submissions), 3)
138 group = grouped_submissions[SubmissionStatus.TODO]
139 self.assertEqual(len(group), 5)
141 group = grouped_submissions[SubmissionStatus.WAITING]
142 self.assertEqual(len(group), 1)
144 group = grouped_submissions[SubmissionStatus.DONE]
145 self.assertEqual(len(group), 1)
147 @patch.object(views_submission, "group_submissions_per_status", grouped_submissions_per_status)
148 # @patch.object(
149 # JournalManagerRights,
150 # "get_submission_list_config",
151 # Mock(return_value=base_submission_list_config()),
152 # )
153 def test_submissions_list_grouping(self):
154 role_handler = RoleHandler(self.user)
155 request = self.dummy_request("/")
157 context = views_submission.prepare_submissions_lists(
158 role_handler, request, group_submissions_ftor=grouped_submissions_per_status
159 )
161 submissions_config = context["submissions_config"]
162 self.assertEqual(len(submissions_config), 3)
164 config: SubmissionListConfig = submissions_config[0]
165 self.assertEqual(config.key, SubmissionStatus.TODO)
166 self.assertEqual(len(config.all_submissions), 2)
167 self.assertEqual(len(config.submissions), 2)
169 config: SubmissionListConfig = submissions_config[1]
170 self.assertEqual(config.key, SubmissionStatus.WAITING)
171 self.assertEqual(len(config.all_submissions), 3)
172 self.assertEqual(len(config.submissions), 3)
174 config: SubmissionListConfig = submissions_config[2]
175 self.assertEqual(config.key, SubmissionStatus.DONE)
176 self.assertEqual(len(config.all_submissions), 1)
177 self.assertEqual(len(config.submissions), 1)
179 submission_count = context["submission_count"]
180 self.assertEqual(submission_count, CountWithTotal(value=6, total=6))
182 @patch.object(views_submission, "group_submissions_per_status", grouped_submissions_per_status)
183 # @patch.object(
184 # JournalManagerRights,
185 # "get_submission_list_config",
186 # Mock(return_value=base_submission_list_config()),
187 # )
188 def test_submissions_list_filtering(self):
189 role_handler = RoleHandler(self.user)
190 # Test single filter
191 query_params = {"_filter_state": [SubmissionState.ON_REVIEW.value]}
192 request = self.request_factory.get("/", data=query_params)
193 context = views_submission.prepare_submissions_lists(
194 role_handler, request, group_submissions_ftor=grouped_submissions_per_status
195 )
197 submissions_config = context["submissions_config"]
198 self.assertEqual(len(submissions_config), 3)
200 config: SubmissionListConfig = submissions_config[0]
201 self.assertEqual(config.key, SubmissionStatus.TODO)
202 self.assertEqual(len(config.all_submissions), 2)
203 self.assertEqual(len(config.submissions), 1)
205 config: SubmissionListConfig = submissions_config[1]
206 self.assertEqual(config.key, SubmissionStatus.WAITING)
207 self.assertEqual(len(config.all_submissions), 3)
208 self.assertEqual(len(config.submissions), 2)
210 config: SubmissionListConfig = submissions_config[2]
211 self.assertEqual(config.key, SubmissionStatus.DONE)
212 self.assertEqual(len(config.all_submissions), 1)
213 self.assertEqual(len(config.submissions), 1)
215 query_params = {"_filter_state": [SubmissionState.REVISION_REQUESTED.value]}
216 request = self.request_factory.get("/", data=query_params)
217 context = views_submission.prepare_submissions_lists(
218 role_handler, request, group_submissions_ftor=grouped_submissions_per_status
219 )
221 submissions_config = context["submissions_config"]
222 self.assertEqual(len(submissions_config), 3)
224 config: SubmissionListConfig = submissions_config[0]
225 self.assertEqual(config.key, SubmissionStatus.TODO)
226 self.assertEqual(len(config.all_submissions), 2)
227 self.assertEqual(len(config.submissions), 1)
229 config: SubmissionListConfig = submissions_config[1]
230 self.assertEqual(config.key, SubmissionStatus.WAITING)
231 self.assertEqual(len(config.all_submissions), 3)
232 self.assertEqual(len(config.submissions), 0)
234 config: SubmissionListConfig = submissions_config[2]
235 self.assertEqual(config.key, SubmissionStatus.DONE)
236 self.assertEqual(len(config.all_submissions), 1)
237 self.assertEqual(len(config.submissions), 0)
239 # Test single filter with multiple values
240 query_params = {
241 "_filter_state": [
242 SubmissionState.REVISION_REQUESTED.value,
243 SubmissionState.ON_REVIEW.value,
244 ]
245 }
246 request = self.request_factory.get("/", data=query_params)
247 context = views_submission.prepare_submissions_lists(
248 role_handler, request, group_submissions_ftor=grouped_submissions_per_status
249 )
251 submissions_config = context["submissions_config"]
252 self.assertEqual(len(submissions_config), 3)
254 config: SubmissionListConfig = submissions_config[0]
255 self.assertEqual(config.key, SubmissionStatus.TODO)
256 self.assertEqual(len(config.all_submissions), 2)
257 self.assertEqual(len(config.submissions), 2)
259 config: SubmissionListConfig = submissions_config[1]
260 self.assertEqual(config.key, SubmissionStatus.WAITING)
261 self.assertEqual(len(config.all_submissions), 3)
262 self.assertEqual(len(config.submissions), 2)
264 config: SubmissionListConfig = submissions_config[2]
265 self.assertEqual(config.key, SubmissionStatus.DONE)
266 self.assertEqual(len(config.all_submissions), 1)
267 self.assertEqual(len(config.submissions), 1)
269 # Test multiple filters behaviour
270 query_params = {
271 "_filter_state": [
272 SubmissionState.REVISION_REQUESTED.value,
273 SubmissionState.ON_REVIEW.value,
274 ],
275 "_filter_journal_section": [journal_section.pk], # type:ignore
276 }
277 request = self.request_factory.get("/", data=query_params)
278 context = views_submission.prepare_submissions_lists(
279 role_handler, request, group_submissions_ftor=grouped_submissions_per_status
280 )
282 submissions_config = context["submissions_config"]
283 self.assertEqual(len(submissions_config), 3)
285 config: SubmissionListConfig = submissions_config[0]
286 self.assertEqual(config.key, SubmissionStatus.TODO)
287 self.assertEqual(len(config.all_submissions), 2)
288 self.assertEqual(len(config.submissions), 1)
290 config: SubmissionListConfig = submissions_config[1]
291 self.assertEqual(config.key, SubmissionStatus.WAITING)
292 self.assertEqual(len(config.all_submissions), 3)
293 self.assertEqual(len(config.submissions), 0)
295 config: SubmissionListConfig = submissions_config[2]
296 self.assertEqual(config.key, SubmissionStatus.DONE)
297 self.assertEqual(len(config.all_submissions), 1)
298 self.assertEqual(len(config.submissions), 1)
300 filters: FilterSet = context["filters"]
301 filter: Filter = filters.get_filter("state") # type:ignore
302 self.assertEqual(len(filter.values), 3)
303 self.assertEqual(len(filter.active_values), 2)
305 @patch.object(views_submission, "group_submissions_per_status", grouped_submissions_per_status)
306 def test_submissions_list_filtering_settings(self):
307 role_handler = RoleHandler(self.user)
308 # Test single filter
309 query_params = {"_filter_state": [SubmissionState.ON_REVIEW.value]}
310 request = self.request_factory.get("/", data=query_params)
312 # with patch.object(
313 # JournalManagerRights,
314 # "get_submission_list_config",
315 # Mock(return_value=base_submission_list_config()),
316 # ):
317 context = views_submission.prepare_submissions_lists(
318 role_handler, request, group_submissions_ftor=grouped_submissions_per_status
319 )
321 filters: FilterSet = context["filters"]
322 filter: Filter = filters.get_filter("state") # type:ignore
323 self.assertEqual(len(filter.values), 3)
325 # with patch.object(
326 # JournalManagerRights,
327 # "get_submission_list_config",
328 # Mock(return_value=base_config),
329 # ):
330 context = views_submission.prepare_submissions_lists(
331 role_handler,
332 request,
333 list_config_ftor=submission_list_config_in_filters,
334 group_submissions_ftor=grouped_submissions_per_status,
335 )
337 filters: FilterSet = context["filters"]
338 filter: Filter = filters.get_filter("state") # type:ignore
339 self.assertEqual(len(filter.values), 2)
341 submissions_config = context["submissions_config"]
343 config: SubmissionListConfig = submissions_config[0]
344 self.assertEqual(config.key, SubmissionStatus.TODO)
345 self.assertEqual(len(config.all_submissions), 2)
346 self.assertEqual(len(config.submissions), 2)
348 config: SubmissionListConfig = submissions_config[1]
349 self.assertEqual(config.key, SubmissionStatus.WAITING)
350 self.assertEqual(len(config.all_submissions), 3)
351 self.assertEqual(len(config.submissions), 2)
353 submission_count = context["submission_count"]
354 self.assertEqual(submission_count, CountWithTotal(value=3, total=4))
356 # with patch.object(
357 # JournalManagerRights,
358 # "get_submission_list_config",
359 # Mock(return_value=base_config),
360 # ):
361 context = views_submission.prepare_submissions_lists(
362 role_handler,
363 request,
364 list_config_ftor=submission_list_config_display,
365 group_submissions_ftor=grouped_submissions_per_status,
366 )
368 filters: FilterSet = context["filters"]
369 filter: Filter = filters.get_filter("state") # type:ignore
370 self.assertEqual(len(filter.values), 3)
372 submissions_config = context["submissions_config"]
374 config: SubmissionListConfig = submissions_config[0]
375 self.assertEqual(config.key, SubmissionStatus.TODO)
376 self.assertEqual(len(config.all_submissions), 2)
377 self.assertEqual(len(config.submissions), 0)
379 config: SubmissionListConfig = submissions_config[1]
380 self.assertEqual(config.key, SubmissionStatus.WAITING)
381 self.assertEqual(len(config.all_submissions), 3)
382 self.assertEqual(len(config.submissions), 2)
384 def test_review_summary(self):
385 submission = SubmissionFactory.create()
386 review_summary = build_review_summary(submission)
387 self.assertEqual(review_summary.current_version, 0)
389 version = SubmissionVersionFactory.create(submission=submission)
390 submission = Submission.objects.get(pk=submission.pk)
392 review_summary = build_review_summary(submission)
393 expected = ReviewSummary(
394 current_version=1,
395 reviewers_count=CountWithTotal(value=0, total=0),
396 reports_count=CountWithTotal(value=0, total=0),
397 )
398 self.assertEqual(expected, review_summary)
400 ReviewFactory.create(version=version)
401 submission = Submission.objects.get(pk=submission.pk)
403 review_summary = build_review_summary(submission)
404 expected = ReviewSummary(
405 current_version=1,
406 reviewers_count=CountWithTotal(value=0, total=1),
407 reports_count=CountWithTotal(value=0, total=0),
408 )
409 self.assertEqual(expected, review_summary)
411 version.submitted = True
412 version.save()
414 version_2 = SubmissionVersionFactory.create(submission=submission)
415 submission = Submission.objects.get(pk=submission.pk)
417 review_summary = build_review_summary(submission)
418 expected = ReviewSummary(
419 current_version=2,
420 reviewers_count=CountWithTotal(value=0, total=0),
421 reports_count=CountWithTotal(value=0, total=0),
422 )
423 self.assertEqual(expected, review_summary)
425 ReviewFactory.create(version=version_2, accepted=False)
426 ReviewFactory.create(version=version_2)
427 ReviewFactory.create(version=version_2, accepted=True)
428 ReviewFactory.create(version=version_2, accepted=True, submitted=True)
429 submission = Submission.objects.get(pk=submission.pk)
431 review_summary = build_review_summary(submission)
432 expected = ReviewSummary(
433 current_version=2,
434 reviewers_count=CountWithTotal(value=3, total=4),
435 reports_count=CountWithTotal(value=1, total=2),
436 )
437 self.assertEqual(expected, review_summary)