davinci_crd_test_kit 0.14.1 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/{inferno_crd_server_suite.json.erb → client_against_inferno_crd_server_suite.json.erb} +0 -33
  3. data/config/presets/{ri_crd_request_generator.json.erb → client_against_ri_crd_request_generator.json.erb} +1 -14
  4. data/config/presets/client_v221_against_inferno_crd_server_suite.json.erb +84 -0
  5. data/config/presets/client_v221_against_ri_br_provider.json.erb +31 -0
  6. data/config/presets/{ri_crd_request_generator.json_v221.json.erb → client_v221_against_ri_crd_request_generator.json.erb} +1 -1
  7. data/config/presets/{inferno_crd_client_suite.json.erb → server_against_inferno_crd_client_suite.json.erb} +0 -43
  8. data/config/presets/{ri_crd_server.json.erb → server_against_ri_crd_server.json.erb} +1 -44
  9. data/config/presets/{inferno_crd_client_suite_v221.json.erb → server_v221_against_inferno_crd_client_suite.json.erb} +0 -61
  10. data/config/presets/{inferno_crd_client_suite_prefetch_subset_v221.json.erb → server_v221_against_inferno_crd_client_suite_prefetch_subset.json.erb} +0 -46
  11. data/config/presets/server_v221_against_inferno_g31_suite.json.erb +49 -0
  12. data/lib/davinci_crd_test_kit/client/cross_hook_helper.rb +26 -0
  13. data/lib/davinci_crd_test_kit/client/endpoints/custom_service_response.rb +7 -7
  14. data/lib/davinci_crd_test_kit/client/endpoints/gather_response_generation_data.rb +4 -1
  15. data/lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb +63 -38
  16. data/lib/davinci_crd_test_kit/client/endpoints/mock_service_response.rb +26 -7
  17. data/lib/davinci_crd_test_kit/client/endpoints/scenario_service_response.rb +54 -0
  18. data/lib/davinci_crd_test_kit/client/tagged_request_load_helper.rb +8 -27
  19. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/retrieve_jwks_test.rb +35 -23
  20. data/lib/davinci_crd_test_kit/client/v2.0.1/auth/token_payload_test.rb +34 -21
  21. data/lib/davinci_crd_test_kit/client/v2.0.1/cds-services-v201.json +20 -20
  22. data/lib/davinci_crd_test_kit/client/v2.0.1/client_appointment_book_group.rb +12 -10
  23. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_discharge_group.rb +12 -10
  24. data/lib/davinci_crd_test_kit/client/v2.0.1/client_encounter_start_group.rb +12 -10
  25. data/lib/davinci_crd_test_kit/client/v2.0.1/client_hooks_group.rb +5 -5
  26. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_dispatch_group.rb +12 -10
  27. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_select_group.rb +12 -10
  28. data/lib/davinci_crd_test_kit/client/v2.0.1/client_order_sign_group.rb +12 -10
  29. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_coverage_information.rb +3 -36
  30. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_external_reference.rb +3 -36
  31. data/lib/davinci_crd_test_kit/client/v2.0.1/must_support/client_card_must_support_instructions.rb +3 -36
  32. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_fetched_data_test.rb +4 -13
  33. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_request/hook_request_prefetch_equals_queried_test.rb +3 -13
  34. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/client_display_cards_attest.rb +3 -13
  35. data/lib/davinci_crd_test_kit/client/v2.0.1/verify_response/inferno_response_validation.rb +3 -13
  36. data/lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb +1 -1
  37. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/attestation_instructions.rb +10 -0
  38. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_authorized_scope_attestation_test.rb +45 -0
  39. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_coverage_based_invocation_attestation_test.rb +44 -0
  40. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_data_element_expectations_attestation_test.rb +44 -0
  41. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_hook_invocation_logging_attestation_test.rb +43 -0
  42. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_must_support_exposure_attestation_test.rb +43 -0
  43. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_must_support_use_attestation_test.rb +41 -0
  44. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_order_sign_support_attestation_test.rb +42 -0
  45. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_prefetch_key_omission_attestation_test.rb +42 -0
  46. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_resource_identifiers_attestation_test.rb +43 -0
  47. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_response_case_distinction_attestation_test.rb +43 -0
  48. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_security_and_privacy_attestation_test.rb +43 -0
  49. data/lib/davinci_crd_test_kit/client/v2.2.1/attestations/client_workflow_integration_attestation_test.rb +44 -0
  50. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/decode_auth_token_test.rb +1 -1
  51. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/retrieve_jwks_test.rb +29 -18
  52. data/lib/davinci_crd_test_kit/client/v2.2.1/auth/token_payload_test.rb +35 -22
  53. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-prefetch-subset-v221.json +47 -47
  54. data/lib/davinci_crd_test_kit/client/v2.2.1/cds-services-v221.json +50 -50
  55. data/lib/davinci_crd_test_kit/client/v2.2.1/client_appointment_book_group.rb +16 -14
  56. data/lib/davinci_crd_test_kit/client/v2.2.1/client_attestations_group.rb +49 -0
  57. data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_group.rb +22 -6
  58. data/lib/davinci_crd_test_kit/client/v2.2.1/client_cross_hook_interaction_group.rb +98 -0
  59. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_discharge_group.rb +12 -10
  60. data/lib/davinci_crd_test_kit/client/v2.2.1/client_encounter_start_group.rb +12 -10
  61. data/lib/davinci_crd_test_kit/client/v2.2.1/client_fhir_api_group.rb +14 -12
  62. data/lib/davinci_crd_test_kit/client/v2.2.1/client_hooks_group.rb +9 -9
  63. data/lib/davinci_crd_test_kit/client/v2.2.1/client_long_running_hook_group.rb +2 -1
  64. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_dispatch_group.rb +16 -14
  65. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_select_group.rb +12 -10
  66. data/lib/davinci_crd_test_kit/client/v2.2.1/client_order_sign_group.rb +16 -14
  67. data/lib/davinci_crd_test_kit/client/v2.2.1/client_scenarios_group.rb +26 -0
  68. data/lib/davinci_crd_test_kit/client/v2.2.1/client_self_pay_hook_group.rb +36 -0
  69. data/lib/davinci_crd_test_kit/client/v2.2.1/client_unknown_content_hook_group.rb +34 -0
  70. data/lib/davinci_crd_test_kit/client/v2.2.1/crd_client_suite.rb +19 -3
  71. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_card_must_support_coverage_information_test.rb +1 -1
  72. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_fhirpath_collection_as_comma_delimited_string_test.rb +4 -11
  73. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_hook_instances_unique_test.rb +1 -9
  74. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_location_address_propagation_test.rb +6 -2
  75. data/lib/davinci_crd_test_kit/client/v2.2.1/cross_hook/client_prefetch_complete_and_subset_test.rb +3 -12
  76. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/appointment_book_receive_request_test.rb +8 -89
  77. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/base_hook_invocation_receive_request_test.rb +163 -0
  78. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/cross_hooks_receive_request_test.rb +97 -0
  79. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_discharge_receive_request_test.rb +8 -90
  80. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/encounter_start_receive_request_test.rb +8 -90
  81. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_dispatch_receive_request_test.rb +8 -98
  82. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_select_receive_request_test.rb +8 -98
  83. data/lib/davinci_crd_test_kit/client/v2.2.1/invocation/order_sign_receive_request_test.rb +8 -98
  84. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_long_running_receive_request_test.rb +10 -2
  85. data/lib/davinci_crd_test_kit/client/v2.2.1/long_running/client_skip_long_running_attestation_test.rb +1 -1
  86. data/lib/davinci_crd_test_kit/client/v2.2.1/self_pay/client_self_pay_no_request_test.rb +30 -0
  87. data/lib/davinci_crd_test_kit/client/v2.2.1/self_pay/client_self_pay_workflow_test.rb +55 -0
  88. data/lib/davinci_crd_test_kit/client/v2.2.1/unknown_content/client_unknown_content_attestation_test.rb +99 -0
  89. data/lib/davinci_crd_test_kit/client/v2.2.1/unknown_content/client_unknown_content_receive_request_test.rb +62 -0
  90. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_conformance_test.rb +1 -1
  91. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_coverage_verification_test.rb +10 -2
  92. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_data_fetch_verification_test.rb +1 -1
  93. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_granted_scopes_test.rb +1 -1
  94. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_complete_test.rb +1 -1
  95. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_prefetch_profiles_test.rb +1 -1
  96. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_requested_version_test.rb +1 -1
  97. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_request/hook_request_secured_transport_test.rb +1 -1
  98. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/client_display_cards_attest.rb +52 -20
  99. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/hook_response_support_coverage_information_test.rb +1 -1
  100. data/lib/davinci_crd_test_kit/client/v2.2.1/verify_response/inferno_response_validation.rb +6 -3
  101. data/lib/davinci_crd_test_kit/cross_suite/cards_identification.rb +9 -0
  102. data/lib/davinci_crd_test_kit/cross_suite/logical_models_override_helper.rb +30 -13
  103. data/lib/davinci_crd_test_kit/cross_suite/prefetch_profile_validation.rb +2 -0
  104. data/lib/davinci_crd_test_kit/cross_suite/requests_logical_model_validation.rb +26 -27
  105. data/lib/davinci_crd_test_kit/cross_suite/response_logical_model_validation.rb +48 -41
  106. data/lib/davinci_crd_test_kit/cross_suite/tags.rb +3 -0
  107. data/lib/davinci_crd_test_kit/requirements/cds-hooks_3.0.0-ballot_requirements.xlsx +0 -0
  108. data/lib/davinci_crd_test_kit/requirements/davinci_crd_test_kit_requirements.csv +6 -2
  109. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_requirements_coverage.csv +107 -107
  110. data/lib/davinci_crd_test_kit/requirements/generated/crd_client_v221_requirements_coverage.csv +101 -97
  111. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_requirements_coverage.csv +18 -18
  112. data/lib/davinci_crd_test_kit/requirements/generated/crd_server_v221_requirements_coverage.csv +36 -32
  113. data/lib/davinci_crd_test_kit/requirements/hl7.fhir.us.davinci-crd_2.2.1_requirements.xlsx +0 -0
  114. data/lib/davinci_crd_test_kit/server/v2.0.1/crd_server_suite.rb +1 -1
  115. data/lib/davinci_crd_test_kit/server/v2.0.1/server_hooks_group.rb +5 -5
  116. data/lib/davinci_crd_test_kit/server/v2.2.1/discovery/discovery_standard_prefetch_expressions_test.rb +1 -2
  117. data/lib/davinci_crd_test_kit/server/v2.2.1/server_demonstrate_hook_response_group.rb +2 -2
  118. data/lib/davinci_crd_test_kit/server/v2.2.1/server_hooks_group.rb +5 -5
  119. data/lib/davinci_crd_test_kit/version.rb +2 -2
  120. metadata +40 -12
  121. data/config/presets/inferno_crd_server_suite_v221.json.erb +0 -94
@@ -0,0 +1,49 @@
1
+ {
2
+ "title": "Run Against the (g)(31) Suite",
3
+ "id": "inferno-crd-server-v221-against-g31-v221",
4
+ "test_suite_id": "crd_server_v221",
5
+ "inputs": [
6
+ {
7
+ "name": "base_url",
8
+ "title": "CRD server base URL",
9
+ "type": "text",
10
+ "value": "<%= Inferno::Application['base_url'] %>/custom/g31_certification/crd_v221"
11
+ },
12
+ {
13
+ "name": "authentication_required",
14
+ "title": "Discovery endpoint requires authentication?",
15
+ "type": "radio",
16
+ "value": "no"
17
+ },
18
+ {
19
+ "name": "encryption_method",
20
+ "title": "JWT Signing Algorithm",
21
+ "type": "radio",
22
+ "value": "ES384"
23
+ },
24
+ {
25
+ "name": "jwks_kid",
26
+ "title": "CDS Services JWKS kid",
27
+ "type": "text",
28
+ "value": ""
29
+ },
30
+ {
31
+ "name": "any_hook_request_body",
32
+ "title": "Request body to use for the \"Demonstrate a Hook Response\" test",
33
+ "type": "textarea",
34
+ "value": "{\n \"hookInstance\": \"d2577c69-dfbe-77ad-ba6d-3e05e953b2ea\",\n \"fhirServer\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir\",\n \"hook\": \"order-sign\",\n \"fhirAuthorization\": {\n \"access_token\": \"SAMPLE_TOKEN\",\n \"token_type\": \"Bearer\",\n \"expires_in\": 300,\n \"scope\": \"user/AllergyIntolerance.rs user/CarePlan.rs user/CareTeam.rs user/Condition.rs user/Device.rs user/DiagnosticReport.rs user/DocumentReference.rs user/Encounter.rs user/Goal.rs user/Immunization.rs user/Location.rs user/Medication.rs user/MedicationRequest.rs user/Observation.rs user/Organization.rs user/Patient.rs user/Practitioner.rs user/PractitionerRole.rs user/Procedure.rs user/Provenance.rs\",\n \"subject\": \"cds-service4\"\n },\n \"context\": {\n \"userId\": \"Practitioner/crd221-demo-practitioner-orderer\",\n \"patientId\": \"crd221-demo-patient\",\n \"encounterId\": \"crd221-demo-encounter-no-performer\",\n \"draftOrders\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/DeviceRequest/crd221-demo-devicerequest-different-orderer-vs-performer\",\n \"resource\": {\n \"resourceType\": \"DeviceRequest\",\n \"id\": \"crd221-demo-devicerequest-different-orderer-vs-performer\",\n \"identifier\": [\n {\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0203\",\n \"code\": \"PLAC\"\n }\n ]\n },\n \"value\": \"f105372f-bbef-442c-ad7a-708fee7f8c93\"\n }\n ],\n \"status\": \"draft\",\n \"intent\": \"original-order\",\n \"codeCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"https://bluebutton.cms.gov/resources/codesystem/hcpcs\",\n \"code\": \"E0250\",\n \"display\": \"Hospital bed fixed height with any type of side rails, mattress\"\n }\n ]\n },\n \"authoredOn\": \"2026-05-14\",\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"requester\": {\n \"reference\": \"Practitioner/crd221-demo-practitioner-orderer\"\n },\n \"performer\": {\n \"reference\": \"Practitioner/crd221-demo-practitioner-performer\"\n }\n }\n }\n ]\n }\n },\n \"extension\": {\n \"davinci-crd.configuration\": {\n \"alt-drug\": true\n },\n \"davinci-crd.requestedVersion\": \"2.2\"\n },\n \"prefetch\": {\n \"patient\": {\n \"resourceType\": \"Patient\",\n \"id\": \"crd221-demo-patient\",\n \"gender\": \"male\",\n \"birthDate\": \"2015-02-23\",\n \"address\": [\n {\n \"use\": \"home\",\n \"type\": \"both\",\n \"state\": \"NY\",\n \"city\": \"Buffalo\",\n \"postalCode\": \"14210\",\n \"line\": [\n \"202 Burlington Road\"\n ]\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Oster\",\n \"given\": [\n \"William\",\n \"Hale\",\n \"Oster\"\n ]\n }\n ],\n \"telecom\": [\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555-5555\",\n \"use\": \"home\",\n \"rank\": 1\n },\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555 5613\",\n \"use\": \"work\",\n \"rank\": 2\n },\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555 8834\",\n \"use\": \"old\",\n \"period\": {\n \"end\": \"2014\"\n }\n }\n ],\n \"identifier\": [\n {\n \"use\": \"usual\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0203\",\n \"code\": \"MR\"\n }\n ],\n \"text\": \"Medical Record Number\"\n },\n \"system\": \"http://hl7.org/fhir/sid/us-medicare\",\n \"value\": \"0M34355006FW\"\n }\n ]\n },\n \"encounter\": {\n \"resourceType\": \"Encounter\",\n \"id\": \"crd221-demo-encounter-no-performer\",\n \"status\": \"in-progress\",\n \"class\": {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n \"code\": \"AMB\",\n \"display\": \"ambulatory\"\n },\n \"type\": [\n {\n \"coding\": [\n {\n \"system\": \"http://www.ama-assn.org/go/cpt\",\n \"code\": \"99211\"\n }\n ],\n \"text\": \"Office Visit\"\n }\n ],\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n }\n },\n \"coverage\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"searchset\",\n \"total\": 1,\n \"link\": [\n {\n \"relation\": \"self\",\n \"url\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Coverage?patient=crd221-demo-patient\"\n }\n ],\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Coverage/crd221-demo-coverage-complete-prefetch\",\n \"resource\": {\n \"resourceType\": \"Coverage\",\n \"id\": \"crd221-demo-coverage-complete-prefetch\",\n \"subscriberId\": \"10A3D58WH456\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/subscriber-relationship\",\n \"code\": \"self\"\n }\n ]\n },\n \"beneficiary\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"status\": \"active\",\n \"class\": [\n {\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/coverage-class\",\n \"code\": \"plan\"\n }\n ]\n },\n \"value\": \"Medicare Part A\"\n }\n ],\n \"payor\": [\n {\n \"reference\": \"Organization/crd221-demo-payer-complete-prefetch\"\n }\n ]\n },\n \"search\": {\n \"mode\": \"match\"\n }\n }\n ]\n },\n \"devices\": null,\n \"medications\": null,\n \"practitionerRoles\": null,\n \"organizations\": null,\n \"practitioners\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Practitioner/crd221-demo-practitioner-orderer\",\n \"resource\": {\n \"resourceType\": \"Practitioner\",\n \"id\": \"crd221-demo-practitioner-orderer\",\n \"meta\": {\n \"profile\": [\n \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner\"\n ]\n },\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1122334455\"\n }\n ],\n \"address\": [\n {\n \"use\": \"home\",\n \"type\": \"both\",\n \"state\": \"NY\",\n \"city\": \"Buffalo\",\n \"postalCode\": \"14210\",\n \"line\": [\n \"840 Seneca St\"\n ]\n }\n ],\n \"telecom\": [\n {\n \"system\": \"phone\",\n \"value\": \"716-873-1557\"\n },\n {\n \"system\": \"email\",\n \"value\": \"jane.betty@myhospital.com\"\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Doe\",\n \"given\": [\n \"Jane\",\n \"Betty\"\n ],\n \"prefix\": [\n \"Dr.\"\n ]\n }\n ],\n \"qualification\": [\n {\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0360\",\n \"code\": \"MD\",\n \"display\": \"Doctor of Medicine\"\n }\n ],\n \"text\": \"Doctor of Medicine\"\n },\n \"period\": {\n \"start\": \"1995\"\n },\n \"issuer\": {\n \"display\": \"Example University\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Practitioner/crd221-demo-practitioner-performer\",\n \"resource\": {\n \"resourceType\": \"Practitioner\",\n \"id\": \"crd221-demo-practitioner-performer\",\n \"meta\": {\n \"profile\": [\n \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner\"\n ]\n },\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1122334455\"\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Doe\",\n \"given\": [\n \"Bob\"\n ],\n \"prefix\": [\n \"Dr.\"\n ]\n }\n ],\n \"qualification\": [\n {\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0360\",\n \"code\": \"MD\",\n \"display\": \"Doctor of Medicine\"\n }\n ],\n \"text\": \"Doctor of Medicine\"\n },\n \"period\": {\n \"start\": \"1995\"\n },\n \"issuer\": {\n \"display\": \"Example University\"\n }\n }\n ]\n }\n }\n ]\n },\n \"locations\": null\n }\n }"
35
+ },
36
+ {
37
+ "name": "order_sign_request_bodies",
38
+ "title": "Request body or bodies for invoking the `order-sign` hook",
39
+ "type": "textarea",
40
+ "value": "[\n {\n \"hookInstance\": \"d1577c69-dfbe-77ad-ba6d-3e05e953b2ea\",\n \"fhirServer\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir\",\n \"hook\": \"order-sign\",\n \"fhirAuthorization\": {\n \"access_token\": \"SAMPLE_TOKEN\",\n \"token_type\": \"Bearer\",\n \"expires_in\": 300,\n \"scope\": \"user/AllergyIntolerance.rs user/CarePlan.rs user/CareTeam.rs user/Condition.rs user/Device.rs user/DiagnosticReport.rs user/DocumentReference.rs user/Encounter.rs user/Goal.rs user/Immunization.rs user/Location.rs user/Medication.rs user/MedicationRequest.rs user/Observation.rs user/Organization.rs user/Patient.rs user/Practitioner.rs user/PractitionerRole.rs user/Procedure.rs user/Provenance.rs\",\n \"subject\": \"cds-service4\"\n },\n \"context\": {\n \"userId\": \"Practitioner/crd221-demo-practitioner-orderer\",\n \"patientId\": \"crd221-demo-patient\",\n \"encounterId\": \"crd221-demo-encounter-no-performer\",\n \"draftOrders\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/DeviceRequest/crd221-demo-devicerequest-different-orderer-vs-performer\",\n \"resource\": {\n \"resourceType\": \"DeviceRequest\",\n \"id\": \"crd221-demo-devicerequest-different-orderer-vs-performer\",\n \"identifier\": [\n {\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0203\",\n \"code\": \"PLAC\"\n }\n ]\n },\n \"value\": \"f105372f-bbef-442c-ad7a-708fee7f8c93\"\n }\n ],\n \"status\": \"draft\",\n \"intent\": \"original-order\",\n \"codeCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"https://bluebutton.cms.gov/resources/codesystem/hcpcs\",\n \"code\": \"E0250\",\n \"display\": \"Hospital bed fixed height with any type of side rails, mattress\"\n }\n ]\n },\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"authoredOn\": \"2023-01-01T00:00:00Z\",\n \"requester\": {\n \"reference\": \"Practitioner/crd221-demo-practitioner-orderer\"\n },\n \"performer\": {\n \"reference\": \"Practitioner/crd221-demo-practitioner-performer\"\n }\n }\n }\n ]\n }\n },\n \"extension\": {\n \"davinci-crd.configuration\": {\n \"alt-drug\": true\n },\n \"davinci-crd.requestedVersion\": \"2.2\"\n },\n \"prefetch\": {\n \"patient\": {\n \"resourceType\": \"Patient\",\n \"id\": \"crd221-demo-patient\",\n \"gender\": \"male\",\n \"birthDate\": \"2015-02-23\",\n \"address\": [\n {\n \"use\": \"home\",\n \"type\": \"both\",\n \"state\": \"NY\",\n \"city\": \"Buffalo\",\n \"postalCode\": \"14210\",\n \"line\": [\n \"202 Burlington Road\"\n ]\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Oster\",\n \"given\": [\n \"William\",\n \"Hale\",\n \"Oster\"\n ]\n }\n ],\n \"telecom\": [\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555-5555\",\n \"use\": \"home\",\n \"rank\": 1\n },\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555 5613\",\n \"use\": \"work\",\n \"rank\": 2\n },\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555 8834\",\n \"use\": \"old\",\n \"period\": {\n \"end\": \"2014\"\n }\n }\n ],\n \"identifier\": [\n {\n \"use\": \"usual\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0203\",\n \"code\": \"MR\"\n }\n ],\n \"text\": \"Medical Record Number\"\n },\n \"system\": \"http://hl7.org/fhir/sid/us-medicare\",\n \"value\": \"0M34355006FW\"\n }\n ]\n },\n \"encounter\": {\n \"resourceType\": \"Encounter\",\n \"id\": \"crd221-demo-encounter-no-performer\",\n \"status\": \"in-progress\",\n \"class\": {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n \"code\": \"AMB\",\n \"display\": \"ambulatory\"\n },\n \"type\": [\n {\n \"coding\": [\n {\n \"system\": \"http://www.ama-assn.org/go/cpt\",\n \"code\": \"99211\"\n }\n ],\n \"text\": \"Office Visit\"\n }\n ],\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n }\n },\n \"coverage\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"searchset\",\n \"total\": 1,\n \"link\": [\n {\n \"relation\": \"self\",\n \"url\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Coverage?patient=crd221-demo-patient\"\n }\n ],\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Coverage/crd221-demo-coverage-complete-prefetch\",\n \"resource\": {\n \"resourceType\": \"Coverage\",\n \"id\": \"crd221-demo-coverage-complete-prefetch\",\n \"subscriberId\": \"10A3D58WH456\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/subscriber-relationship\",\n \"code\": \"self\"\n }\n ]\n },\n \"beneficiary\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"status\": \"active\",\n \"class\": [\n {\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/coverage-class\",\n \"code\": \"plan\"\n }\n ]\n },\n \"value\": \"Medicare Part A\"\n }\n ],\n \"payor\": [\n {\n \"reference\": \"Organization/crd221-demo-payer-complete-prefetch\"\n }\n ]\n },\n \"search\": {\n \"mode\": \"match\"\n }\n }\n ]\n },\n \"devices\": null,\n \"medications\": null,\n \"practitionerRoles\": null,\n \"organizations\": null,\n \"practitioners\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Practitioner/crd221-demo-practitioner-orderer\",\n \"resource\": {\n \"resourceType\": \"Practitioner\",\n \"id\": \"crd221-demo-practitioner-orderer\",\n \"meta\": {\n \"profile\": [\n \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner\"\n ]\n },\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1122334455\"\n }\n ],\n \"address\": [\n {\n \"use\": \"home\",\n \"type\": \"both\",\n \"state\": \"NY\",\n \"city\": \"Buffalo\",\n \"postalCode\": \"14210\",\n \"line\": [\n \"840 Seneca St\"\n ]\n }\n ],\n \"telecom\": [\n {\n \"system\": \"phone\",\n \"value\": \"716-873-1557\"\n },\n {\n \"system\": \"email\",\n \"value\": \"jane.betty@myhospital.com\"\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Doe\",\n \"given\": [\n \"Jane\",\n \"Betty\"\n ],\n \"prefix\": [\n \"Dr.\"\n ]\n }\n ],\n \"qualification\": [\n {\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0360\",\n \"code\": \"MD\",\n \"display\": \"Doctor of Medicine\"\n }\n ],\n \"text\": \"Doctor of Medicine\"\n },\n \"period\": {\n \"start\": \"1995\"\n },\n \"issuer\": {\n \"display\": \"Example University\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Practitioner/crd221-demo-practitioner-performer\",\n \"resource\": {\n \"resourceType\": \"Practitioner\",\n \"id\": \"crd221-demo-practitioner-performer\",\n \"meta\": {\n \"profile\": [\n \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner\"\n ]\n },\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1122334455\"\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Doe\",\n \"given\": [\n \"Bob\"\n ],\n \"prefix\": [\n \"Dr.\"\n ]\n }\n ],\n \"qualification\": [\n {\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0360\",\n \"code\": \"MD\",\n \"display\": \"Doctor of Medicine\"\n }\n ],\n \"text\": \"Doctor of Medicine\"\n },\n \"period\": {\n \"start\": \"1995\"\n },\n \"issuer\": {\n \"display\": \"Example University\"\n }\n }\n ]\n }\n }\n ]\n },\n \"locations\": null\n }\n },\n {\n \"hookInstance\": \"d1577c69-dfbe-77a1-ba6d-3e05e953b2ea\",\n \"fhirServer\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir\",\n \"hook\": \"order-sign\",\n \"fhirAuthorization\": {\n \"access_token\": \"SAMPLE_TOKEN\",\n \"token_type\": \"Bearer\",\n \"expires_in\": 300,\n \"scope\": \"user/AllergyIntolerance.rs user/CarePlan.rs user/CareTeam.rs user/Condition.rs user/Device.rs user/DiagnosticReport.rs user/DocumentReference.rs user/Encounter.rs user/Goal.rs user/Immunization.rs user/Location.rs user/Medication.rs user/MedicationRequest.rs user/Observation.rs user/Organization.rs user/Patient.rs user/Practitioner.rs user/PractitionerRole.rs user/Procedure.rs user/Provenance.rs\",\n \"subject\": \"cds-service4\"\n },\n \"context\": {\n \"userId\": \"Practitioner/crd221-demo-practitioner-orderer\",\n \"patientId\": \"crd221-demo-patient\",\n \"encounterId\": \"crd221-demo-encounter-no-performer\",\n \"draftOrders\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/ServiceRequest/crd221-demo-servicerequest-no-orderer\",\n \"resource\": {\n \"resourceType\": \"ServiceRequest\",\n \"id\": \"crd221-demo-servicerequest-no-orderer\",\n \"identifier\": [\n {\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0203\",\n \"code\": \"PLAC\"\n }\n ]\n },\n \"value\": \"11ddab7e-1488-4848-b3d5-512d2f1e3f28\"\n }\n ],\n \"status\": \"draft\",\n \"intent\": \"order\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"https://bluebutton.cms.gov/resources/codesystem/hcpcs\",\n \"code\": \"G0180\",\n \"display\": \"Medicare-covered home health services under a home health plan of care\"\n }\n ]\n },\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"authoredOn\": \"2017-10-04\",\n \"requester\": {\n \"display\": \"Smythe Juliette, MD\"\n },\n \"performer\": [\n {\n \"reference\": \"Practitioner/crd221-demo-practitioner-performer\"\n }\n ]\n }\n },\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/CommunicationRequest/crd221-demo-communicationrequest\",\n \"resource\": {\n \"resourceType\": \"CommunicationRequest\",\n \"id\": \"crd221-demo-communicationrequest\",\n \"status\": \"draft\",\n \"basedOn\" : [\n {\n \"display\" : \"EligibilityRequest\"\n }\n ],\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"payload\": [\n {\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/5.0/StructureDefinition/extension-CommunicationRequest.payload.content\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"65752-8\",\n \"display\": \"Liver Pathology biopsy report\"\n }\n ]\n }\n }\n ],\n \"contentString\": \"Liver pathology biopsy report\"\n }\n ],\n \"authoredOn\": \"2017-10-04\",\n \"requester\": {\n \"reference\": \"Practitioner/crd221-demo-practitioner-orderer\"\n }\n }\n }\n ]\n }\n },\n \"extension\": {\n \"davinci-crd.configuration\": {\n \"alt-drug\": true,\n \"coverage\": true,\n \"dtr-clin\": true,\n \"max-cards\": 10\n },\n \"davinci-crd.requestedVersion\": \"2.2\"\n },\n \"prefetch\": {\n \"patient\": {\n \"resourceType\": \"Patient\",\n \"id\": \"crd221-demo-patient\",\n \"gender\": \"male\",\n \"birthDate\": \"2015-02-23\",\n \"address\": [\n {\n \"use\": \"home\",\n \"type\": \"both\",\n \"state\": \"NY\",\n \"city\": \"Buffalo\",\n \"postalCode\": \"14210\",\n \"line\": [\n \"202 Burlington Road\"\n ]\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Oster\",\n \"given\": [\n \"William\",\n \"Hale\",\n \"Oster\"\n ]\n }\n ],\n \"telecom\": [\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555-5555\",\n \"use\": \"home\",\n \"rank\": 1\n },\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555 5613\",\n \"use\": \"work\",\n \"rank\": 2\n },\n {\n \"system\": \"phone\",\n \"value\": \"(781) 555 8834\",\n \"use\": \"old\",\n \"period\": {\n \"end\": \"2014\"\n }\n }\n ],\n \"identifier\": [\n {\n \"use\": \"usual\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0203\",\n \"code\": \"MR\"\n }\n ],\n \"text\": \"Medical Record Number\"\n },\n \"system\": \"http://hl7.org/fhir/sid/us-medicare\",\n \"value\": \"0M34355006FW\"\n }\n ]\n },\n \"encounter\": {\n \"resourceType\": \"Encounter\",\n \"id\": \"crd221-demo-encounter-no-performer\",\n \"status\": \"in-progress\",\n \"class\": {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v3-ActCode\",\n \"code\": \"AMB\",\n \"display\": \"ambulatory\"\n },\n \"type\": [\n {\n \"coding\": [\n {\n \"system\": \"http://www.ama-assn.org/go/cpt\",\n \"code\": \"99211\"\n }\n ],\n \"text\": \"Office Visit\"\n }\n ],\n \"subject\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n }\n },\n \"coverage\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"searchset\",\n \"total\": 1,\n \"link\": [\n {\n \"relation\": \"self\",\n \"url\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Coverage?patient=crd221-demo-patient\"\n }\n ],\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Coverage/crd221-demo-coverage-complete-prefetch\",\n \"resource\": {\n \"resourceType\": \"Coverage\",\n \"id\": \"crd221-demo-coverage-complete-prefetch\",\n \"subscriberId\": \"10A3D58WH456\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/subscriber-relationship\",\n \"code\": \"self\"\n }\n ]\n },\n \"beneficiary\": {\n \"reference\": \"Patient/crd221-demo-patient\"\n },\n \"status\": \"active\",\n \"class\": [\n {\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/coverage-class\",\n \"code\": \"plan\"\n }\n ]\n },\n \"value\": \"Medicare Part A\"\n }\n ],\n \"payor\": [\n {\n \"reference\": \"Organization/crd221-demo-payer-complete-prefetch\"\n }\n ]\n },\n \"search\": {\n \"mode\": \"match\"\n }\n }\n ]\n },\n \"devices\": null,\n \"medications\": null,\n \"practitionerRoles\": null,\n \"organizations\": null,\n \"practitioners\": {\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Practitioner/crd221-demo-practitioner-orderer\",\n \"resource\": {\n \"resourceType\": \"Practitioner\",\n \"id\": \"crd221-demo-practitioner-orderer\",\n \"meta\": {\n \"profile\": [\n \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner\"\n ]\n },\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1122334455\"\n }\n ],\n \"address\": [\n {\n \"use\": \"home\",\n \"type\": \"both\",\n \"state\": \"NY\",\n \"city\": \"Buffalo\",\n \"postalCode\": \"14210\",\n \"line\": [\n \"840 Seneca St\"\n ]\n }\n ],\n \"telecom\": [\n {\n \"system\": \"phone\",\n \"value\": \"716-873-1557\"\n },\n {\n \"system\": \"email\",\n \"value\": \"jane.betty@myhospital.com\"\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Doe\",\n \"given\": [\n \"Jane\",\n \"Betty\"\n ],\n \"prefix\": [\n \"Dr.\"\n ]\n }\n ],\n \"qualification\": [\n {\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0360\",\n \"code\": \"MD\",\n \"display\": \"Doctor of Medicine\"\n }\n ],\n \"text\": \"Doctor of Medicine\"\n },\n \"period\": {\n \"start\": \"1995\"\n },\n \"issuer\": {\n \"display\": \"Example University\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Practitioner/crd221-demo-practitioner-performer\",\n \"resource\": {\n \"resourceType\": \"Practitioner\",\n \"id\": \"crd221-demo-practitioner-performer\",\n \"meta\": {\n \"profile\": [\n \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner\"\n ]\n },\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1122334455\"\n }\n ],\n \"name\": [\n {\n \"use\": \"official\",\n \"family\": \"Doe\",\n \"given\": [\n \"Bob\"\n ],\n \"prefix\": [\n \"Dr.\"\n ]\n }\n ],\n \"qualification\": [\n {\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/v2-0360\",\n \"code\": \"MD\",\n \"display\": \"Doctor of Medicine\"\n }\n ],\n \"text\": \"Doctor of Medicine\"\n },\n \"period\": {\n \"start\": \"1995\"\n },\n \"issuer\": {\n \"display\": \"Example University\"\n }\n }\n ]\n }\n }\n ]\n },\n \"locations\": null\n }\n }\n]"
41
+ },
42
+ {
43
+ "name": "mock_ehr_bundle",
44
+ "title": "Mock EHR Data",
45
+ "type": "textarea",
46
+ "value": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"collection\",\n \"entry\": [\n {\n \"resource\": {\n \"resourceType\": \"Organization\",\n \"id\": \"crd221-demo-payer-complete-prefetch\",\n \"identifier\": [\n {\n \"system\": \"http://hl7.org/fhir/sid/us-npi\",\n \"value\": \"1234567893\"\n }\n ],\n \"active\": true,\n \"name\": \"Inferno Simulated Payer (complete standard prefetch)\"\n }\n },\n {\n \"fullUrl\": \"<%= Inferno::Application['base_url'] %>/custom/crd_server_v221/fhir/Location/crd221-demo-location-building\",\n \"resource\": {\n \"resourceType\": \"Location\",\n \"id\": \"crd221-demo-location-building\",\n \"status\": \"active\",\n \"name\": \"Building A\",\n \"address\": {\n \"use\": \"work\",\n \"line\": [\n \"Galapagosweg 91, Building A\"\n ],\n \"city\": \"San Francisco\",\n \"state\": \"CA\",\n \"postalCode\": \"94107\",\n \"country\": \"US\"\n },\n \"physicalType\": {\n \"coding\": [\n {\n \"system\": \"http://terminology.hl7.org/CodeSystem/location-physical-type\",\n \"code\": \"bu\",\n \"display\": \"Building\"\n }\n ]\n },\n \"managingOrganization\": {\n \"reference\": \"Organization/crd221-demo-org-performer\"\n }\n }\n }\n ]\n}"
47
+ }
48
+ ]
49
+ }
@@ -0,0 +1,26 @@
1
+ module DaVinciCRDTestKit
2
+ module CrossHookHelper
3
+ def find_completeness_tests # rubocop:disable Metrics/CyclomaticComplexity
4
+ # minimal error checking - want it to bomb if this search logic fails
5
+ hooks_group = self.class.parent.parent.parent.groups.find do |group|
6
+ group.id.to_s.include?('crd_v221_client_hooks')
7
+ end
8
+ completeness_tests = hooks_group.groups.map do |group|
9
+ group.groups.flat_map(&:tests).find do |test|
10
+ test.id.to_s.include?('crd_v221_hook_request_prefetch_complete')
11
+ end
12
+ end
13
+
14
+ cross_hooks_interaction_group = self.class.parent.parent.groups.find do |group|
15
+ group.id.to_s.include?('crd_v221_client_cross_hook_interaction')
16
+ end
17
+ cross_hooks_completeness_test =
18
+ cross_hooks_interaction_group.groups.flat_map(&:tests).find do |test|
19
+ test.id.to_s.include?('crd_v221_hook_request_prefetch_complete')
20
+ end
21
+ completeness_tests << cross_hooks_completeness_test
22
+
23
+ completeness_tests.compact
24
+ end
25
+ end
26
+ end
@@ -18,17 +18,17 @@ module DaVinciCRDTestKit
18
18
 
19
19
  def parsed_user_input
20
20
  if custom_response_template.blank?
21
- error_response('No custom template provided for custom Inferno CRD response',
22
- code: 500,
23
- outcome_code: 'processing')
21
+ hook_error_response('No custom template provided for custom Inferno CRD response',
22
+ code: 500,
23
+ outcome_code: 'processing')
24
24
  nil
25
25
  else
26
26
  JSON.parse(custom_response_template)
27
27
  end
28
28
  rescue JSON::ParserError
29
- error_response('Invalid template provided for custom Inferno CRD response: invalid JSON',
30
- code: 500,
31
- outcome_code: 'processing')
29
+ hook_error_response('Invalid template provided for custom Inferno CRD response: invalid JSON',
30
+ code: 500,
31
+ outcome_code: 'processing')
32
32
  nil
33
33
  end
34
34
 
@@ -45,7 +45,7 @@ module DaVinciCRDTestKit
45
45
 
46
46
  hook_response
47
47
  rescue FhirpathServiceError => e
48
- error_response(
48
+ hook_error_response(
49
49
  'FHIRPath service error while generating custom response. ' \
50
50
  'Check the FHIRPath expressions and data in your response template and hook request. ' \
51
51
  "Details: #{e.message}",
@@ -258,7 +258,10 @@ module DaVinciCRDTestKit
258
258
  request_body['fhirAuthorization'].present? &&
259
259
  request_body['fhirAuthorization']['access_token'].present?
260
260
  Faraday.new(url: request_body['fhirServer'], request: { open_timeout: 10 },
261
- headers: data_request_headers)
261
+ headers: data_request_headers) do |f|
262
+ f.request :url_encoded
263
+ f.use FaradayMiddleware::FollowRedirects
264
+ end
262
265
  end
263
266
  end
264
267
 
@@ -1,6 +1,7 @@
1
1
  require_relative 'gather_response_generation_data'
2
2
  require_relative 'mock_service_response'
3
3
  require_relative 'custom_service_response'
4
+ require_relative 'scenario_service_response'
4
5
  require_relative '../../cross_suite/cards_identification'
5
6
  require_relative '../../cross_suite/tags'
6
7
 
@@ -10,6 +11,7 @@ module DaVinciCRDTestKit
10
11
  include DaVinciCRDTestKit::GatherResponseGenerationData
11
12
  include DaVinciCRDTestKit::CustomServiceResponse
12
13
  include DaVinciCRDTestKit::CardsIdentification
14
+ include DaVinciCRDTestKit::ScenarioServiceResponse
13
15
 
14
16
  AVAILABLE_HOOKS = [
15
17
  'appointment-book',
@@ -77,34 +79,34 @@ module DaVinciCRDTestKit
77
79
 
78
80
  def make_response
79
81
  if requested_hook.blank?
80
- error_response("No hook requested - populate the 'hook' element in the request.",
81
- code: 400,
82
- outcome_code: 'value')
82
+ hook_error_response("No hook requested - populate the 'hook' element in the request.",
83
+ code: 400,
84
+ outcome_code: 'value')
83
85
  elsif invoked_hook != requested_hook
84
- error_response("#{request.env['PATH_INFO']} serves the #{invoked_hook}, but the client " \
85
- "requested the #{requested_hook} hook.",
86
- code: 400,
87
- outcome_code: 'value')
86
+ hook_error_response("#{request.env['PATH_INFO']} serves the #{invoked_hook}, but the client " \
87
+ "requested the #{requested_hook} hook.",
88
+ code: 400,
89
+ outcome_code: 'value')
88
90
  elsif wrong_hook_for_test?
89
- error_response("Hook '#{requested_hook}' is not being tested in the current session. " \
90
- "This session is currently testing the '#{tested_hook}' hook.",
91
- code: 422,
92
- outcome_code: 'value')
91
+ hook_error_response("Hook '#{requested_hook}' is not being tested in the current session. " \
92
+ "This session is currently testing the '#{tested_hook}' hook.",
93
+ code: 422,
94
+ outcome_code: 'value')
93
95
  elsif hook_instance_already_used?
94
- error_response(
96
+ hook_error_response(
95
97
  "Invalid Request: Hook instance `#{request_body['hookInstance']}` has already been used in this session.",
96
98
  outcome_code: 'value'
97
99
  )
98
100
  elsif AVAILABLE_HOOKS.include?(requested_hook)
99
101
  process_valid_hook
100
102
  else
101
- error_response("Invalid Request: hook `#{requested_hook}` is not supported by this server.",
102
- outcome_code: 'value')
103
+ hook_error_response("Invalid Request: hook `#{requested_hook}` is not supported by this server.",
104
+ outcome_code: 'value')
103
105
  end
104
106
  rescue StandardError => e
105
- error_response("Inferno failed to generate a response: #{e.message} at #{e.backtrace.first}",
106
- code: 500,
107
- outcome_code: 'exception')
107
+ hook_error_response("Inferno failed to generate a response: #{e.message} at #{e.backtrace.first}",
108
+ code: 500,
109
+ outcome_code: 'exception')
108
110
  end
109
111
 
110
112
  def process_valid_hook
@@ -130,13 +132,17 @@ module DaVinciCRDTestKit
130
132
  end
131
133
 
132
134
  def hook_response
133
- if response_approach == 'custom'
135
+ if unknown_content_group?
136
+ build_unknown_content_hook_response
137
+ elsif self_pay_group? || long_running_group?
138
+ build_coverage_information_hook_response
139
+ elsif response_approach == 'custom'
134
140
  build_custom_hook_response
135
141
  else
136
142
  build_mock_hook_response
137
143
  end
138
144
  rescue StandardError => e
139
- error_response("Inferno failed to generate a response: #{e.message} at #{e.backtrace.first}", code: 500)
145
+ hook_error_response("Inferno failed to generate a response: #{e.message} at #{e.backtrace.first}", code: 500)
140
146
  nil
141
147
  end
142
148
 
@@ -165,29 +171,40 @@ module DaVinciCRDTestKit
165
171
  end
166
172
 
167
173
  def tags
168
- return [LONG_RUNNING_GROUP_TAG] if long_running_group?
169
- return [DUPLICATED_HOOK_INSTANCE_TAG] if hook_instance_already_used?
174
+ tags =
175
+ if hook_instance_already_used?
176
+ [DUPLICATED_HOOK_INSTANCE_TAG]
177
+ elsif invoked_hook != requested_hook ||
178
+ wrong_hook_for_test? ||
179
+ !AVAILABLE_HOOKS.include?(requested_hook)
180
+ []
181
+ else
182
+ [hook_instance_tag, hook_tag, interaction_group_tag, cross_hook_tag]
183
+ end
170
184
 
171
- return [] if invoked_hook != requested_hook ||
172
- wrong_hook_for_test? ||
173
- !AVAILABLE_HOOKS.include?(requested_hook)
185
+ # the self-pay scenario checks for the absence of requests, so even invalid requests must carry the group tag
186
+ tags << interaction_group_tag if self_pay_group?
174
187
 
175
- [hook_instance_tag, hook_or_group_tag].compact
188
+ tags.uniq.compact
176
189
  end
177
190
 
178
191
  def hook_instance_tag
179
192
  TagMethods.hook_instance_tag(request_body['hookInstance'])
180
193
  end
181
194
 
182
- def hook_or_group_tag
183
- if test.config.options[:crd_test_group].present?
184
- test.config.options[:crd_test_group]
185
- elsif name.present?
186
- DaVinciCRDTestKit.const_get(:"#{name.upcase}_TAG")
187
- end
195
+ def hook_tag
196
+ DaVinciCRDTestKit.const_get(:"#{name.upcase}_TAG") if name.present?
197
+ end
198
+
199
+ def interaction_group_tag
200
+ test.config.options[:crd_interaction_group].presence
201
+ end
202
+
203
+ def cross_hook_tag
204
+ CROSS_HOOK_ANALYSIS_TAG if test.config.options[:include_in_cross_hook_analysis]
188
205
  end
189
206
 
190
- def error_response(error_message, code: 400, outcome_code: 'invalid')
207
+ def hook_error_response(error_message, code: 400, outcome_code: 'invalid')
191
208
  response.status = code
192
209
  response.body = error_operation_outcome(outcome_code, error_message).to_json
193
210
  response.headers.merge!({ 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' })
@@ -214,11 +231,19 @@ module DaVinciCRDTestKit
214
231
  end
215
232
 
216
233
  # -----------------------
217
- # Long Running Group handling
234
+ # Scenario Group handling
218
235
  # -----------------------
219
236
 
220
237
  def long_running_group?
221
- test.config.options[:crd_test_group] == LONG_RUNNING_GROUP_TAG
238
+ test.config.options[:crd_interaction_group] == LONG_RUNNING_GROUP_TAG
239
+ end
240
+
241
+ def unknown_content_group?
242
+ test.config.options[:crd_interaction_group] == UNKNOWN_CONTENT_GROUP_TAG
243
+ end
244
+
245
+ def self_pay_group?
246
+ test.config.options[:crd_interaction_group] == SELF_PAY_GROUP_TAG
222
247
  end
223
248
 
224
249
  def long_running_pause_time
@@ -227,12 +252,12 @@ module DaVinciCRDTestKit
227
252
  &.dig('value').to_i
228
253
  end
229
254
 
230
- # end the wait immediately after the long-running request returns
231
- # pause here because update_result runs before response generation
255
+ # end the wait immediately after the scenario request returns
256
+ # pause for long-running requests here because update_result runs before response generation
232
257
  def update_result
233
- return unless long_running_group?
258
+ return unless long_running_group? || unknown_content_group? || self_pay_group?
234
259
 
235
- sleep long_running_pause_time
260
+ sleep long_running_pause_time if long_running_group?
236
261
  results_repo.update(result.id, result: 'pass', result_message: '')
237
262
  end
238
263
  end
@@ -156,8 +156,16 @@ module DaVinciCRDTestKit
156
156
  }[requested_hook]
157
157
  end
158
158
 
159
+ # @private
160
+ def connection
161
+ @connection ||= Faraday.new do |f|
162
+ f.request :url_encoded
163
+ f.use FaradayMiddleware::FollowRedirects
164
+ end
165
+ end
166
+
159
167
  def make_resource_request(uri, access_token)
160
- response = Faraday.get(uri, nil, { 'Authorization' => "Bearer #{access_token}" })
168
+ response = connection.get(uri, nil, { 'Authorization' => "Bearer #{access_token}" })
161
169
  return unless response.status == 200
162
170
 
163
171
  resource = FHIR.from_contents(response.body)
@@ -284,22 +292,33 @@ module DaVinciCRDTestKit
284
292
 
285
293
  def identify_resources_for_system_actions
286
294
  update_resource = context[resource_to_update_field_name]
287
- prefetch_id = prefetch_key_for_system_actions
295
+ prefetch_id_options = prefetch_key_options_for_system_actions
296
+ prefetched_resource = find_prefetched_resource(request_body, prefetch_id_options)
288
297
 
289
298
  if update_resource.is_a? Hash
290
299
  FHIR.from_contents(update_resource.to_json)
291
- elsif prefetch_id.present? && request_body['prefetch'] && request_body['prefetch'][prefetch_id]
292
- FHIR.from_contents(request_body['prefetch'][prefetch_id].to_json)
300
+ elsif prefetched_resource.present?
301
+ FHIR.from_contents(prefetched_resource.to_json)
293
302
  elsif update_resource.present?
294
303
  get_context_resource(update_resource)
295
304
  end
296
305
  end
297
306
 
298
- def prefetch_key_for_system_actions
307
+ def find_prefetched_resource(request_body, key_options)
308
+ prefetch = request_body['prefetch']
309
+ return if prefetch.blank?
310
+
311
+ found_key = key_options&.find { |key| prefetch[key].present? }
312
+ return unless found_key.present?
313
+
314
+ prefetch[found_key]
315
+ end
316
+
317
+ def prefetch_key_options_for_system_actions
299
318
  if requested_hook.starts_with?('encounter')
300
- 'encounter'
319
+ ['encounter', 'enc'] # handle subset service
301
320
  elsif requested_hook == 'order-dispatch'
302
- 'order'
321
+ ['order'] # v2.2.1 order-dispatch handled elsewhere
303
322
  end
304
323
  end
305
324
 
@@ -0,0 +1,54 @@
1
+ module DaVinciCRDTestKit
2
+ # Serve fixed coverage information responses for hook requests made during scenario groups
3
+ module ScenarioServiceResponse
4
+ # coverage information carrying content that clients are not expected to recognize
5
+ def build_unknown_content_hook_response
6
+ response_body = build_coverage_information_hook_response
7
+ add_unknown_action_element(response_body) if response_body['systemActions'].present?
8
+ add_unknown_extension(response_body)
9
+ response_body
10
+ end
11
+
12
+ def build_coverage_information_hook_response
13
+ response_body = { 'cards' => [] }
14
+ system_actions = coverage_information_system_actions
15
+
16
+ if system_actions.present?
17
+ response_body['systemActions'] = system_actions
18
+ else
19
+ create_missing_coverage_information_message
20
+ end
21
+
22
+ response_body
23
+ end
24
+
25
+ def coverage_information_system_actions
26
+ return if context.blank? || patient_coverage.blank?
27
+
28
+ create_coverage_extension_system_actions(patient_coverage.id)
29
+ end
30
+
31
+ def random_element_name
32
+ ('a'..'z').to_a.sample(16).join
33
+ end
34
+
35
+ # an element that is not part of the CDS Hooks action definition
36
+ def add_unknown_action_element(response_body)
37
+ element_name = random_element_name
38
+ response_body['systemActions'].each { |action| action[element_name] = random_element_name }
39
+ end
40
+
41
+ # a CDS Hooks extension whose key is not defined by CRD or CDS Hooks
42
+ def add_unknown_extension(response_body)
43
+ response_body['extension'] = { random_element_name => random_element_name }
44
+ end
45
+
46
+ def create_missing_coverage_information_message
47
+ Inferno::Repositories::Messages.new.create(
48
+ result_id: result.id,
49
+ type: 'warning',
50
+ message: %(Unable to return a coverage information system action for the #{requested_hook} hook)
51
+ )
52
+ end
53
+ end
54
+ end
@@ -1,38 +1,19 @@
1
1
  module DaVinciCRDTestKit
2
2
  module TaggedRequestLoadHelper
3
- ALL_HOOKS = [
4
- APPOINTMENT_BOOK_TAG,
5
- ENCOUNTER_START_TAG,
6
- ENCOUNTER_DISCHARGE_TAG,
7
- ORDER_DISPATCH_TAG,
8
- ORDER_SELECT_TAG,
9
- ORDER_SIGN_TAG
10
- ].freeze
11
-
12
- def hook_name
13
- config.options[:hook_name]
3
+ def load_requests_for_cross_hook_analysis
4
+ load_tagged_requests(CROSS_HOOK_ANALYSIS_TAG)
14
5
  end
15
6
 
16
- def crd_test_group
17
- config.options[:crd_test_group]
7
+ def load_interaction_group_requests
8
+ load_tagged_requests(config.options[:crd_interaction_group])
18
9
  end
19
10
 
20
- def tags_to_load(hook = hook_name)
21
- crd_test_group.present? ? [crd_test_group] : [hook]
22
- end
23
-
24
- def load_hook_requests
25
- load_tagged_requests(*tags_to_load)
11
+ def hook_name
12
+ config.options[:hook_name]
26
13
  end
27
14
 
28
- def requests_to_analyze
29
- if hook_name.present?
30
- load_tagged_requests(*tags_to_load)
31
- else
32
- ALL_HOOKS.each_with_object([]) do |hook, request_list|
33
- request_list.concat(load_tagged_requests(*tags_to_load(hook)))
34
- end
35
- end
15
+ def crd_interaction_group
16
+ config.options[:crd_interaction_group]
36
17
  end
37
18
  end
38
19
  end
@@ -41,30 +41,17 @@ module DaVinciCRDTestKit
41
41
  @request_number = index + 1
42
42
 
43
43
  jku = JSON.parse(token_header)['jku']
44
- if jku.present?
45
- get(jku)
46
-
47
- if response[:status] != 200
48
- add_message('error', %(
49
- #{request_number}Unexpected response status: expected 200, but received
50
- #{response[:status]}))
51
- next
44
+ jwks =
45
+ if jku.present?
46
+ fetch_jwks(jku, crd_jwks_json)
47
+ else
48
+ skip_if cds_jwk_set.blank?,
49
+ %(#{request_number}JWK Set must be inputted if the client's JWK Set is not available via a URL
50
+ identified by the jku header field)
51
+
52
+ parse_or_fetch_jwks(cds_jwk_set, crd_jwks_json)
52
53
  end
53
-
54
- @request_number = index + 1
55
- jwks = json_parse(response[:body])
56
- next if jwks.blank?
57
-
58
- crd_jwks_json << response[:body]
59
-
60
- jwks = JSON.parse(response[:body])
61
- else
62
- skip_if cds_jwk_set.blank?,
63
- %(#{request_number}JWK Set must be inputted if the client's JWK Set is not available via a URL
64
- identified by the jku header field)
65
-
66
- jwks = JSON.parse(cds_jwk_set)
67
- end
54
+ next if jwks.blank?
68
55
 
69
56
  keys = jwks['keys']
70
57
  unless keys.is_a?(Array)
@@ -104,6 +91,31 @@ module DaVinciCRDTestKit
104
91
 
105
92
  no_error_validation('Retrieving JWKS failed.')
106
93
  end
94
+
95
+ def fetch_jwks(uri, crd_jwks_json)
96
+ get(uri)
97
+
98
+ if response[:status] != 200
99
+ add_message('error', %(
100
+ #{request_number}Unexpected response status: expected 200, but received
101
+ #{response[:status]}))
102
+ return false
103
+ end
104
+
105
+ jwks = json_parse(response[:body])
106
+ return false if jwks.blank?
107
+
108
+ crd_jwks_json << response[:body]
109
+ jwks
110
+ end
111
+
112
+ def parse_or_fetch_jwks(jwk_set_input, crd_jwks_json)
113
+ if jwk_set_input.match?(%r{\Ahttps?://})
114
+ fetch_jwks(jwk_set_input, crd_jwks_json)
115
+ else
116
+ json_parse(jwk_set_input)
117
+ end
118
+ end
107
119
  end
108
120
  end
109
121
  end