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

1"""

2 camcops_server/cc_modules/tests/cc_taskschedule_tests.py

3

4===============================================================================

5

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

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

8

9 This file is part of CamCOPS.

10

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

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

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

14 (at your option) any later version.

15

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

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

18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

19 GNU General Public License for more details.

20

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

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

23

24===============================================================================

25

26"""

27

28 from urllib.parse import parse_qs, urlsplit

29

30 from cardinal_pythonlib.uriconst import UriSchemes

31 from pendulum import Duration

32

33 from camcops_server.cc_modules.cc_email import Email

34 from camcops_server.cc_modules.cc_pyramid import Routes

35 from camcops_server.cc_modules.cc_taskschedule import (

36 PatientTaskSchedule,

37 PatientTaskScheduleEmail,

38 TaskScheduleItem,

39)

40 from camcops_server.cc_modules.cc_testfactories import (

41 EmailFactory,

42 PatientTaskScheduleEmailFactory,

43 PatientTaskScheduleFactory,

44 ServerCreatedPatientFactory,

45 TaskScheduleFactory,

46 TaskScheduleItemFactory,

47)

48 from camcops_server.cc_modules.cc_unittest import DemoRequestTestCase

49

50

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

52# Unit tests

53# =============================================================================

54

55

56 class TaskScheduleTests(DemoRequestTestCase):

57 def test_deleting_deletes_related_objects(self) -> None:

58 patient = ServerCreatedPatientFactory()

59 schedule = TaskScheduleFactory(group=patient._group)

60

61 item = TaskScheduleItemFactory(

62 task_schedule=schedule,

63 task_table_name="ace3",

64 )

65

66 pts = PatientTaskScheduleFactory(

67 task_schedule=schedule,

68 patient=patient,

69 )

70

71 pts_email = PatientTaskScheduleEmailFactory(

72 patient_task_schedule=pts,

73 )

74

75 self.assertIsNotNone(

76 self.dbsession.query(TaskScheduleItem)

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

78 .one_or_none()

79 )

80 self.assertIsNotNone(

81 self.dbsession.query(PatientTaskSchedule)

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

83 .one_or_none()

84 )

85 self.assertIsNotNone(

86 self.dbsession.query(PatientTaskScheduleEmail)

87 .filter(

88 PatientTaskScheduleEmail.patient_task_schedule_id == pts.id

89 )

90 .one_or_none()

91 )

92 self.assertIsNotNone(

93 self.dbsession.query(Email)

94 .filter(Email.id == pts_email.email.id)

95 .one_or_none()

96 )

97

98 self.dbsession.delete(schedule)

99 self.dbsession.commit()

100

101 self.assertIsNone(

102 self.dbsession.query(TaskScheduleItem)

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

104 .one_or_none()

105 )

106 self.assertIsNone(

107 self.dbsession.query(PatientTaskSchedule)

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

109 .one_or_none()

110 )

111 self.assertIsNone(

112 self.dbsession.query(PatientTaskScheduleEmail)

113 .filter(

114 PatientTaskScheduleEmail.patient_task_schedule_id == pts.id

115 )

116 .one_or_none()

117 )

118 self.assertIsNone(

119 self.dbsession.query(Email)

120 .filter(Email.id == pts_email.email.id)

121 .one_or_none()

122 )

123

124

125 class TaskScheduleItemTests(DemoRequestTestCase):

126 def test_description_shows_shortname_and_number_of_days(self) -> None:

127 item = TaskScheduleItemFactory(

128 task_table_name="bmi",

129 due_from=Duration(days=30),

130 )

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

132

133 def test_description_with_no_durations(self) -> None:

134 item = TaskScheduleItemFactory(task_table_name="bmi")

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

136

137 def test_due_within_calculated_from_due_by_and_due_from(self) -> None:

138 item = TaskScheduleItemFactory(

139 due_from=Duration(days=30),

140 due_by=Duration(days=50),

141 )

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

143

144 def test_due_within_is_none_when_missing_due_by(self) -> None:

145 item = TaskScheduleItemFactory(due_from=Duration(days=30))

146 self.assertIsNone(item.due_within)

147

148 def test_due_within_calculated_when_missing_due_from(self) -> None:

149 item = TaskScheduleItemFactory(due_by=Duration(days=30))

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

151

152

153 class PatientTaskScheduleTests(DemoRequestTestCase):

154 def test_email_body_contains_access_key(self) -> None:

155 schedule = TaskScheduleFactory(email_template="{access_key}")

156 pts = PatientTaskScheduleFactory(task_schedule=schedule)

157

158 self.assertIn(

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

160 )

161

162 def test_email_body_contains_server_url(self) -> None:

163 schedule = TaskScheduleFactory(email_template="{server_url}")

164 pts = PatientTaskScheduleFactory(task_schedule=schedule)

165

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

167

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

169

170 def test_email_body_contains_patient_forename(self) -> None:

171 schedule = TaskScheduleFactory(email_template="{forename}")

172 pts = PatientTaskScheduleFactory(task_schedule=schedule)

173

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

175

176 def test_email_body_contains_patient_surname(self) -> None:

177 schedule = TaskScheduleFactory(email_template="{surname}")

178 pts = PatientTaskScheduleFactory(task_schedule=schedule)

179

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

181

182 def test_email_body_contains_android_launch_url(self) -> None:

183 schedule = TaskScheduleFactory(email_template="{android_launch_url}")

184 pts = PatientTaskScheduleFactory(task_schedule=schedule)

185

186 url = pts.email_body(self.req)

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

188 self.assertEqual(scheme, UriSchemes.HTTP)

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

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

191 query_dict = parse_qs(query)

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

193 self.assertEqual(

194 query_dict["default_server_location"],

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

196 )

197 self.assertEqual(

198 query_dict["default_access_key"], [pts.patient.uuid_as_proquint]

199 )

200

201 def test_email_body_contains_ios_launch_url(self) -> None:

202 schedule = TaskScheduleFactory(email_template="{ios_launch_url}")

203 pts = PatientTaskScheduleFactory(task_schedule=schedule)

204

205 url = pts.email_body(self.req)

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

207 self.assertEqual(scheme, "camcops")

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

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

210 query_dict = parse_qs(query)

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

212 self.assertEqual(

213 query_dict["default_server_location"],

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

215 )

216 self.assertEqual(

217 query_dict["default_access_key"], [pts.patient.uuid_as_proquint]

218 )

219

220 def test_email_body_disallows_invalid_template(self) -> None:

221 schedule = TaskScheduleFactory(email_template="{foobar}")

222 pts = PatientTaskScheduleFactory(task_schedule=schedule)

223

224 with self.assertRaises(KeyError):

225 pts.email_body(self.req)

226

227 def test_email_body_disallows_accessing_properties(self) -> None:

228 schedule = TaskScheduleFactory(email_template="{server_url.__class__}")

229 pts = PatientTaskScheduleFactory(task_schedule=schedule)

230

231 with self.assertRaises(KeyError):

232 pts.email_body(self.req)

233

234 def test_email_sent_false_for_no_emails(self) -> None:

235 pts = PatientTaskScheduleFactory()

236 self.assertFalse(pts.email_sent)

237

238 def test_email_sent_false_for_one_unsent_email(self) -> None:

239 email1 = EmailFactory(sent=False)

240 pts_email1 = PatientTaskScheduleEmailFactory(email=email1)

241 self.assertFalse(pts_email1.patient_task_schedule.email_sent)

242

243 def test_email_sent_true_for_one_sent_email(self) -> None:

244 email1 = EmailFactory(sent=True)

245 pts_email1 = PatientTaskScheduleEmailFactory(email=email1)

246 self.assertTrue(pts_email1.patient_task_schedule.email_sent)