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#!/usr/bin/env python 

2 

3""" 

4camcops_server/cc_modules/tests/cc_taskschedule_tests.py 

5 

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

7 

8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com). 

9 

10 This file is part of CamCOPS. 

11 

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

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

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

15 (at your option) any later version. 

16 

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

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

19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

20 GNU General Public License for more details. 

21 

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

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

24 

25=============================================================================== 

26 

27""" 

28 

29from urllib.parse import urlencode 

30 

31from pendulum import Duration 

32 

33from camcops_server.cc_modules.cc_pyramid import Routes 

34from camcops_server.cc_modules.cc_taskschedule import ( 

35 PatientTaskSchedule, 

36 TaskSchedule, 

37 TaskScheduleItem, 

38) 

39from camcops_server.cc_modules.cc_unittest import ( 

40 DemoDatabaseTestCase, 

41 DemoRequestTestCase, 

42) 

43 

44 

45# ============================================================================= 

46# Unit tests 

47# ============================================================================= 

48 

49class TaskScheduleTests(DemoDatabaseTestCase): 

50 def test_deleting_deletes_related_objects(self) -> None: 

51 schedule = TaskSchedule() 

52 schedule.group_id = self.group.id 

53 self.dbsession.add(schedule) 

54 self.dbsession.flush() 

55 

56 item = TaskScheduleItem() 

57 item.schedule_id = schedule.id 

58 item.task_table_name = "ace3" 

59 item.due_from = Duration(days=30) 

60 item.due_by = Duration(days=60) 

61 self.dbsession.add(item) 

62 self.dbsession.flush() 

63 

64 patient = self.create_patient() 

65 

66 pts = PatientTaskSchedule() 

67 pts.schedule_id = schedule.id 

68 pts.patient_pk = patient.pk 

69 self.dbsession.add(pts) 

70 self.dbsession.commit() 

71 

72 self.assertIsNotNone(self.dbsession.query(TaskScheduleItem).filter( 

73 TaskScheduleItem.id == item.id).one_or_none()) 

74 self.assertIsNotNone(self.dbsession.query(PatientTaskSchedule).filter( 

75 PatientTaskSchedule.id == pts.id).one_or_none()) 

76 

77 self.dbsession.delete(schedule) 

78 self.dbsession.commit() 

79 

80 self.assertIsNone(self.dbsession.query(TaskScheduleItem).filter( 

81 TaskScheduleItem.id == item.id).one_or_none()) 

82 self.assertIsNone(self.dbsession.query(PatientTaskSchedule).filter( 

83 PatientTaskSchedule.id == pts.id).one_or_none()) 

84 

85 

86class TaskScheduleItemTests(DemoRequestTestCase): 

87 def test_description_shows_shortname_and_number_of_days(self) -> None: 

88 item = TaskScheduleItem() 

89 item.task_table_name = "bmi" 

90 item.due_from = Duration(days=30) 

91 

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

93 

94 def test_description_with_no_durations(self) -> None: 

95 item = TaskScheduleItem() 

96 item.task_table_name = "bmi" 

97 

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

99 

100 def test_due_within_calculated_from_due_by_and_due_from(self) -> None: 

101 item = TaskScheduleItem() 

102 item.due_from = Duration(days=30) 

103 item.due_by = Duration(days=50) 

104 

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

106 

107 def test_due_within_is_none_when_missing_due_by(self) -> None: 

108 item = TaskScheduleItem() 

109 item.due_from = Duration(days=30) 

110 

111 self.assertIsNone(item.due_within) 

112 

113 def test_due_within_calculated_when_missing_due_from(self) -> None: 

114 item = TaskScheduleItem() 

115 item.due_by = Duration(days=30) 

116 

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

118 

119 

120class PatientTaskScheduleTests(DemoDatabaseTestCase): 

121 def setUp(self) -> None: 

122 super().setUp() 

123 

124 import datetime 

125 

126 self.schedule = TaskSchedule() 

127 self.schedule.group_id = self.group.id 

128 self.dbsession.add(self.schedule) 

129 

130 self.patient = self.create_patient( 

131 id=1, forename="Jo", surname="Patient", 

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

133 sex="F", address="Address", gp="GP", other="Other" 

134 ) 

135 

136 self.pts = PatientTaskSchedule() 

137 self.pts.schedule_id = self.schedule.id 

138 self.pts.patient_pk = self.patient.pk 

139 self.dbsession.add(self.pts) 

140 self.dbsession.flush() 

141 

142 def test_mailto_url_contains_patient_email(self) -> None: 

143 self.assertIn(f"mailto:{self.patient.email}", 

144 self.pts.mailto_url(self.req)) 

145 

146 def test_mailto_url_contains_subject(self) -> None: 

147 self.schedule.email_subject = "CamCOPS access key" 

148 self.dbsession.add(self.schedule) 

149 self.dbsession.flush() 

150 

151 self.assertIn("subject=CamCOPS%20access%20key", 

152 self.pts.mailto_url(self.req)) 

153 

154 def test_mailto_url_contains_access_key(self) -> None: 

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

156 self.dbsession.add(self.schedule) 

157 self.dbsession.flush() 

158 

159 self.assertIn(f"body={self.patient.uuid_as_proquint}", 

160 self.pts.mailto_url(self.req)) 

161 

162 def test_mailto_url_contains_server_url(self) -> None: 

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

164 self.dbsession.add(self.schedule) 

165 self.dbsession.flush() 

166 

167 expected_url = urlencode({"body": 

168 self.req.route_url(Routes.CLIENT_API)}) 

169 

170 self.assertIn(f"{expected_url}", self.pts.mailto_url(self.req)) 

171 

172 def test_mailto_url_disallows_invalid_template(self) -> None: 

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

174 self.dbsession.add(self.schedule) 

175 self.dbsession.flush() 

176 

177 with self.assertRaises(KeyError): 

178 self.pts.mailto_url(self.req) 

179 

180 def test_mailto_url_disallows_accessing_properties(self) -> None: 

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

182 self.dbsession.add(self.schedule) 

183 self.dbsession.flush() 

184 

185 with self.assertRaises(KeyError): 

186 self.pts.mailto_url(self.req)