示例#1
0
def export_task(req: "CamcopsRequest", recipient: ExportRecipient,
                task: Task) -> None:
    """
    Exports a single task, checking that it remains valid to do so.
    
    Args:
        req: a :class:`camcops_server.cc_modules.cc_request.CamcopsRequest`
        recipient: an :class:`camcops_server.cc_modules.cc_exportmodels.ExportRecipient`
        task: a :class:`camcops_server.cc_modules.cc_task.Task` 
    """  # noqa

    # Double-check it's OK! Just in case, for example, an old backend task has
    # persisted, or someone's managed to get an iffy back-end request in some
    # other way.
    if not recipient.is_task_suitable(task):
        # Warning will already have been emitted.
        return

    cfg = req.config
    lockfilename = cfg.get_export_lockfilename_task(
        recipient_name=recipient.recipient_name,
        basetable=task.tablename,
        pk=task.get_pk(),
    )
    dbsession = req.dbsession
    try:
        with lockfile.FileLock(lockfilename, timeout=0):  # doesn't wait
            # We recheck the export status once we hold the lock, in case
            # multiple jobs are competing to export it.
            if ExportedTask.task_already_exported(
                    dbsession=dbsession,
                    recipient_name=recipient.recipient_name,
                    basetable=task.tablename,
                    task_pk=task.get_pk()):
                log.info(
                    "Task {!r} already exported to recipient {!r}; "
                    "ignoring", task, recipient)
                # Not a warning; it's normal to see these because it allows the
                # client API to skip some checks for speed.
                return
            # OK; safe to export now.
            et = ExportedTask(recipient, task)
            dbsession.add(et)
            et.export(req)
            dbsession.commit()  # so the ExportedTask is visible to others ASAP
    except lockfile.AlreadyLocked:
        log.warning(
            "Export logfile {!r} already locked by another process; "
            "aborting", lockfilename)
示例#2
0
    def test_raises_for_missing_api_url(self) -> None:
        self.recipient.fhir_api_url = ""
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        with self.assertRaises(FhirExportException) as cm:
            FhirTaskExporter(self.req, exported_task_fhir)

        message = str(cm.exception)
        self.assertIn("must be initialized with `base_uri`", message)
示例#3
0
    def test_raises_when_fhirclient_raises(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        exporter.client.server = None
        with self.assertRaises(FhirExportException) as cm:
            exporter.export_task()

            message = str(cm.exception)
            self.assertIn("Cannot create a resource without a server", message)
示例#4
0
    def test_patient_exported(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        response_json = {Fc.TYPE: Fc.TRANSACTION_RESPONSE}

        with mock.patch.object(
            exporter.client.server,
            "post_json",
            return_value=MockFhirResponse(response_json),
        ) as mock_post:
            exporter.export_task()

        args, kwargs = mock_post.call_args

        sent_json = args[1]

        self.assertEqual(sent_json[Fc.RESOURCE_TYPE], Fc.RESOURCE_TYPE_BUNDLE)
        self.assertEqual(sent_json[Fc.TYPE], Fc.TRANSACTION)

        patient = sent_json[Fc.ENTRY][0][Fc.RESOURCE]
        self.assertEqual(patient[Fc.RESOURCE_TYPE], Fc.RESOURCE_TYPE_PATIENT)

        identifier = patient[Fc.IDENTIFIER]
        idnum_value = self.patient_rio.idnum_value

        patient_id = self.patient.get_fhir_identifier(self.req, self.recipient)

        self.assertEqual(identifier[0][Fc.SYSTEM], patient_id.system)
        self.assertEqual(identifier[0][Fc.VALUE], str(idnum_value))

        self.assertEqual(
            patient[Fc.NAME][0][Fc.NAME_FAMILY], self.patient.surname
        )
        self.assertEqual(
            patient[Fc.NAME][0][Fc.NAME_GIVEN], [self.patient.forename]
        )
        self.assertEqual(patient[Fc.GENDER], Fc.GENDER_FEMALE)

        request = sent_json[Fc.ENTRY][0][Fc.REQUEST]
        self.assertEqual(request[Fc.METHOD], HttpMethod.POST)
        self.assertEqual(request[Fc.URL], Fc.RESOURCE_TYPE_PATIENT)
        self.assertEqual(
            request[Fc.IF_NONE_EXIST],
            fhir_reference_from_identifier(patient_id),
        )
示例#5
0
    def test_raises_when_http_error(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        errmsg = "Something bad happened"
        with mock.patch.object(
            exporter.client.server,
            "post_json",
            side_effect=HTTPError(response=mock.Mock(text=errmsg)),
        ):
            with self.assertRaises(FhirExportException) as cm:
                exporter.export_task()

            message = str(cm.exception)
            self.assertIn(errmsg, message)
示例#6
0
    def test_questionnaire_response_exported(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        response_json = {Fc.TYPE: Fc.TRANSACTION_RESPONSE}

        with mock.patch.object(
            exporter.client.server,
            "post_json",
            return_value=MockFhirResponse(response_json),
        ) as mock_post:
            exporter.export_task()

        args, kwargs = mock_post.call_args

        sent_json = args[1]

        response = sent_json[Fc.ENTRY][1][Fc.RESOURCE]
        self.assertEqual(
            response[Fc.RESOURCE_TYPE], Fc.RESOURCE_TYPE_QUESTIONNAIRE_RESPONSE
        )
        q_id = self.task._get_fhir_questionnaire_id(self.req)
        self.assertEqual(response[Fc.QUESTIONNAIRE], fhir_sysval_from_id(q_id))
        self.assertEqual(
            response[Fc.AUTHORED], self.task.when_created.isoformat()
        )
        self.assertEqual(response[Fc.STATUS], Fc.QSTATUS_COMPLETED)

        request = sent_json[Fc.ENTRY][1][Fc.REQUEST]
        self.assertEqual(request[Fc.METHOD], HttpMethod.POST)
        self.assertEqual(request[Fc.URL], "QuestionnaireResponse")
        qr_id = self.task._get_fhir_questionnaire_response_id(self.req)
        self.assertEqual(
            request[Fc.IF_NONE_EXIST], fhir_reference_from_identifier(qr_id)
        )

        self.assertEqual(len(response[Fc.ITEM]), 5)
        (
            q1_choice,
            q2_choice,
            q3_choice,
            q1_satisfaction,
            q2_satisfaction,
        ) = response[Fc.ITEM]

        # q1_choice
        self.assertEqual(q1_choice[Fc.LINK_ID], "q1_choice")
        self.assertEqual(q1_choice[Fc.TEXT], GIVEN_INFO)
        q1_choice_answer = q1_choice[Fc.ANSWER][0]
        self.assertEqual(
            q1_choice_answer[Fc.VALUE_INTEGER], self.task.q1_choice
        )

        # q2_choice
        self.assertEqual(q2_choice[Fc.LINK_ID], "q2_choice")
        self.assertEqual(q2_choice[Fc.TEXT], PREFER_ANY)
        q2_choice_answer = q2_choice[Fc.ANSWER][0]
        self.assertEqual(
            q2_choice_answer[Fc.VALUE_INTEGER], self.task.q2_choice
        )

        # q3_choice
        self.assertEqual(q3_choice[Fc.LINK_ID], "q3_choice")
        self.assertEqual(q3_choice[Fc.TEXT], OFFERED_PREFERENCE)
        q3_choice_answer = q3_choice[Fc.ANSWER][0]
        self.assertEqual(
            q3_choice_answer[Fc.VALUE_INTEGER], self.task.q3_choice
        )

        # q1_satisfaction
        self.assertEqual(q1_satisfaction[Fc.LINK_ID], "q1_satisfaction")
        self.assertEqual(q1_satisfaction[Fc.TEXT], SATISFIED_ASSESSMENT)
        q1_satisfaction_answer = q1_satisfaction[Fc.ANSWER][0]
        self.assertEqual(
            q1_satisfaction_answer[Fc.VALUE_INTEGER], self.task.q1_satisfaction
        )

        # q2 satisfaction
        self.assertEqual(q2_satisfaction[Fc.LINK_ID], "q2_satisfaction")
        self.assertEqual(q2_satisfaction[Fc.TEXT], TELL_US)
        q2_satisfaction_answer = q2_satisfaction[Fc.ANSWER][0]
        self.assertEqual(
            q2_satisfaction_answer[Fc.VALUE_STRING], self.task.q2_satisfaction
        )
示例#7
0
    def test_questionnaire_exported(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        response_json = {Fc.TYPE: Fc.TRANSACTION_RESPONSE}

        with mock.patch.object(
            exporter.client.server,
            "post_json",
            return_value=MockFhirResponse(response_json),
        ) as mock_post:
            exporter.export_task()

        args, kwargs = mock_post.call_args

        sent_json = args[1]

        questionnaire = sent_json[Fc.ENTRY][0][Fc.RESOURCE]
        self.assertEqual(
            questionnaire[Fc.RESOURCE_TYPE], Fc.RESOURCE_TYPE_QUESTIONNAIRE
        )
        self.assertEqual(questionnaire[Fc.STATUS], Fc.QSTATUS_ACTIVE)

        identifier = questionnaire[Fc.IDENTIFIER]

        questionnaire_url = (
            f"{self.camcops_root_url}/{Routes.FHIR_QUESTIONNAIRE_SYSTEM}"
        )
        self.assertEqual(identifier[0][Fc.SYSTEM], questionnaire_url)
        self.assertEqual(
            identifier[0][Fc.VALUE], f"apeqpt/{CAMCOPS_SERVER_VERSION_STRING}"
        )

        self.assertEqual(len(questionnaire[Fc.ITEM]), 5)
        (
            q1_choice,
            q2_choice,
            q3_choice,
            q1_satisfaction,
            q2_satisfaction,
        ) = questionnaire[Fc.ITEM]

        # q1_choice
        self.assertEqual(q1_choice[Fc.LINK_ID], "q1_choice")
        self.assertEqual(q1_choice[Fc.TEXT], GIVEN_INFO)
        self.assertEqual(q1_choice[Fc.TYPE], Fc.QITEM_TYPE_CHOICE)

        options = q1_choice[Fc.ANSWER_OPTION]
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.CODE], "0")
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.DISPLAY], "No")

        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.CODE], "1")
        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.DISPLAY], "Yes")

        # q2_choice
        self.assertEqual(q2_choice[Fc.LINK_ID], "q2_choice")
        self.assertEqual(q2_choice[Fc.TEXT], PREFER_ANY)
        self.assertEqual(q2_choice[Fc.TYPE], Fc.QITEM_TYPE_CHOICE)
        options = q2_choice[Fc.ANSWER_OPTION]
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.CODE], "0")
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.DISPLAY], "No")

        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.CODE], "1")
        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.DISPLAY], "Yes")

        # q3_choice
        self.assertEqual(q3_choice[Fc.LINK_ID], "q3_choice")
        self.assertEqual(q3_choice[Fc.TEXT], OFFERED_PREFERENCE)
        self.assertEqual(q3_choice[Fc.TYPE], Fc.QITEM_TYPE_CHOICE)
        options = q3_choice[Fc.ANSWER_OPTION]
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.CODE], "0")
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.DISPLAY], "No")

        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.CODE], "1")
        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.DISPLAY], "Yes")

        self.assertEqual(options[2][Fc.VALUE_CODING][Fc.CODE], "2")
        self.assertEqual(options[2][Fc.VALUE_CODING][Fc.DISPLAY], "N/A")

        # q1_satisfaction
        self.assertEqual(q1_satisfaction[Fc.LINK_ID], "q1_satisfaction")
        self.assertEqual(q1_satisfaction[Fc.TEXT], SATISFIED_ASSESSMENT)
        self.assertEqual(q1_satisfaction[Fc.TYPE], Fc.QITEM_TYPE_CHOICE)
        options = q1_satisfaction[Fc.ANSWER_OPTION]
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.CODE], "0")
        self.assertEqual(
            options[0][Fc.VALUE_CODING][Fc.DISPLAY], APEQ_SATIS_A0
        )

        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.CODE], "1")
        self.assertEqual(
            options[1][Fc.VALUE_CODING][Fc.DISPLAY], APEQ_SATIS_A1
        )

        self.assertEqual(options[2][Fc.VALUE_CODING][Fc.CODE], "2")
        self.assertEqual(
            options[2][Fc.VALUE_CODING][Fc.DISPLAY], APEQ_SATIS_A2
        )

        self.assertEqual(options[3][Fc.VALUE_CODING][Fc.CODE], "3")
        self.assertEqual(
            options[3][Fc.VALUE_CODING][Fc.DISPLAY], APEQ_SATIS_A3
        )

        self.assertEqual(options[4][Fc.VALUE_CODING][Fc.CODE], "4")
        self.assertEqual(
            options[4][Fc.VALUE_CODING][Fc.DISPLAY], APEQ_SATIS_A4
        )

        # q2 satisfaction
        self.assertEqual(q2_satisfaction[Fc.LINK_ID], "q2_satisfaction")
        self.assertEqual(q2_satisfaction[Fc.TEXT], TELL_US)
        self.assertEqual(q2_satisfaction[Fc.TYPE], Fc.QITEM_TYPE_STRING)

        request = sent_json[Fc.ENTRY][0][Fc.REQUEST]
        self.assertEqual(request[Fc.METHOD], HttpMethod.POST)
        self.assertEqual(request[Fc.URL], Fc.RESOURCE_TYPE_QUESTIONNAIRE)
        q_id = self.task._get_fhir_questionnaire_id(self.req)
        self.assertEqual(
            request[Fc.IF_NONE_EXIST], fhir_reference_from_identifier(q_id)
        )
示例#8
0
    def test_exported_task_saved(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        # auto increment doesn't work for BigInteger with SQLite
        exported_task.id = 1
        self.dbsession.add(exported_task)

        exported_task_fhir = ExportedTaskFhir(exported_task)
        self.dbsession.add(exported_task_fhir)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        response_json = {
            Fc.RESOURCE_TYPE: Fc.RESOURCE_TYPE_BUNDLE,
            Fc.ID: "cae48957-e7e6-4649-97f8-0a882076ad0a",
            Fc.TYPE: Fc.TRANSACTION_RESPONSE,
            Fc.LINK: [
                {Fc.RELATION: Fc.SELF, Fc.URL: "http://localhost:8080/fhir"}
            ],
            Fc.ENTRY: [
                {
                    Fc.RESPONSE: {
                        Fc.STATUS: Fc.RESPONSE_STATUS_200_OK,
                        Fc.LOCATION: "Patient/1/_history/1",
                        Fc.ETAG: "1",
                    }
                },
                {
                    Fc.RESPONSE: {
                        Fc.STATUS: Fc.RESPONSE_STATUS_200_OK,
                        Fc.LOCATION: "Questionnaire/26/_history/1",
                        Fc.ETAG: "1",
                    }
                },
                {
                    Fc.RESPONSE: {
                        Fc.STATUS: Fc.RESPONSE_STATUS_201_CREATED,
                        Fc.LOCATION: "QuestionnaireResponse/42/_history/1",
                        Fc.ETAG: "1",
                        Fc.LAST_MODIFIED: "2021-05-24T09:30:11.098+00:00",
                    }
                },
            ],
        }

        with mock.patch.object(
            exporter.client.server,
            "post_json",
            return_value=MockFhirResponse(response_json),
        ):
            exporter.export_task()

        self.dbsession.commit()

        entries = (
            exported_task_fhir.entries
        )  # type: List[ExportedTaskFhirEntry]  # noqa

        entries.sort(key=lambda e: e.location)

        self.assertEqual(entries[0].status, Fc.RESPONSE_STATUS_200_OK)
        self.assertEqual(entries[0].location, "Patient/1/_history/1")
        self.assertEqual(entries[0].etag, "1")

        self.assertEqual(entries[1].status, Fc.RESPONSE_STATUS_200_OK)
        self.assertEqual(entries[1].location, "Questionnaire/26/_history/1")
        self.assertEqual(entries[1].etag, "1")

        self.assertEqual(entries[2].status, Fc.RESPONSE_STATUS_201_CREATED)
        self.assertEqual(
            entries[2].location, "QuestionnaireResponse/42/_history/1"
        )
        self.assertEqual(entries[2].etag, "1")
        self.assertEqual(
            entries[2].last_modified,
            datetime.datetime(2021, 5, 24, 9, 30, 11, 98000),
        )
示例#9
0
    def test_questionnaire_response_exported(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        response_json = {Fc.TYPE: Fc.TRANSACTION_RESPONSE}

        with mock.patch.object(
            exporter.client.server,
            "post_json",
            return_value=MockFhirResponse(response_json),
        ) as mock_post:
            exporter.export_task()

        args, kwargs = mock_post.call_args

        sent_json = args[1]

        response = sent_json[Fc.ENTRY][2][Fc.RESOURCE]
        self.assertEqual(
            response[Fc.RESOURCE_TYPE], Fc.RESOURCE_TYPE_QUESTIONNAIRE_RESPONSE
        )

        q_id = self.task._get_fhir_questionnaire_id(self.req)
        self.assertEqual(response[Fc.QUESTIONNAIRE], fhir_sysval_from_id(q_id))
        self.assertEqual(
            response[Fc.AUTHORED], self.task.when_created.isoformat()
        )
        self.assertEqual(response[Fc.STATUS], Fc.QSTATUS_COMPLETED)

        subject = response[Fc.SUBJECT]
        identifier = subject[Fc.IDENTIFIER]
        self.assertEqual(subject[Fc.TYPE], Fc.RESOURCE_TYPE_PATIENT)
        idnum_value = self.patient_rio.idnum_value

        patient_id = self.patient.get_fhir_identifier(self.req, self.recipient)
        if isinstance(identifier, list):
            test_identifier = identifier[0]
        else:  # only one
            test_identifier = identifier
        self.assertEqual(test_identifier[Fc.SYSTEM], patient_id.system)
        self.assertEqual(test_identifier[Fc.VALUE], str(idnum_value))

        request = sent_json[Fc.ENTRY][2][Fc.REQUEST]
        self.assertEqual(request[Fc.METHOD], HttpMethod.POST)
        self.assertEqual(
            request[Fc.URL], Fc.RESOURCE_TYPE_QUESTIONNAIRE_RESPONSE
        )
        qr_id = self.task._get_fhir_questionnaire_response_id(self.req)
        self.assertEqual(
            request[Fc.IF_NONE_EXIST], fhir_reference_from_identifier(qr_id)
        )

        item_1 = response[Fc.ITEM][0]
        item_10 = response[Fc.ITEM][9]
        self.assertEqual(item_1[Fc.LINK_ID], "q1")
        self.assertEqual(
            item_1[Fc.TEXT], "1. Little interest or pleasure in doing things"
        )
        answer_1 = item_1[Fc.ANSWER][0]
        # noinspection PyUnresolvedReferences
        self.assertEqual(answer_1[Fc.VALUE_INTEGER], self.task.q1)

        self.assertEqual(item_10[Fc.LINK_ID], "q10")
        self.assertEqual(
            item_10[Fc.TEXT],
            (
                "10. If you checked off any problems, how difficult have "
                "these problems made it for you to do your work, take care of "
                "things at home, or get along with other people?"
            ),
        )
        answer_10 = item_10[Fc.ANSWER][0]
        self.assertEqual(answer_10[Fc.VALUE_INTEGER], self.task.q10)

        self.assertEqual(len(response[Fc.ITEM]), 10)
示例#10
0
    def test_questionnaire_exported(self) -> None:
        exported_task = ExportedTask(task=self.task, recipient=self.recipient)
        exported_task_fhir = ExportedTaskFhir(exported_task)

        exporter = MockFhirTaskExporter(self.req, exported_task_fhir)

        response_json = {Fc.TYPE: Fc.TRANSACTION_RESPONSE}

        with mock.patch.object(
            exporter.client.server,
            "post_json",
            return_value=MockFhirResponse(response_json),
        ) as mock_post:
            exporter.export_task()

        args, kwargs = mock_post.call_args

        sent_json = args[1]

        questionnaire = sent_json[Fc.ENTRY][1][Fc.RESOURCE]
        self.assertEqual(
            questionnaire[Fc.RESOURCE_TYPE], Fc.RESOURCE_TYPE_QUESTIONNAIRE
        )
        self.assertEqual(questionnaire[Fc.STATUS], Fc.QSTATUS_ACTIVE)

        identifier = questionnaire[Fc.IDENTIFIER]

        questionnaire_url = (
            f"{self.camcops_root_url}/{Routes.FHIR_QUESTIONNAIRE_SYSTEM}"
        )
        self.assertEqual(identifier[0][Fc.SYSTEM], questionnaire_url)
        self.assertEqual(
            identifier[0][Fc.VALUE], f"phq9/{CAMCOPS_SERVER_VERSION_STRING}"
        )

        question_1 = questionnaire[Fc.ITEM][0]
        question_10 = questionnaire[Fc.ITEM][9]
        self.assertEqual(question_1[Fc.LINK_ID], "q1")
        self.assertEqual(
            question_1[Fc.TEXT],
            "1. Little interest or pleasure in doing things",
        )
        self.assertEqual(question_1[Fc.TYPE], Fc.QITEM_TYPE_CHOICE)

        options = question_1[Fc.ANSWER_OPTION]
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.CODE], "0")
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.DISPLAY], "Not at all")

        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.CODE], "1")
        self.assertEqual(
            options[1][Fc.VALUE_CODING][Fc.DISPLAY], "Several days"
        )

        self.assertEqual(options[2][Fc.VALUE_CODING][Fc.CODE], "2")
        self.assertEqual(
            options[2][Fc.VALUE_CODING][Fc.DISPLAY], "More than half the days"
        )

        self.assertEqual(options[3][Fc.VALUE_CODING][Fc.CODE], "3")
        self.assertEqual(
            options[3][Fc.VALUE_CODING][Fc.DISPLAY], "Nearly every day"
        )

        self.assertEqual(question_10[Fc.LINK_ID], "q10")
        self.assertEqual(
            question_10[Fc.TEXT],
            (
                "10. If you checked off any problems, how difficult have "
                "these problems made it for you to do your work, take care of "
                "things at home, or get along with other people?"
            ),
        )
        self.assertEqual(question_10[Fc.TYPE], Fc.QITEM_TYPE_CHOICE)
        options = question_10[Fc.ANSWER_OPTION]
        self.assertEqual(options[0][Fc.VALUE_CODING][Fc.CODE], "0")
        self.assertEqual(
            options[0][Fc.VALUE_CODING][Fc.DISPLAY], "Not difficult at all"
        )

        self.assertEqual(options[1][Fc.VALUE_CODING][Fc.CODE], "1")
        self.assertEqual(
            options[1][Fc.VALUE_CODING][Fc.DISPLAY], "Somewhat difficult"
        )

        self.assertEqual(options[2][Fc.VALUE_CODING][Fc.CODE], "2")
        self.assertEqual(
            options[2][Fc.VALUE_CODING][Fc.DISPLAY], "Very difficult"
        )

        self.assertEqual(options[3][Fc.VALUE_CODING][Fc.CODE], "3")
        self.assertEqual(
            options[3][Fc.VALUE_CODING][Fc.DISPLAY], "Extremely difficult"
        )

        self.assertEqual(len(questionnaire[Fc.ITEM]), 10)

        request = sent_json[Fc.ENTRY][1][Fc.REQUEST]
        self.assertEqual(request[Fc.METHOD], HttpMethod.POST)
        self.assertEqual(request[Fc.URL], Fc.RESOURCE_TYPE_QUESTIONNAIRE)
        q_id = self.task._get_fhir_questionnaire_id(self.req)
        self.assertEqual(
            request[Fc.IF_NONE_EXIST], fhir_reference_from_identifier(q_id)
        )