Class: DaVinciCRDTestKit::HookRequestEndpoint
- Inherits:
-
Inferno::DSL::SuiteEndpoint
- Object
- Inferno::DSL::SuiteEndpoint
- DaVinciCRDTestKit::HookRequestEndpoint
- Includes:
- CardsIdentification, CustomServiceResponse, GatherResponseGenerationData, MockServiceResponse
- Defined in:
- lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb
Constant Summary collapse
- AVAILABLE_HOOKS =
[ 'appointment-book', 'encounter-start', 'encounter-discharge', 'order-select', 'order-sign', 'order-dispatch' ].freeze
Constants included from CardsIdentification
CardsIdentification::ADDITIONAL_ORDERS_EXPECTED_RESOURCE_TYPES, CardsIdentification::ADDITIONAL_ORDERS_RESPONSE_TYPE, CardsIdentification::COVERAGE_INFORMATION_RESPONSE_TYPE, CardsIdentification::COVERAGE_INFO_CONFIGURATION_CODE, CardsIdentification::COVERAGE_INFO_EXPECTED_RESOURCE_TYPES, CardsIdentification::COVERAGE_INFO_EXT_URL, CardsIdentification::CREATE_OR_UPDATE_COVERAGE_RESPONSE_TYPE, CardsIdentification::EXTERNAL_REFERENCE_RESPONSE_TYPE, CardsIdentification::FORM_COMPLETION_RESPONSE_TYPE, CardsIdentification::INSTRUCTIONS_RESPONSE_TYPE, CardsIdentification::LAUNCH_SMART_APP_RESPONSE_TYPE, CardsIdentification::PROPOSE_ALTERNATIVE_REQUEST_EXPECTED_RESOURCE_TYPES, CardsIdentification::PROPOSE_ALTERNATIVE_REQUEST_RESPONSE_TYPE
Constants included from ProfilesAndResourceTypes
ProfilesAndResourceTypes::ORDER_OR_ENCOUNTER_RESOURCE_CLASSES, ProfilesAndResourceTypes::ORDER_RESOURCE_CLASSES, ProfilesAndResourceTypes::ORDER_RESOURCE_TYPES
Constants included from RequestsLogicalModelValidation
RequestsLogicalModelValidation::CRD_CDS_HOOK_REQUEST_MODEL_URL, RequestsLogicalModelValidation::PERFORMER_ALLOWED_RESOURCE_TYPES, RequestsLogicalModelValidation::USER_ID_ALLOWED_RESOURCE_TYPES
Constants included from GatherResponseGenerationData
GatherResponseGenerationData::REFERENCES_TO_READ_BY_RESOURCE_TYPE
Constants included from FhirpathOnCDSRequest
FhirpathOnCDSRequest::SUPPORTED_POST_RESOLVE_FUNCTIONS, FhirpathOnCDSRequest::TODAY_EXPRESSION_PATTERN
Instance Method Summary collapse
- #apply_hook_configuration(response_body) ⇒ Object
- #coverage_info_disabled? ⇒ Boolean
- #error_operation_outcome(code, text) ⇒ Object
- #error_response(error_message, code: 400, outcome_code: 'invalid') ⇒ Object
- #hook_instance_already_used? ⇒ Boolean
- #hook_instance_tag ⇒ Object
- #hook_or_group_tag ⇒ Object
- #hook_response ⇒ Object
- #ig_version ⇒ Object
-
#invoked_hook ⇒ Object
from the url.
- #iss ⇒ Object
-
#long_running_group? ⇒ Boolean
———————– Long Running Group handling ———————–.
- #long_running_pause_time ⇒ Object
- #make_response ⇒ Object
- #name ⇒ Object
- #process_valid_hook ⇒ Object
-
#request_body ⇒ Object
JSON round-trip normalizes the Hanami params object to a plain string-keyed Hash.
-
#requested_hook ⇒ Object
from the hook body.
- #requested_version ⇒ Object
- #response_approach ⇒ Object
- #tags ⇒ Object
- #test_run_identifier ⇒ Object
-
#tested_hook ⇒ Object
from the waiting test.
- #token ⇒ Object
-
#update_result ⇒ Object
end the wait immediately after the long-running request returns pause here because update_result runs before response generation.
- #wrong_hook_for_test? ⇒ Boolean
Methods included from CardsIdentification
#additional_orders_response_type?, #cache_sorted_cards, #check_action_type, #coverage_info_card_type?, #coverage_info_configuration_disabled?, #coverage_info_content, #coverage_info_response?, #coverage_info_system_action_type?, #coverage_information_response_type?, #create_or_update_coverage_action_response_type?, #create_or_update_coverage_card_response_type?, #create_questionnaire_action_response_type?, #disable_coverage_info_configuration!, #extension_url, #external_reference_response_type?, #extract_coverage_information_extensions, #form_completion_action_response_type?, #form_completion_card_response_type?, #form_completion_task_questionnaire?, #hook_instances_from_requests, #identify_action_type, #identify_card_type, #initialize_sorted_cards_hash, #instructions_response_type?, #launch_smart_app_response_type?, #list_card_types_in_requests, #propose_alternative_request_response_type?, #sort_card_types_from_request, #sorted_cards_cached?, #sorted_cards_from_cache, #sorted_cards_from_requests
Methods included from HookRequestFieldValidation
#hook_request_context_check, #hook_request_optional_fields_check, #hook_request_prefetch_check, #hook_request_required_fields_check, #json_parse, #no_error_validation
Methods included from ProfilesAndResourceTypes
#structure_definition_map, #structure_definition_map_v201, #structure_definition_map_v221
Methods included from ServerBaseURLs
#client_fhir_base_url, #fhir_url, #instance_url, #search_url
Methods included from BaseURLs
#inferno_base_url, #resume_fail_url, #resume_pass_url
Methods included from RequestsLogicalModelValidation
#validate_request_against_logical_model
Methods included from LogicalModelsOverrideHelper
#allowed_resource_type?, #check_appointment_conformance, #check_order_like_resource_conformance, #check_resource_conformance_to_coverage_profile, #check_resource_conformance_to_order_or_encounter_profile, #check_resource_conformance_to_order_profile, #check_resource_conformance_to_questionnaire_task_profile, #check_resource_type_and_validate, #local_reference?, #manually_check_appointment_validation_errors, #parse_action_resource, #primary_performer_type?, #referenced_resource_present_in_bundle?, #reject_resource_issues, #resolved_participant_patient_slice_issue?, #resolved_participant_primary_performer_slice_issue?
Methods included from SuggestionActionsValidation
#action_fields_validation, #action_resource_type_check, #actions_check
Methods included from CustomServiceResponse
#add_first_default, #build_custom_hook_response, #create_instantiated_action_from_target, #custom_response_template, #default_coverage_information_assertion_id, #default_coverage_information_coverage, #default_coverage_information_date, #default_coverage_information_elements, #default_extension_name, #defaults_extension?, #define_extension, #enabled_on_service?, #evaluate_inclusion_for_request, #filter_and_separate_defaults, #filter_response, #finalize_card_list, #get_defaults_extension_value, #get_extension_value, #get_object_inclusion_criteria_extension_value, #get_object_resource_selection_criteria_extension_value, #get_target_resources_for_request, #instantiate_action_using_targets, #instantiate_actions, #instantiate_an_action, #merge_action_resource_into_target, #object_has_inclusion_criteria?, #object_has_resource_selection_criteria?, #object_included_for_this_request?, #object_is_a_default?, #parsed_user_input, #remove_defaults_extension, #remove_extension, #remove_inclusion_criteria, #remove_resource_selection_criteria, #update_card, #update_suggestion
Methods included from GatherResponseGenerationData
#add_location_to_hash, #add_prefetch_resource_to_resource_hash, #analyzed_resources, #data_request_headers, #entry_has_required_details?, #execute_request, #extract_bundle_entries, #fetch_reference, #fhir_server_connection, #find_coverage_for_request, #find_references_to_read, #gather_appointment_book_data, #gather_data_for_request, #gather_encounter_discharge_data, #gather_encounter_start_data, #gather_order_dispatch_data, #gather_order_select_data, #gather_order_sign_data, #get_literal_reference_values, #hook_instance_data_fetch_tag, #normalize_reference, #persist_query_request, #prefetched_coverage, #prefetched_coverage_resource, #prefetched_location_bundle, #prefetched_locations_and_parents_hash, #prefetched_resources, #query_for_coverages, #read_and_analyze, #request_additional_fhir_data, #request_coverage, #request_coverage_payer, #request_parent_locations, #resource_has_required_details?
Methods included from ReplaceTokens
#replace_tokens, #replace_tokens_in_string
Methods included from FhirpathOnCDSRequest
#execute_fhirpath_on_cds_request
Methods included from MockServiceResponse
#add_basic_cards, #add_coverage_cards, #add_coverage_cards?, #add_coverage_extension, #add_order_hook_cards, #build_mock_hook_response, #context, #coverage_information_required?, #coverage_information_required_hooks, #create_alternate_request_card, #create_card_response, #create_cards_and_system_actions, #create_companions_prerequisites_card, #create_coverage_extension_system_actions, #create_coverage_resource, #create_form_completion_card, #create_or_update_coverage, #create_system_actions, #create_warning_messages, #current_time, #extract_prefetched_coverage, #find_entry_in_prefetch_bundle, #find_one_prefetched_order_dispatch_order, #find_prefetched_order_dispatch_orders, #format_missing_response_types, #get_context_resource, #get_missing_response_types, #get_patient_coverage, #identify_alternate_order_resource, #identify_resources_for_system_actions, #load_json_file, #make_resource_request, #missing_response_type_filter, #patient_coverage, #payer_reference_from_coverage, #prefetch_key_for_system_actions, #resource_to_update_field_name, #resource_type_to_update, #selected_response_types, #update_one_card_info, #update_service_request, #update_specific_hook_card_info
Instance Method Details
#apply_hook_configuration(response_body) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 139 def apply_hook_configuration(response_body) return response_body unless response_body.present? && coverage_info_disabled? cards = response_body['cards'] response_body['cards'] = cards.reject { |card| coverage_info_card_type?(card) } if cards.is_a?(Array) system_actions = response_body['systemActions'] if system_actions.is_a?(Array) response_body['systemActions'] = system_actions.reject { |action| coverage_info_system_action_type?(action) } end response_body end |
#coverage_info_disabled? ⇒ Boolean
153 154 155 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 153 def coverage_info_disabled? request_body.dig('extension', 'davinci-crd.configuration', COVERAGE_INFO_CONFIGURATION_CODE) == false end |
#error_operation_outcome(code, text) ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 191 def error_operation_outcome(code, text) { resourceType: 'OperationOutcome', issue: [ { severity: 'error', code:, details: { text: } } ] } end |
#error_response(error_message, code: 400, outcome_code: 'invalid') ⇒ Object
184 185 186 187 188 189 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 184 def error_response(, code: 400, outcome_code: 'invalid') response.status = code response.body = error_operation_outcome(outcome_code, ).to_json response.headers.merge!({ 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }) response.format = :json end |
#hook_instance_already_used? ⇒ Boolean
157 158 159 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 157 def hook_instance_already_used? requests_repo.tagged_requests(test_run.test_session_id, [hook_instance_tag]).present? end |
#hook_instance_tag ⇒ Object
172 173 174 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 172 def hook_instance_tag TagMethods.hook_instance_tag(request_body['hookInstance']) end |
#hook_or_group_tag ⇒ Object
176 177 178 179 180 181 182 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 176 def hook_or_group_tag if test.config.[:crd_test_group].present? test.config.[:crd_test_group] else DaVinciCRDTestKit.const_get(:"#{name.upcase}_TAG") end end |
#hook_response ⇒ Object
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 128 def hook_response if response_approach == 'custom' build_custom_hook_response else build_mock_hook_response end rescue StandardError => e error_response("Inferno failed to generate a response: #{e.} at #{e.backtrace.first}", code: 500) nil end |
#ig_version ⇒ Object
23 24 25 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 23 def ig_version @ig_version ||= requested_version || request.env['PATH_INFO'].match(/(v\d+)/)&.[](1) || 'v201' end |
#invoked_hook ⇒ Object
from the url
65 66 67 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 65 def invoked_hook @invoked_hook ||= request.env['PATH_INFO'].match(%r{/([^/]+)-(?:service|subset)$})&.[](1) end |
#iss ⇒ Object
45 46 47 48 49 50 51 52 53 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 45 def iss @iss ||= begin payload, = JWT.decode(token, nil, false) payload['iss'] rescue JWT::DecodeError nil end end |
#long_running_group? ⇒ Boolean
Long Running Group handling
214 215 216 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 214 def long_running_group? test.config.[:crd_test_group] == LONG_RUNNING_GROUP_TAG end |
#long_running_pause_time ⇒ Object
218 219 220 221 222 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 218 def long_running_pause_time JSON.parse(result.input_json) .find { |input| input['name'].include?('long_running_pause_time') } &.dig('value').to_i end |
#make_response ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 78 def make_response if invoked_hook != requested_hook error_response("#{request.env['PATH_INFO']} serves the #{invoked_hook}, but the client " \ "requested the #{requested_hook} hook.", code: 400, outcome_code: 'value') elsif wrong_hook_for_test? error_response("Hook '#{requested_hook}' is not being tested in the current session. " \ "This session is currently testing the '#{tested_hook}' hook.", code: 422, outcome_code: 'value') elsif hook_instance_already_used? error_response( "Invalid Request: Hook instance `#{request_body['hookInstance']}` has already been used in this session.", outcome_code: 'value' ) elsif AVAILABLE_HOOKS.include?(requested_hook) process_valid_hook else error_response("Invalid Request: hook `#{requested_hook}` is not supported by this server.", outcome_code: 'value') end rescue StandardError => e error_response("Inferno failed to generate a response: #{e.} at #{e.backtrace.first}", code: 500, outcome_code: 'exception') end |
#name ⇒ Object
206 207 208 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 206 def name requested_hook.gsub('-', '_') end |
#process_valid_hook ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 106 def process_valid_hook if ig_version == 'v201' send(:"gather_#{requested_hook.gsub('-', '_')}_data") request_coverage elsif ig_version == 'v221' request_additional_fhir_data end response_body = apply_hook_configuration(hook_response) return unless response_body.present? response.body = response_body.to_json response.headers.merge!({ 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }) response.status = 200 response.format = :json end |
#request_body ⇒ Object
JSON round-trip normalizes the Hanami params object to a plain string-keyed Hash
28 29 30 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 28 def request_body @request_body ||= JSON.parse(request.params.to_json) end |
#requested_hook ⇒ Object
from the hook body
60 61 62 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 60 def requested_hook @requested_hook ||= request_body['hook'] end |
#requested_version ⇒ Object
32 33 34 35 36 37 38 39 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 32 def requested_version requested = request_body.dig('extension', 'davinci-crd.requestedVersion').to_s if requested == '2.2' 'v221' elsif requested == '2.0' 'v201' end end |
#response_approach ⇒ Object
122 123 124 125 126 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 122 def response_approach JSON.parse(result.input_json) .find { |input| input['name'].ends_with?('_response_approach') } &.dig('value') end |
#tags ⇒ Object
161 162 163 164 165 166 167 168 169 170 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 161 def return [LONG_RUNNING_GROUP_TAG] if long_running_group? return [DUPLICATED_HOOK_INSTANCE_TAG] if hook_instance_already_used? return [] if invoked_hook != requested_hook || wrong_hook_for_test? || !AVAILABLE_HOOKS.include?(requested_hook) [hook_instance_tag, hook_or_group_tag] end |
#test_run_identifier ⇒ Object
41 42 43 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 41 def test_run_identifier iss end |
#tested_hook ⇒ Object
from the waiting test
70 71 72 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 70 def tested_hook @tested_hook ||= test.config.[:hook_name] end |
#token ⇒ Object
55 56 57 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 55 def token @token ||= request.headers['authorization']&.delete_prefix('Bearer ') end |
#update_result ⇒ Object
end the wait immediately after the long-running request returns pause here because update_result runs before response generation
226 227 228 229 230 231 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 226 def update_result return unless long_running_group? sleep long_running_pause_time results_repo.update(result.id, result: 'pass', result_message: '') end |
#wrong_hook_for_test? ⇒ Boolean
74 75 76 |
# File 'lib/davinci_crd_test_kit/client/endpoints/hook_request_endpoint.rb', line 74 def wrong_hook_for_test? tested_hook.present? && tested_hook != ANY_HOOK_TAG && requested_hook != tested_hook end |