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

1from __future__ import annotations 

2 

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 

26 

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 

35 

36 

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) 

58 

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) 

66 

67 

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) 

76 

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 } 

88 

89 return grouped_submissions_per_status 

90 

91 

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 ] 

111 

112 

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 ] 

132 

133 

134class SubmissionViewsTestCase(BaseTestCase): 

135 class_used_models = [Submission, JournalSection, User] 

136 

137 @classmethod 

138 def setUpClass(cls) -> None: 

139 super().setUpClass() 

140 cls.user = UserFactory.create(journal_manager=True) 

141 create_global_submissions() 

142 

143 def test_group_submissions_per_status(self): 

144 role = JournalManager(self.user) 

145 

146 submissions = role.get_submissions() 

147 

148 grouped_submissions = views_submission.group_submissions_per_status(submissions, role) 

149 self.assertEqual(len(grouped_submissions), 3) 

150 

151 group = grouped_submissions[SubmissionStatus.TODO] 

152 self.assertEqual(len(group), 5) 

153 

154 group = grouped_submissions[SubmissionStatus.WAITING] 

155 self.assertEqual(len(group), 1) 

156 

157 group = grouped_submissions[SubmissionStatus.DONE] 

158 self.assertEqual(len(group), 1) 

159 

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) 

167 

168 grouped_submissions_per_status = generate_grouped_function(role) 

169 

170 request = self.dummy_request("/") 

171 

172 context = views_submission.prepare_submissions_lists( 

173 role, request, group_submissions_ftor=grouped_submissions_per_status 

174 ) 

175 

176 submissions_config = context["submissions_config"] 

177 self.assertEqual(len(submissions_config), 3) 

178 

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) 

183 

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) 

188 

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) 

193 

194 submission_count = context["submission_count"] 

195 self.assertEqual(submission_count, CountWithTotal(value=6, total=6)) 

196 

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) 

207 

208 grouped_submissions_per_status = generate_grouped_function(role) 

209 

210 context = views_submission.prepare_submissions_lists( 

211 role, request, group_submissions_ftor=grouped_submissions_per_status 

212 ) 

213 

214 submissions_config = context["submissions_config"] 

215 self.assertEqual(len(submissions_config), 3) 

216 

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) 

221 

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) 

226 

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) 

231 

232 query_params = {"_filter_state": [SubmissionState.REVISION_REQUESTED.value]} 

233 request = self.request_factory.get("/", data=query_params) 

234 

235 context = views_submission.prepare_submissions_lists( 

236 role, request, group_submissions_ftor=grouped_submissions_per_status 

237 ) 

238 

239 submissions_config = context["submissions_config"] 

240 self.assertEqual(len(submissions_config), 3) 

241 

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) 

246 

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) 

251 

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) 

256 

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) 

265 

266 context = views_submission.prepare_submissions_lists( 

267 role, request, group_submissions_ftor=grouped_submissions_per_status 

268 ) 

269 

270 submissions_config = context["submissions_config"] 

271 self.assertEqual(len(submissions_config), 3) 

272 

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) 

277 

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) 

282 

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) 

287 

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) 

297 

298 context = views_submission.prepare_submissions_lists( 

299 role, request, group_submissions_ftor=grouped_submissions_per_status 

300 ) 

301 

302 submissions_config = context["submissions_config"] 

303 self.assertEqual(len(submissions_config), 3) 

304 

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) 

309 

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) 

314 

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) 

319 

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) 

324 

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) 

330 

331 grouped_submissions_per_status = generate_grouped_function(role) 

332 

333 # with patch.object( 

334 # JournalManagerRights, 

335 # "get_submission_list_config", 

336 # Mock(return_value=base_submission_list_config()), 

337 # ): 

338 

339 context = views_submission.prepare_submissions_lists( 

340 role, request, group_submissions_ftor=grouped_submissions_per_status 

341 ) 

342 

343 filters = context["filters"] 

344 filter = filters.get_filter("state") 

345 self.assertEqual(len(filter.values), 3) 

346 

347 # with patch.object( 

348 # JournalManagerRights, 

349 # "get_submission_list_config", 

350 # Mock(return_value=base_config), 

351 # ): 

352 

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 ) 

359 

360 filters = context["filters"] 

361 filter = filters.get_filter("state") 

362 self.assertEqual(len(filter.values), 2) 

363 

364 submissions_config = context["submissions_config"] 

365 

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) 

370 

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) 

375 

376 submission_count = context["submission_count"] 

377 self.assertEqual(submission_count, CountWithTotal(value=3, total=4)) 

378 

379 # with patch.object( 

380 # JournalManagerRights, 

381 # "get_submission_list_config", 

382 # Mock(return_value=base_config), 

383 # ): 

384 

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 ) 

391 

392 filters: FilterSet = context["filters"] 

393 filter = filters.get_filter("state") 

394 self.assertEqual(len(filter.values), 3) 

395 

396 submissions_config = context["submissions_config"] 

397 

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) 

402 

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) 

407 

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) 

412 

413 submission = role.get_submissions().get(pk=submission.pk) 

414 

415 review_summary = build_review_summary(submission) 

416 self.assertEqual(review_summary.current_version, 0) 

417 

418 version = SubmissionVersionFactory.create(submission=submission, submitted=False) 

419 

420 submission = role.get_submissions().get(pk=submission.pk) 

421 

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) 

430 

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) 

441 

442 ReviewFactory.create(version=version) 

443 

444 submission = role.get_submissions().get(pk=submission.pk) 

445 

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) 

453 

454 version_2 = SubmissionVersionFactory.create(submission=submission) 

455 

456 # Version is not yet submitted : Editor should not be allowed to view it 

457 submission = role.get_submissions().get(pk=submission.pk) 

458 

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) 

466 

467 version_2.submitted = True 

468 version_2.save() 

469 

470 submission = role.get_submissions().get(pk=submission.pk) 

471 

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) 

479 

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) 

484 

485 submission = role.get_submissions().get(pk=submission.pk) 

486 

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)