Coverage for cc_modules/tests/cc_taskschedule_tests.py: 17%

172 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-08 23:14 +0000

1#!/usr/bin/env python 

2 

3""" 

4camcops_server/cc_modules/tests/cc_taskschedule_tests.py 

5 

6=============================================================================== 

7 

8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry. 

9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk). 

10 

11 This file is part of CamCOPS. 

12 

13 CamCOPS is free software: you can redistribute it and/or modify 

14 it under the terms of the GNU General Public License as published by 

15 the Free Software Foundation, either version 3 of the License, or 

16 (at your option) any later version. 

17 

18 CamCOPS is distributed in the hope that it will be useful, 

19 but WITHOUT ANY WARRANTY; without even the implied warranty of 

20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

21 GNU General Public License for more details. 

22 

23 You should have received a copy of the GNU General Public License 

24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>. 

25 

26=============================================================================== 

27 

28""" 

29 

30from urllib.parse import parse_qs, urlsplit 

31 

32from cardinal_pythonlib.uriconst import UriSchemes 

33from pendulum import Duration 

34 

35from camcops_server.cc_modules.cc_email import Email 

36from camcops_server.cc_modules.cc_pyramid import Routes 

37from camcops_server.cc_modules.cc_taskschedule import ( 

38 PatientTaskSchedule, 

39 PatientTaskScheduleEmail, 

40 TaskSchedule, 

41 TaskScheduleItem, 

42) 

43from camcops_server.cc_modules.cc_unittest import ( 

44 DemoDatabaseTestCase, 

45 DemoRequestTestCase, 

46) 

47 

48 

49# ============================================================================= 

50# Unit tests 

51# ============================================================================= 

52 

53 

54class TaskScheduleTests(DemoDatabaseTestCase): 

55 def test_deleting_deletes_related_objects(self) -> None: 

56 schedule = TaskSchedule() 

57 schedule.group_id = self.group.id 

58 self.dbsession.add(schedule) 

59 self.dbsession.flush() 

60 

61 item = TaskScheduleItem() 

62 item.schedule_id = schedule.id 

63 item.task_table_name = "ace3" 

64 item.due_from = Duration(days=30) 

65 item.due_by = Duration(days=60) 

66 self.dbsession.add(item) 

67 self.dbsession.flush() 

68 

69 patient = self.create_patient() 

70 

71 pts = PatientTaskSchedule() 

72 pts.schedule_id = schedule.id 

73 pts.patient_pk = patient.pk 

74 self.dbsession.add(pts) 

75 self.dbsession.flush() 

76 

77 email = Email() 

78 self.dbsession.add(email) 

79 self.dbsession.flush() 

80 

81 pts_email = PatientTaskScheduleEmail() 

82 pts_email.email_id = email.id 

83 pts_email.patient_task_schedule_id = pts.id 

84 self.dbsession.add(pts_email) 

85 self.dbsession.commit() 

86 

87 self.assertIsNotNone( 

88 self.dbsession.query(TaskScheduleItem) 

89 .filter(TaskScheduleItem.id == item.id) 

90 .one_or_none() 

91 ) 

92 self.assertIsNotNone( 

93 self.dbsession.query(PatientTaskSchedule) 

94 .filter(PatientTaskSchedule.id == pts.id) 

95 .one_or_none() 

96 ) 

97 self.assertIsNotNone( 

98 self.dbsession.query(PatientTaskScheduleEmail) 

99 .filter( 

100 PatientTaskScheduleEmail.patient_task_schedule_id == pts.id 

101 ) 

102 .one_or_none() 

103 ) 

104 self.assertIsNotNone( 

105 self.dbsession.query(Email) 

106 .filter(Email.id == email.id) 

107 .one_or_none() 

108 ) 

109 

110 self.dbsession.delete(schedule) 

111 self.dbsession.commit() 

112 

113 self.assertIsNone( 

114 self.dbsession.query(TaskScheduleItem) 

115 .filter(TaskScheduleItem.id == item.id) 

116 .one_or_none() 

117 ) 

118 self.assertIsNone( 

119 self.dbsession.query(PatientTaskSchedule) 

120 .filter(PatientTaskSchedule.id == pts.id) 

121 .one_or_none() 

122 ) 

123 self.assertIsNone( 

124 self.dbsession.query(PatientTaskScheduleEmail) 

125 .filter( 

126 PatientTaskScheduleEmail.patient_task_schedule_id == pts.id 

127 ) 

128 .one_or_none() 

129 ) 

130 self.assertIsNone( 

131 self.dbsession.query(Email) 

132 .filter(Email.id == email.id) 

133 .one_or_none() 

134 ) 

135 

136 

137class TaskScheduleItemTests(DemoRequestTestCase): 

138 def test_description_shows_shortname_and_number_of_days(self) -> None: 

139 item = TaskScheduleItem() 

140 item.task_table_name = "bmi" 

141 item.due_from = Duration(days=30) 

142 

143 self.assertEqual(item.description(self.req), "BMI @ 30 days") 

144 

145 def test_description_with_no_durations(self) -> None: 

146 item = TaskScheduleItem() 

147 item.task_table_name = "bmi" 

148 

149 self.assertEqual(item.description(self.req), "BMI @ ? days") 

150 

151 def test_due_within_calculated_from_due_by_and_due_from(self) -> None: 

152 item = TaskScheduleItem() 

153 item.due_from = Duration(days=30) 

154 item.due_by = Duration(days=50) 

155 

156 self.assertEqual(item.due_within.in_days(), 20) 

157 

158 def test_due_within_is_none_when_missing_due_by(self) -> None: 

159 item = TaskScheduleItem() 

160 item.due_from = Duration(days=30) 

161 

162 self.assertIsNone(item.due_within) 

163 

164 def test_due_within_calculated_when_missing_due_from(self) -> None: 

165 item = TaskScheduleItem() 

166 item.due_by = Duration(days=30) 

167 

168 self.assertEqual(item.due_within.in_days(), 30) 

169 

170 

171class PatientTaskScheduleTests(DemoDatabaseTestCase): 

172 def setUp(self) -> None: 

173 super().setUp() 

174 

175 import datetime 

176 

177 self.schedule = TaskSchedule() 

178 self.schedule.group_id = self.group.id 

179 self.dbsession.add(self.schedule) 

180 

181 self.patient = self.create_patient( 

182 id=1, 

183 forename="Jo", 

184 surname="Patient", 

185 dob=datetime.date(1958, 4, 19), 

186 sex="F", 

187 address="Address", 

188 gp="GP", 

189 other="Other", 

190 ) 

191 

192 self.pts = PatientTaskSchedule() 

193 self.pts.schedule_id = self.schedule.id 

194 self.pts.patient_pk = self.patient.pk 

195 self.dbsession.add(self.pts) 

196 self.dbsession.flush() 

197 

198 def test_email_body_contains_access_key(self) -> None: 

199 self.schedule.email_template = "{access_key}" 

200 self.dbsession.add(self.schedule) 

201 self.dbsession.flush() 

202 

203 self.assertIn( 

204 f"{self.patient.uuid_as_proquint}", self.pts.email_body(self.req) 

205 ) 

206 

207 def test_email_body_contains_server_url(self) -> None: 

208 self.schedule.email_template = "{server_url}" 

209 self.dbsession.add(self.schedule) 

210 self.dbsession.flush() 

211 

212 expected_url = self.req.route_url(Routes.CLIENT_API) 

213 

214 self.assertIn(f"{expected_url}", self.pts.email_body(self.req)) 

215 

216 def test_email_body_contains_patient_forename(self) -> None: 

217 self.schedule.email_template = "{forename}" 

218 self.dbsession.add(self.schedule) 

219 self.dbsession.flush() 

220 

221 self.assertIn( 

222 f"{self.pts.patient.forename}", self.pts.email_body(self.req) 

223 ) 

224 

225 def test_email_body_contains_patient_surname(self) -> None: 

226 self.schedule.email_template = "{surname}" 

227 self.dbsession.add(self.schedule) 

228 self.dbsession.flush() 

229 

230 self.assertIn( 

231 f"{self.pts.patient.surname}", self.pts.email_body(self.req) 

232 ) 

233 

234 def test_email_body_contains_android_launch_url(self) -> None: 

235 self.schedule.email_template = "{android_launch_url}" 

236 self.dbsession.add(self.schedule) 

237 self.dbsession.flush() 

238 

239 url = self.pts.email_body(self.req) 

240 (scheme, netloc, path, query, fragment) = urlsplit(url) 

241 self.assertEqual(scheme, UriSchemes.HTTP) 

242 self.assertEqual(netloc, "camcops.org") 

243 self.assertEqual(path, "/register/") 

244 query_dict = parse_qs(query) 

245 self.assertEqual(query_dict["default_single_user_mode"], ["true"]) 

246 self.assertEqual( 

247 query_dict["default_server_location"], 

248 [self.req.route_url(Routes.CLIENT_API)], 

249 ) 

250 self.assertEqual( 

251 query_dict["default_access_key"], [self.patient.uuid_as_proquint] 

252 ) 

253 

254 def test_email_body_contains_ios_launch_url(self) -> None: 

255 self.schedule.email_template = "{ios_launch_url}" 

256 self.dbsession.add(self.schedule) 

257 self.dbsession.flush() 

258 

259 url = self.pts.email_body(self.req) 

260 (scheme, netloc, path, query, fragment) = urlsplit(url) 

261 self.assertEqual(scheme, "camcops") 

262 self.assertEqual(netloc, "camcops.org") 

263 self.assertEqual(path, "/register/") 

264 query_dict = parse_qs(query) 

265 self.assertEqual(query_dict["default_single_user_mode"], ["true"]) 

266 self.assertEqual( 

267 query_dict["default_server_location"], 

268 [self.req.route_url(Routes.CLIENT_API)], 

269 ) 

270 self.assertEqual( 

271 query_dict["default_access_key"], [self.patient.uuid_as_proquint] 

272 ) 

273 

274 def test_email_body_disallows_invalid_template(self) -> None: 

275 self.schedule.email_template = "{foobar}" 

276 self.dbsession.add(self.schedule) 

277 self.dbsession.flush() 

278 

279 with self.assertRaises(KeyError): 

280 self.pts.email_body(self.req) 

281 

282 def test_email_body_disallows_accessing_properties(self) -> None: 

283 self.schedule.email_template = "{server_url.__class__}" 

284 self.dbsession.add(self.schedule) 

285 self.dbsession.flush() 

286 

287 with self.assertRaises(KeyError): 

288 self.pts.email_body(self.req) 

289 

290 def test_email_sent_false_for_no_emails(self) -> None: 

291 self.assertFalse(self.pts.email_sent) 

292 

293 def test_email_sent_false_for_one_unsent_email(self) -> None: 

294 email1 = Email() 

295 email1.sent = False 

296 self.dbsession.add(email1) 

297 self.dbsession.flush() 

298 pts_email1 = PatientTaskScheduleEmail() 

299 pts_email1.email_id = email1.id 

300 pts_email1.patient_task_schedule_id = self.pts.id 

301 self.dbsession.add(pts_email1) 

302 self.dbsession.commit() 

303 

304 self.assertFalse(self.pts.email_sent) 

305 

306 def test_email_sent_true_for_one_sent_email(self) -> None: 

307 email1 = Email() 

308 email1.sent = False 

309 self.dbsession.add(email1) 

310 self.dbsession.flush() 

311 pts_email1 = PatientTaskScheduleEmail() 

312 pts_email1.email_id = email1.id 

313 pts_email1.patient_task_schedule_id = self.pts.id 

314 self.dbsession.add(pts_email1) 

315 

316 email2 = Email() 

317 email2.sent = True 

318 self.dbsession.add(email2) 

319 self.dbsession.flush() 

320 pts_email2 = PatientTaskScheduleEmail() 

321 pts_email2.email_id = email2.id 

322 pts_email2.patient_task_schedule_id = self.pts.id 

323 self.dbsession.add(pts_email2) 

324 self.dbsession.commit() 

325 

326 self.assertTrue(self.pts.email_sent)