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

1from __future__ import annotations 

2 

3from unittest.mock import patch 

4 

5from mesh.model.filters import Filter, FilterSet 

6from mesh.model.roles.role_handler import RoleHandler 

7 

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 

23 

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 

32 

33 

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) 

55 

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) 

63 

64 

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 } 

76 

77 

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 ] 

97 

98 

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 ] 

118 

119 

120class SubmissionViewsTestCase(BaseTestCase): 

121 class_used_models = [Submission, JournalSection, User] 

122 

123 @classmethod 

124 def setUpClass(cls) -> None: 

125 super().setUpClass() 

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

127 create_global_submissions() 

128 

129 def test_group_submissions_per_status(self): 

130 submissions = Submission.objects.get_submissions().all() 

131 role_handler = RoleHandler(self.user) 

132 

133 grouped_submissions = views_submission.group_submissions_per_status( 

134 submissions, role_handler 

135 ) 

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

137 

138 group = grouped_submissions[SubmissionStatus.TODO] 

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

140 

141 group = grouped_submissions[SubmissionStatus.WAITING] 

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

143 

144 group = grouped_submissions[SubmissionStatus.DONE] 

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

146 

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("/") 

156 

157 context = views_submission.prepare_submissions_lists( 

158 role_handler, request, group_submissions_ftor=grouped_submissions_per_status 

159 ) 

160 

161 submissions_config = context["submissions_config"] 

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

163 

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) 

168 

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) 

173 

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) 

178 

179 submission_count = context["submission_count"] 

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

181 

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 ) 

196 

197 submissions_config = context["submissions_config"] 

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

199 

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) 

204 

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) 

209 

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) 

214 

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 ) 

220 

221 submissions_config = context["submissions_config"] 

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

223 

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) 

228 

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) 

233 

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) 

238 

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 ) 

250 

251 submissions_config = context["submissions_config"] 

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

253 

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) 

258 

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) 

263 

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) 

268 

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 ) 

281 

282 submissions_config = context["submissions_config"] 

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

284 

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) 

289 

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) 

294 

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) 

299 

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) 

304 

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) 

311 

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 ) 

320 

321 filters: FilterSet = context["filters"] 

322 filter: Filter = filters.get_filter("state") # type:ignore 

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

324 

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 ) 

336 

337 filters: FilterSet = context["filters"] 

338 filter: Filter = filters.get_filter("state") # type:ignore 

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

340 

341 submissions_config = context["submissions_config"] 

342 

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) 

347 

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) 

352 

353 submission_count = context["submission_count"] 

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

355 

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 ) 

367 

368 filters: FilterSet = context["filters"] 

369 filter: Filter = filters.get_filter("state") # type:ignore 

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

371 

372 submissions_config = context["submissions_config"] 

373 

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) 

378 

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) 

383 

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) 

388 

389 version = SubmissionVersionFactory.create(submission=submission) 

390 submission = Submission.objects.get(pk=submission.pk) 

391 

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) 

399 

400 ReviewFactory.create(version=version) 

401 submission = Submission.objects.get(pk=submission.pk) 

402 

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) 

410 

411 version.submitted = True 

412 version.save() 

413 

414 version_2 = SubmissionVersionFactory.create(submission=submission) 

415 submission = Submission.objects.get(pk=submission.pk) 

416 

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) 

424 

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) 

430 

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)