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

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
3"""
4camcops_server/cc_modules/tests/cc_taskschedule_tests.py
6===============================================================================
8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com).
10 This file is part of CamCOPS.
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.
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.
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/>.
25===============================================================================
27"""
29from urllib.parse import urlencode
31from pendulum import Duration
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)
45# =============================================================================
46# Unit tests
47# =============================================================================
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()
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()
64 patient = self.create_patient()
66 pts = PatientTaskSchedule()
67 pts.schedule_id = schedule.id
68 pts.patient_pk = patient.pk
69 self.dbsession.add(pts)
70 self.dbsession.commit()
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())
77 self.dbsession.delete(schedule)
78 self.dbsession.commit()
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())
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)
92 self.assertEqual(item.description(self.req), "BMI @ 30 days")
94 def test_description_with_no_durations(self) -> None:
95 item = TaskScheduleItem()
96 item.task_table_name = "bmi"
98 self.assertEqual(item.description(self.req), "BMI @ ? days")
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)
105 self.assertEqual(item.due_within.in_days(), 20)
107 def test_due_within_is_none_when_missing_due_by(self) -> None:
108 item = TaskScheduleItem()
109 item.due_from = Duration(days=30)
111 self.assertIsNone(item.due_within)
113 def test_due_within_calculated_when_missing_due_from(self) -> None:
114 item = TaskScheduleItem()
115 item.due_by = Duration(days=30)
117 self.assertEqual(item.due_within.in_days(), 30)
120class PatientTaskScheduleTests(DemoDatabaseTestCase):
121 def setUp(self) -> None:
122 super().setUp()
124 import datetime
126 self.schedule = TaskSchedule()
127 self.schedule.group_id = self.group.id
128 self.dbsession.add(self.schedule)
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 )
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()
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))
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()
151 self.assertIn("subject=CamCOPS%20access%20key",
152 self.pts.mailto_url(self.req))
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()
159 self.assertIn(f"body={self.patient.uuid_as_proquint}",
160 self.pts.mailto_url(self.req))
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()
167 expected_url = urlencode({"body":
168 self.req.route_url(Routes.CLIENT_API)})
170 self.assertIn(f"{expected_url}", self.pts.mailto_url(self.req))
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()
177 with self.assertRaises(KeyError):
178 self.pts.mailto_url(self.req)
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()
185 with self.assertRaises(KeyError):
186 self.pts.mailto_url(self.req)