Example #1
0
    def test_raises_for_missing_valid_proquint(self) -> None:
        valid_proquint = "sazom-diliv-navol-hubot-mufur-mamuv-kojus-loluv-v"

        # Error message is same as for invalid proquint so make sure our
        # test proquint really is valid (should not raise)
        uuid_from_proquint(valid_proquint)

        assert self.other_device.name is not None

        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: valid_proquint,
            }
        )
        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)

        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], FAILURE_CODE, msg=reply_dict
        )
        self.assertIn(
            f"no patient with access key '{valid_proquint}'",
            reply_dict[TabletParam.ERROR],
        )
Example #2
0
    def test_creates_user(self) -> None:
        from camcops_server.cc_modules.cc_taskindex import (
            PatientIdNumIndexEntry,
        )

        patient = self.create_patient(
            _group_id=self.group.id, as_server_patient=True
        )
        idnum = self.create_patient_idnum(
            patient_id=patient.id,
            which_idnum=self.nhs_iddef.which_idnum,
            idnum_value=TEST_NHS_NUMBER,
            as_server_patient=True,
        )
        PatientIdNumIndexEntry.index_idnum(idnum, self.dbsession)

        proquint = patient.uuid_as_proquint

        # For type checker
        assert proquint is not None
        assert self.other_device.name is not None

        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: proquint,
            }
        )
        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)

        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], SUCCESS_CODE, msg=reply_dict
        )

        username = reply_dict[TabletParam.USER]
        self.assertEqual(
            username,
            make_single_user_mode_username(
                self.other_device.name, patient._pk
            ),
        )
        password = reply_dict[TabletParam.PASSWORD]
        self.assertEqual(len(password), 32)

        valid_chars = string.ascii_letters + string.digits + string.punctuation
        self.assertTrue(all(c in valid_chars for c in password))

        user = (
            self.req.dbsession.query(User)
            .filter(User.username == username)
            .one_or_none()
        )
        self.assertIsNotNone(user)
        self.assertEqual(user.upload_group, patient.group)
        self.assertTrue(user.auto_generated)
        self.assertTrue(user.may_register_devices)
        self.assertTrue(user.may_upload)
Example #3
0
    def test_returns_patient_info(self) -> None:
        import datetime

        patient = self.create_patient(
            forename="JO",
            surname="PATIENT",
            dob=datetime.date(1958, 4, 19),
            sex="F",
            address="Address",
            gp="GP",
            other="Other",
            as_server_patient=True,
        )

        self.create_patient_idnum(
            patient_id=patient.id,
            which_idnum=self.nhs_iddef.which_idnum,
            idnum_value=TEST_NHS_NUMBER,
            as_server_patient=True,
        )

        proquint = patient.uuid_as_proquint

        # For type checker
        assert proquint is not None
        assert self.other_device.name is not None

        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: proquint,
            }
        )
        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)

        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], SUCCESS_CODE, msg=reply_dict
        )

        patient_dict = json.loads(reply_dict[TabletParam.PATIENT_INFO])[0]

        self.assertEqual(patient_dict[TabletParam.SURNAME], "PATIENT")
        self.assertEqual(patient_dict[TabletParam.FORENAME], "JO")
        self.assertEqual(patient_dict[TabletParam.SEX], "F")
        self.assertEqual(patient_dict[TabletParam.DOB], "1958-04-19")
        self.assertEqual(patient_dict[TabletParam.ADDRESS], "Address")
        self.assertEqual(patient_dict[TabletParam.GP], "GP")
        self.assertEqual(patient_dict[TabletParam.OTHER], "Other")
        self.assertEqual(
            patient_dict[f"idnum{self.nhs_iddef.which_idnum}"], TEST_NHS_NUMBER
        )
Example #4
0
 def test_client_api_antique_support_3(self) -> None:
     self.announce("test_client_api_antique_support_3")
     self.req.fake_request_post_from_dict(
         {
             TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
             TabletParam.DEVICE: self.other_device.name,
             TabletParam.OPERATION: Operations.UPLOAD_TABLE,
             TabletParam.TABLE: DEVICE_STORED_VAR_TABLENAME_DEFUNCT,
         }
     )
     response = client_api(self.req)
     d = get_reply_dict_from_response(response)
     self.assertEqual(d[TabletParam.SUCCESS], SUCCESS_CODE)
Example #5
0
 def test_client_api_antique_support_2(self) -> None:
     self.announce("test_client_api_antique_support_2")
     self.req.fake_request_post_from_dict(
         {
             TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
             TabletParam.DEVICE: self.other_device.name,
             TabletParam.OPERATION: Operations.WHICH_KEYS_TO_SEND,
             TabletParam.TABLE: "nonexistent_table",
         }
     )
     response = client_api(self.req)
     d = get_reply_dict_from_response(response)
     self.assertEqual(d[TabletParam.SUCCESS], FAILURE_CODE)
Example #6
0
    def test_raises_for_invalid_proquint(self) -> None:
        # For type checker
        assert self.other_device.name is not None

        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: "invalid",
            }
        )
        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)

        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], FAILURE_CODE, msg=reply_dict
        )
        self.assertIn(
            "no patient with access key 'invalid'",
            reply_dict[TabletParam.ERROR],
        )
Example #7
0
    def test_raises_when_no_patient_idnums(self) -> None:
        # In theory this shouldn't be possible in normal operation as the
        # patient cannot be created without any idnums
        patient = self.create_patient(as_server_patient=True)

        proquint = patient.uuid_as_proquint
        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: proquint,
            }
        )

        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)
        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], FAILURE_CODE, msg=reply_dict
        )
        self.assertIn(
            "Patient has no ID numbers", reply_dict[TabletParam.ERROR]
        )
Example #8
0
    def test_raises_when_patient_not_created_on_server(self) -> None:
        patient = self.create_patient(
            _device_id=self.other_device.id, as_server_patient=True
        )

        proquint = patient.uuid_as_proquint
        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: proquint,
            }
        )

        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)
        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], FAILURE_CODE, msg=reply_dict
        )
        self.assertIn(
            f"no patient with access key '{proquint}'",
            reply_dict[TabletParam.ERROR],
        )
Example #9
0
    def test_returns_task_schedules(self) -> None:
        from pendulum import DateTime as Pendulum, Duration, local, parse

        from camcops_server.cc_modules.cc_taskindex import (
            PatientIdNumIndexEntry,
            TaskIndexEntry,
        )
        from camcops_server.cc_modules.cc_taskschedule import (
            PatientTaskSchedule,
            TaskSchedule,
            TaskScheduleItem,
        )
        from camcops_server.tasks.bmi import Bmi

        schedule1 = TaskSchedule()
        schedule1.group_id = self.group.id
        schedule1.name = "Test 1"
        self.dbsession.add(schedule1)

        schedule2 = TaskSchedule()
        schedule2.group_id = self.group.id
        self.dbsession.add(schedule2)
        self.dbsession.commit()

        item1 = TaskScheduleItem()
        item1.schedule_id = schedule1.id
        item1.task_table_name = "phq9"
        item1.due_from = Duration(days=0)
        item1.due_by = Duration(days=7)
        self.dbsession.add(item1)

        item2 = TaskScheduleItem()
        item2.schedule_id = schedule1.id
        item2.task_table_name = "bmi"
        item2.due_from = Duration(days=0)
        item2.due_by = Duration(days=8)
        self.dbsession.add(item2)

        item3 = TaskScheduleItem()
        item3.schedule_id = schedule1.id
        item3.task_table_name = "phq9"
        item3.due_from = Duration(days=30)
        item3.due_by = Duration(days=37)
        self.dbsession.add(item3)

        item4 = TaskScheduleItem()
        item4.schedule_id = schedule1.id
        item4.task_table_name = "gmcpq"
        item4.due_from = Duration(days=30)
        item4.due_by = Duration(days=38)
        self.dbsession.add(item4)
        self.dbsession.commit()

        patient = self.create_patient()
        idnum = self.create_patient_idnum(
            patient_id=patient.id,
            which_idnum=self.nhs_iddef.which_idnum,
            idnum_value=TEST_NHS_NUMBER,
        )
        PatientIdNumIndexEntry.index_idnum(idnum, self.dbsession)

        server_patient = self.create_patient(as_server_patient=True)
        _ = self.create_patient_idnum(
            patient_id=server_patient.id,
            which_idnum=self.nhs_iddef.which_idnum,
            idnum_value=TEST_NHS_NUMBER,
            as_server_patient=True,
        )

        schedule_1 = PatientTaskSchedule()
        schedule_1.patient_pk = server_patient.pk
        schedule_1.schedule_id = schedule1.id
        schedule_1.settings = {
            "bmi": {"bmi_key": "bmi_value"},
            "phq9": {"phq9_key": "phq9_value"},
        }
        schedule_1.start_datetime = local(2020, 7, 31)
        self.dbsession.add(schedule_1)

        schedule_2 = PatientTaskSchedule()
        schedule_2.patient_pk = server_patient.pk
        schedule_2.schedule_id = schedule2.id
        self.dbsession.add(schedule_2)

        bmi = Bmi()
        self.apply_standard_task_fields(bmi)
        bmi.id = 1
        bmi.height_m = 1.83
        bmi.mass_kg = 67.57
        bmi.patient_id = patient.id
        bmi.when_created = local(2020, 8, 1)
        self.dbsession.add(bmi)
        self.dbsession.commit()
        self.assertTrue(bmi.is_complete())

        TaskIndexEntry.index_task(
            bmi, self.dbsession, indexed_at_utc=Pendulum.utcnow()
        )
        self.dbsession.commit()

        proquint = server_patient.uuid_as_proquint

        # For type checker
        assert proquint is not None
        assert self.other_device.name is not None

        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.GET_TASK_SCHEDULES,
                TabletParam.PATIENT_PROQUINT: proquint,
            }
        )
        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)

        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], SUCCESS_CODE, msg=reply_dict
        )

        task_schedules = json.loads(reply_dict[TabletParam.TASK_SCHEDULES])

        self.assertEqual(len(task_schedules), 2)

        s = task_schedules[0]
        self.assertEqual(s[TabletParam.TASK_SCHEDULE_NAME], "Test 1")

        schedule_items = s[TabletParam.TASK_SCHEDULE_ITEMS]
        self.assertEqual(len(schedule_items), 4)

        phq9_1_sched = schedule_items[0]
        self.assertEqual(phq9_1_sched[TabletParam.TABLE], "phq9")
        self.assertEqual(
            phq9_1_sched[TabletParam.SETTINGS], {"phq9_key": "phq9_value"}
        )
        self.assertEqual(
            parse(phq9_1_sched[TabletParam.DUE_FROM]), local(2020, 7, 31)
        )
        self.assertEqual(
            parse(phq9_1_sched[TabletParam.DUE_BY]), local(2020, 8, 7)
        )
        self.assertFalse(phq9_1_sched[TabletParam.COMPLETE])
        self.assertFalse(phq9_1_sched[TabletParam.ANONYMOUS])

        bmi_sched = schedule_items[1]
        self.assertEqual(bmi_sched[TabletParam.TABLE], "bmi")
        self.assertEqual(
            bmi_sched[TabletParam.SETTINGS], {"bmi_key": "bmi_value"}
        )
        self.assertEqual(
            parse(bmi_sched[TabletParam.DUE_FROM]), local(2020, 7, 31)
        )
        self.assertEqual(
            parse(bmi_sched[TabletParam.DUE_BY]), local(2020, 8, 8)
        )
        self.assertTrue(bmi_sched[TabletParam.COMPLETE])
        self.assertFalse(bmi_sched[TabletParam.ANONYMOUS])

        phq9_2_sched = schedule_items[2]
        self.assertEqual(phq9_2_sched[TabletParam.TABLE], "phq9")
        self.assertEqual(
            phq9_2_sched[TabletParam.SETTINGS], {"phq9_key": "phq9_value"}
        )
        self.assertEqual(
            parse(phq9_2_sched[TabletParam.DUE_FROM]), local(2020, 8, 30)
        )
        self.assertEqual(
            parse(phq9_2_sched[TabletParam.DUE_BY]), local(2020, 9, 6)
        )
        self.assertFalse(phq9_2_sched[TabletParam.COMPLETE])
        self.assertFalse(phq9_2_sched[TabletParam.ANONYMOUS])

        # GMCPQ
        gmcpq_sched = schedule_items[3]
        self.assertTrue(gmcpq_sched[TabletParam.ANONYMOUS])
Example #10
0
    def test_returns_ip_use_flags(self) -> None:
        import datetime
        from camcops_server.cc_modules.cc_taskindex import (
            PatientIdNumIndexEntry,
        )

        patient = self.create_patient(
            forename="JO",
            surname="PATIENT",
            dob=datetime.date(1958, 4, 19),
            sex="F",
            address="Address",
            gp="GP",
            other="Other",
            as_server_patient=True,
        )
        idnum = self.create_patient_idnum(
            patient_id=patient.id,
            which_idnum=self.nhs_iddef.which_idnum,
            idnum_value=TEST_NHS_NUMBER,
            as_server_patient=True,
        )
        PatientIdNumIndexEntry.index_idnum(idnum, self.dbsession)

        patient.group.ip_use = IpUse()

        patient.group.ip_use.commercial = True
        patient.group.ip_use.clinical = True
        patient.group.ip_use.educational = False
        patient.group.ip_use.research = False

        self.dbsession.add(patient.group)
        self.dbsession.commit()

        proquint = patient.uuid_as_proquint

        # For type checker
        assert proquint is not None
        assert self.other_device.name is not None

        self.req.fake_request_post_from_dict(
            {
                TabletParam.CAMCOPS_VERSION: MINIMUM_TABLET_VERSION,
                TabletParam.DEVICE: self.other_device.name,
                TabletParam.OPERATION: Operations.REGISTER_PATIENT,
                TabletParam.PATIENT_PROQUINT: proquint,
            }
        )
        response = client_api(self.req)
        reply_dict = get_reply_dict_from_response(response)

        self.assertEqual(
            reply_dict[TabletParam.SUCCESS], SUCCESS_CODE, msg=reply_dict
        )

        ip_use_info = json.loads(reply_dict[TabletParam.IP_USE_INFO])

        self.assertEqual(ip_use_info[TabletParam.IP_USE_COMMERCIAL], 1)
        self.assertEqual(ip_use_info[TabletParam.IP_USE_CLINICAL], 1)
        self.assertEqual(ip_use_info[TabletParam.IP_USE_EDUCATIONAL], 0)
        self.assertEqual(ip_use_info[TabletParam.IP_USE_RESEARCH], 0)