Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""Test scenario for reviews. 

2 

3## Domain 

4 

5* Users as in `conftest`, under *players* 

6* Clean slate, see `starters`. 

7* The user table 

8* The country table 

9* One contribution record 

10* One assessment record 

11* The assessment submitted and reviewers assigned. 

12* Two reviews, with review comments filled out. 

13 

14## Acts 

15 

16Filling out reviews. 

17 

18`test_reviewEntryViewAll` 

19: All users try to see the review entries, but only 

20 **expert** and **final** succeed for their own comments, and the power users 

21 succeed for all comments. 

22 Only when a review decision has been taken, the review comments become readable 

23 to the owner/editor of the contribution, the other reviewer, and the national 

24 coordinator. 

25 

26`test_decideOthers` 

27: All users except the reviewers try to make all review decisions. 

28 None of them succeeds. 

29 

30`test_reviewersDecide` 

31: **expert** tries to make all possible decisions and then revokes 

32 his last decision. 

33 After that, **final** tries the same, but fails, because 

34 **final** can only decide after **expert**. 

35 

36`test_expertDecides` 

37: **expert** tries to revoke the decision, but fails because the decision 

38 is already revoked. 

39 Then he Accepts. 

40 Then he Accepts again, but fails, because it is the same as the existing 

41 decision. 

42 

43`test_finalAccepts` 

44: **final** accepts. 

45 After that **expert** tries to take all review decisions, but fails, 

46 because the final decision has been taken. 

47 

48`test_modify` 

49: All users try to modify a field in the contribution, in the assessment, and in 

50 a review comment, but all fail, because everything is in a finished state. 

51 In particular, also a re-assignment of the reviewers to the assessment it attempted. 

52 

53`test_revokeDelay` 

54 There is a delay time during which the final decision can be revoked. 

55 We'll test what happens when the delay time is past. 

56 We do this by updating the `dateDecided` field under water, directly 

57 in Mongo. 

58 We shift the time back 23 hours 

59 **final** revokes and succeeds and then accepts again. 

60 We shift the time back 25 hours. 

61 **final** revokes and fails. 

62 We shift the time forward 25 hours again. 

63 

64`test_finalRevokes` 

65: **final** revokes his decision. 

66 After that **expert** tries to take all review decisions, and succeeds, 

67 because there is no final decision. 

68 

69`test_modify2` 

70: All users try to modify a field in the contribution, in the assessment, and in 

71 a review comment, and some succeed, because there is no finished state. 

72 

73 The assesssment is still submitted, so the contribution and assessment are still 

74 locked: nobody can modify them. 

75 

76 The reviewers can be reassigned by **office**. 

77 

78 The reviews can be modified. 

79 

80`test_finalRevise` 

81: We test revision and resubmission. The chain of events is: 

82 

83 * **expert** has to give an advisory decision first. We let hem accept 

84 the assessment; 

85 * we shift the submission date back 27 hours, 

86 so that the system does not consider the assessment resubmitted 

87 when we have shifted the review decisions back in time; 

88 * we shift the decisionDate back 26 hours, 

89 so that **expert** cannot revoke his decision right now; 

90 * **final** decides that revision is needed; 

91 * we shift the decisionData back 25 hours, 

92 so that **final** cannot revoke his decision under the current 

93 conditions; 

94 * **expert** tries to take all review decisions, but fails, 

95 because the assessment has not yet been resubmitted. 

96 

97`test_revise` 

98: Here we test the **owner**'s part in the revision: 

99 

100 * he checks the current stage of the assessment: "complete revised" 

101 * he sets the evidence of the first entry to an empty value 

102 * he checks the current stage of the assessment: "incomplete revised" 

103 * he sets the evidence of the first entry to a new empty value 

104 * he checks the current stage of the assessment: "complete revised" 

105 * he submits the assessment but fails 

106 * he resubmits the assessment but fails 

107 * he submits the assessment as revision and succeeds 

108 

109`test_newRound` 

110: Here we test the making of new review decisions. 

111 

112 * **final** tries to decide anything, but fails. 

113 * **expert** acceepts and succeeds. 

114 * **final** acceepts and succeeds. 

115""" 

116 

117import pytest 

118 

119import magic # noqa 

120from control.utils import pick as G, E 

121from conftest import USERS, POWER_USERS 

122from example import ( 

123 ACCEPT, 

124 ASSESS, 

125 COMMENTS, 

126 COMMENTS_E, 

127 COMMENTS_F, 

128 COMPLETE_REVISED, 

129 CONTRIB, 

130 CRITERIA_ENTRY, 

131 DATE_DECIDED, 

132 DATE_SUBMITTED, 

133 EVIDENCE, 

134 EVIDENCE1, 

135 EXPERT, 

136 FINAL, 

137 INCOMPLETE_REVISED, 

138 OFFICE, 

139 REJECT, 

140 REMARKS, 

141 REMARKS_E, 

142 REMARKS_F, 

143 RESUBMIT_ASSESSMENT, 

144 REVIEW, 

145 REVIEW_DECISION, 

146 REVIEW_ENTRY, 

147 REVIEWER_E, 

148 REVISE, 

149 REVOKE, 

150 SUBMIT_ASSESSMENT, 

151 SUBMIT_REVISED, 

152 TITLE, 

153 TITLE2, 

154 TITLE_A2, 

155 USER, 

156) 

157from helpers import ( 

158 findReviewEntries, 

159 forall, 

160 getItem, 

161 getReviewEntryId, 

162) 

163from starters import start 

164from subtest import ( 

165 assertFieldValue, 

166 assertModifyField, 

167 assertReviewDecisions, 

168 assertShiftDate, 

169 assertStage, 

170 assertStatus, 

171) 

172 

173startInfo = {} 

174 

175 

176@pytest.mark.usefixtures("db") 

177def test_start(clientOffice, clientOwner, clientExpert, clientFinal): 

178 startInfo.update( 

179 start( 

180 clientOffice=clientOffice, 

181 clientOwner=clientOwner, 

182 clientExpert=clientExpert, 

183 clientFinal=clientFinal, 

184 users=True, 

185 assessment=True, 

186 countries=True, 

187 review=True, 

188 ) 

189 ) 

190 

191 

192def test_reviewEntryView(clients): 

193 recordId = startInfo["recordId"] 

194 

195 cIds = recordId[CRITERIA_ENTRY] 

196 cIdFirst = cIds[0] 

197 reId = {} 

198 for user in {EXPERT, FINAL}: 

199 criteriaEntryInfo = getItem(clients[user], CRITERIA_ENTRY, cIdFirst) 

200 text = criteriaEntryInfo["text"] 

201 reviewEntries = findReviewEntries(text) 

202 reId[user] = reviewEntries[user][0] 

203 

204 def assertIt(cl, exp): 

205 user = cl.user 

206 for (kind, rId) in reId.items(): 

207 value = f"{kind}'s comment on criteria 1" 

208 expValue = ( 

209 None 

210 if exp is None 

211 else value 

212 if user in {EXPERT, FINAL} | POWER_USERS 

213 else None 

214 ) 

215 assertFieldValue((cl, REVIEW_ENTRY, rId), COMMENTS, expValue) 

216 

217 expect = {user: None for user in USERS} 

218 expect.update({user: True for user in {EXPERT, FINAL} | POWER_USERS}) 

219 forall(clients, expect, assertIt) 

220 

221 

222def test_decideOthers(clients): 

223 recordId = startInfo["recordId"] 

224 

225 reviewId = G(recordId, REVIEW) 

226 

227 def assertIt(cl, exp): 

228 user = cl.user 

229 for kind in [EXPERT, FINAL]: 

230 rId = G(reviewId, kind) 

231 expStatus = kind == user if exp else exp 

232 for decision in [REJECT, REVISE, ACCEPT, REVOKE]: 

233 decisionStr = G(G(REVIEW_DECISION, decision), kind) 

234 url = f"/api/task/{decisionStr}/{rId}" 

235 assertStatus(cl, url, expStatus) 

236 

237 expect = {user: False for user in USERS if user not in {EXPERT, FINAL}} 

238 forall(clients, expect, assertIt) 

239 

240 

241def test_reviewersDecide(clientsReviewer): 

242 recordId = startInfo["recordId"] 

243 reviewId = G(recordId, REVIEW) 

244 

245 assertReviewDecisions( 

246 clientsReviewer, 

247 reviewId, 

248 [EXPERT, FINAL], 

249 [REJECT, REVISE, ACCEPT, REVOKE], 

250 {EXPERT: True, FINAL: False}, 

251 ) 

252 

253 

254def test_expertDecides(clientsReviewer): 

255 recordId = startInfo["recordId"] 

256 reviewId = G(recordId, REVIEW) 

257 

258 assertReviewDecisions( 

259 clientsReviewer, 

260 reviewId, 

261 [EXPERT], 

262 [REVOKE], 

263 False, 

264 ) 

265 assertReviewDecisions( 

266 clientsReviewer, 

267 reviewId, 

268 [EXPERT], 

269 [ACCEPT], 

270 True, 

271 ) 

272 assertReviewDecisions( 

273 clientsReviewer, 

274 reviewId, 

275 [EXPERT], 

276 [ACCEPT], 

277 False, 

278 ) 

279 

280 

281def test_finalAccepts(clientsReviewer): 

282 recordId = startInfo["recordId"] 

283 reviewId = G(recordId, REVIEW) 

284 

285 assertReviewDecisions( 

286 clientsReviewer, 

287 reviewId, 

288 [FINAL], 

289 [ACCEPT], 

290 True, 

291 ) 

292 assertReviewDecisions( 

293 clientsReviewer, 

294 reviewId, 

295 [EXPERT], 

296 [REJECT, REVISE, ACCEPT, REVOKE], 

297 False, 

298 ) 

299 

300 

301def test_modify(clients): 

302 valueTables = startInfo["valueTables"] 

303 recordId = startInfo["recordId"] 

304 

305 users = valueTables[USER] 

306 eid = recordId[CONTRIB] 

307 aId = recordId[ASSESS] 

308 reviewId = recordId[REVIEW] 

309 rExpertId = reviewId[EXPERT] 

310 rFinalId = reviewId[FINAL] 

311 cIdFirst = recordId[CRITERIA_ENTRY][0] 

312 renId = getReviewEntryId(clients, cIdFirst, rExpertId, rFinalId) 

313 

314 def assertIt(cl, exp): 

315 assertModifyField(cl, CONTRIB, eid, TITLE, TITLE2, exp) 

316 assertModifyField(cl, ASSESS, aId, TITLE, TITLE_A2, exp) 

317 reviewerFId = G(users, FINAL) 

318 assertModifyField(cl, ASSESS, aId, REVIEWER_E, (reviewerFId, FINAL), exp) 

319 assertModifyField( 

320 cl, CRITERIA_ENTRY, cIdFirst, EVIDENCE, ([EVIDENCE1], EVIDENCE1), exp 

321 ) 

322 for (rId, remarks) in ((rExpertId, REMARKS_E), (rFinalId, REMARKS_F)): 

323 assertModifyField(cl, REVIEW, rId, REMARKS, ([remarks], remarks), exp) 

324 for (u, reid) in renId.items(): 

325 comments = COMMENTS_E if u == EXPERT else COMMENTS_F 

326 assertModifyField( 

327 cl, REVIEW_ENTRY, reid, COMMENTS, ([comments], comments), exp 

328 ) 

329 

330 expect = {user: False for user in USERS} 

331 forall(clients, expect, assertIt) 

332 

333 

334def test_revokeDelay(clientFinal, clientSystem): 

335 recordId = startInfo["recordId"] 

336 reviewId = G(recordId, REVIEW) 

337 

338 cFinal = {FINAL: clientFinal} 

339 rFinal = G(reviewId, FINAL) 

340 assertShiftDate(clientSystem, REVIEW, rFinal, DATE_DECIDED, -23) 

341 assertReviewDecisions( 

342 cFinal, 

343 reviewId, 

344 [FINAL], 

345 [REVOKE, ACCEPT], 

346 True, 

347 ) 

348 assertShiftDate(clientSystem, REVIEW, rFinal, DATE_DECIDED, -25) 

349 assertReviewDecisions( 

350 cFinal, 

351 reviewId, 

352 [FINAL], 

353 [REVOKE], 

354 False, 

355 ) 

356 assertShiftDate(clientSystem, REVIEW, rFinal, DATE_DECIDED, 25) 

357 

358 

359def test_finalRevokes(clientsReviewer): 

360 recordId = startInfo["recordId"] 

361 reviewId = G(recordId, REVIEW) 

362 

363 assertReviewDecisions( 

364 clientsReviewer, 

365 reviewId, 

366 [FINAL], 

367 [REVOKE], 

368 True, 

369 ) 

370 assertReviewDecisions( 

371 clientsReviewer, 

372 reviewId, 

373 [EXPERT], 

374 [REJECT, REVISE, ACCEPT, REVOKE], 

375 True, 

376 ) 

377 

378 

379def test_modify2(clients): 

380 valueTables = startInfo["valueTables"] 

381 recordId = startInfo["recordId"] 

382 

383 users = valueTables[USER] 

384 eid = recordId[CONTRIB] 

385 aId = recordId[ASSESS] 

386 reviewId = recordId[REVIEW] 

387 rExpertId = reviewId[EXPERT] 

388 rFinalId = reviewId[FINAL] 

389 cIdFirst = recordId[CRITERIA_ENTRY][0] 

390 renId = getReviewEntryId(clients, cIdFirst, rExpertId, rFinalId) 

391 

392 def assertIt(cl, exp): 

393 assertModifyField(cl, CONTRIB, eid, TITLE, TITLE2, exp[CONTRIB]) 

394 assertModifyField(cl, ASSESS, aId, TITLE, TITLE_A2, exp[ASSESS]) 

395 reviewerFId = G(users, FINAL) 

396 reviewerEId = G(users, EXPERT) 

397 assertModifyField( 

398 cl, ASSESS, aId, REVIEWER_E, (reviewerFId, FINAL), exp["assign"] 

399 ) 

400 assertModifyField( 

401 cl, ASSESS, aId, REVIEWER_E, (reviewerEId, EXPERT), exp["assign"] 

402 ) 

403 assertModifyField( 

404 cl, 

405 CRITERIA_ENTRY, 

406 cIdFirst, 

407 EVIDENCE, 

408 ([EVIDENCE1], EVIDENCE1), 

409 exp[CRITERIA_ENTRY], 

410 ) 

411 for (rId, remarks, kind) in ( 

412 (rExpertId, REMARKS_E, EXPERT), 

413 (rFinalId, REMARKS_F, FINAL), 

414 ): 

415 assertModifyField( 

416 cl, REVIEW, rId, REMARKS, ([remarks], remarks), exp[f"{REVIEW}_{kind}"] 

417 ) 

418 for (kind, reid) in renId.items(): 

419 comments = COMMENTS_E if kind == EXPERT else COMMENTS_F 

420 assertModifyField( 

421 cl, 

422 REVIEW_ENTRY, 

423 reid, 

424 COMMENTS, 

425 ([comments], comments), 

426 exp[f"{REVIEW_ENTRY}_{kind}"], 

427 ) 

428 

429 expectDefault = {user: False for user in USERS} 

430 expectPerKind = { 

431 CONTRIB: dict(expectDefault), 

432 ASSESS: dict(expectDefault), 

433 CRITERIA_ENTRY: dict(expectDefault), 

434 "assign": dict(expectDefault), 

435 f"{REVIEW}_{EXPERT}": dict(expectDefault), 

436 f"{REVIEW}_{FINAL}": dict(expectDefault), 

437 f"{REVIEW_ENTRY}_{EXPERT}": dict(expectDefault), 

438 f"{REVIEW_ENTRY}_{FINAL}": dict(expectDefault), 

439 } 

440 expectPerKind["assign"].update({user: True for user in {OFFICE}}) 

441 expectPerKind[f"{REVIEW}_{EXPERT}"].update( 

442 {user: True for user in {EXPERT} | POWER_USERS} 

443 ) 

444 expectPerKind[f"{REVIEW}_{FINAL}"].update( 

445 {user: True for user in {FINAL} | POWER_USERS} 

446 ) 

447 expectPerKind[f"{REVIEW_ENTRY}_{EXPERT}"].update( 

448 {user: True for user in {EXPERT} | POWER_USERS} 

449 ) 

450 expectPerKind[f"{REVIEW_ENTRY}_{FINAL}"].update( 

451 {user: True for user in {FINAL} | POWER_USERS} 

452 ) 

453 expect = {} 

454 for (kind, expectKind) in expectPerKind.items(): 

455 for (user, exp) in expectKind.items(): 

456 expect.setdefault(user, {})[kind] = exp 

457 

458 forall(clients, expect, assertIt) 

459 

460 

461def test_finalRevise(clientsReviewer, clientSystem): 

462 recordId = startInfo["recordId"] 

463 aId = G(recordId, ASSESS) 

464 reviewId = G(recordId, REVIEW) 

465 rExpert = G(reviewId, EXPERT) 

466 rFinal = G(reviewId, FINAL) 

467 

468 assertReviewDecisions(clientsReviewer, reviewId, [EXPERT], [ACCEPT], True) 

469 assertShiftDate(clientSystem, ASSESS, aId, DATE_SUBMITTED, -27) 

470 assertShiftDate(clientSystem, REVIEW, rExpert, DATE_DECIDED, -26) 

471 assertReviewDecisions(clientsReviewer, reviewId, [FINAL], [REVISE], True) 

472 assertShiftDate(clientSystem, REVIEW, rFinal, DATE_DECIDED, -25) 

473 assertReviewDecisions( 

474 clientsReviewer, 

475 reviewId, 

476 [EXPERT], 

477 [REJECT, REVISE, ACCEPT, REVOKE], 

478 False, 

479 ) 

480 

481 

482def test_Revise(clientOwner): 

483 recordId = startInfo["recordId"] 

484 aId = G(recordId, ASSESS) 

485 cIds = recordId[CRITERIA_ENTRY] 

486 cIdFirst = cIds[0] 

487 

488 assertStage(clientOwner, ASSESS, aId, COMPLETE_REVISED) 

489 assertModifyField( 

490 clientOwner, 

491 CRITERIA_ENTRY, 

492 cIdFirst, 

493 EVIDENCE, 

494 ([], E), 

495 True, 

496 ) 

497 assertStage(clientOwner, ASSESS, aId, INCOMPLETE_REVISED) 

498 theEvidence = ["revised evidence for 1", "see the internet"] 

499 theEvidenceRep = ",".join(theEvidence) 

500 assertModifyField( 

501 clientOwner, 

502 CRITERIA_ENTRY, 

503 cIdFirst, 

504 EVIDENCE, 

505 (theEvidence, theEvidenceRep), 

506 True, 

507 ) 

508 assertStage(clientOwner, ASSESS, aId, COMPLETE_REVISED) 

509 assertStatus(clientOwner, f"/api/task/{SUBMIT_ASSESSMENT}/{aId}", False) 

510 assertStatus(clientOwner, f"/api/task/{RESUBMIT_ASSESSMENT}/{aId}", False) 

511 assertStatus(clientOwner, f"/api/task/{SUBMIT_REVISED}/{aId}", True) 

512 

513 

514def test_newRound(clientsReviewer): 

515 recordId = startInfo["recordId"] 

516 reviewId = G(recordId, REVIEW) 

517 

518 assertReviewDecisions( 

519 clientsReviewer, reviewId, [FINAL], [REJECT, ACCEPT, REVISE, REVOKE], False 

520 ) 

521 assertReviewDecisions(clientsReviewer, reviewId, [EXPERT], [ACCEPT], True) 

522 assertReviewDecisions(clientsReviewer, reviewId, [FINAL], [ACCEPT], True)