Class: DaVinciCRDTestKit::V221::ClientCoverageInfoUpdateTest

Inherits:
Inferno::Test
  • Object
show all
Includes:
CardsIdentification, TaggedRequestLoadHelper
Defined in:
lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb

Constant Summary

Constants included from TaggedRequestLoadHelper

TaggedRequestLoadHelper::ALL_HOOKS

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

Instance Method Summary collapse

Methods included from TaggedRequestLoadHelper

#crd_test_group, #hook_name, #load_hook_requests, #requests_to_analyze, #tags_to_load

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

Instance Method Details

#check_for_stored_coverage_information_extension(resource_details) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 138

def check_for_stored_coverage_information_extension(resource_details)
  fhir_read resource_details[:resource_type], resource_details[:target_id]
  unless resource.present? && resource.resourceType == resource_details[:resource_type]
    add_message('error', "#{error_prefix(resource_details)}Unable to read target resource.")
    return
  end

  stored_extensions = resource.extension.select { |ext| ext.url == COVERAGE_INFO_EXT_URL }
  if stored_extensions.blank?
    add_message('error', "#{error_prefix(resource_details)}coverage-information extension(s) not stored.")
    return
  end

  difference_string = coverage_info_extension_differences(
    resource_details[:coverage_information_extensions],
    stored_extensions
  )
  return unless difference_string.present?

  add_message('error', "#{error_prefix(resource_details)}#{difference_string}.")
end

#compare_coverage_info_sub_extensions(expected, actual) ⇒ Object



173
174
175
176
177
178
179
180
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 173

def compare_coverage_info_sub_extensions(expected, actual)
  expected_by_url = expected.extension.group_by(&:url)
  actual_by_url = actual.extension.group_by(&:url)

  (expected_by_url.keys | actual_by_url.keys).filter_map do |url|
    compare_url_sub_extensions(url, expected_by_url, actual_by_url)
  end
end

#compare_url_sub_extensions(url, expected_by_url, actual_by_url) ⇒ Object



182
183
184
185
186
187
188
189
190
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 182

def compare_url_sub_extensions(url, expected_by_url, actual_by_url)
  if !expected_by_url.key?(url)
    "unexpected sub-extension '#{url}' found in stored resource"
  elsif !actual_by_url.key?(url)
    "sub-extension '#{url}' missing from stored resource"
  elsif normalized_extensions(expected_by_url[url]) != normalized_extensions(actual_by_url[url])
    "sub-extension '#{url}' value differs"
  end
end

#coverage_info_extension_differences(expected, actual) ⇒ Object

Raises:

  • (ArgumentError)


160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 160

def coverage_info_extension_differences(expected, actual)
  raise ArgumentError, 'expected must contain exactly one coverage-information extension' if expected.size != 1

  if expected.size != actual.size
    return "Expected #{expected.size} coverage-information extension(s), found #{actual.size}."
  end

  differences = compare_coverage_info_sub_extensions(expected[0], actual[0])
  return unless differences.present?

  "Stored coverage-information extension does not match what was sent by the server: #{differences.join(', ')}"
end

#error_prefix(resource_details) ⇒ Object



205
206
207
208
209
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 205

def error_prefix(resource_details)
  "(Request #{resource_details[:request_index] + 1}) " \
    "coverage-info systemAction #{resource_details[:action_index] + 1} " \
    "targeting resource #{resource_details[:resource_type]}/#{resource_details[:target_id]}: "
end

#extract_coverage_information_details(action, action_index, request_index) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 108

def extract_coverage_information_details(action, action_index, request_index)
  {
    request_index:,
    action_index:,
    resource_type: action.dig('resource', 'resourceType'),
    target_id: action.dig('resource', 'id'),
    coverage_information_extensions: FHIR.from_contents(action['resource'].to_json).extension.select do |ext|
                                       ext.url == COVERAGE_INFO_EXT_URL
                                     end
  }
end

#extract_supported_resource_types(capability_statement) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 120

def extract_supported_resource_types(capability_statement)
  return [] unless capability_statement.rest.is_a?(Array)

  capability_statement.rest.select { |rest| rest.mode == 'server' }.flat_map do |rest|
    next [] unless rest.resource.is_a?(Array)

    rest.resource.select do |resource|
      supports_read?(resource)
    end.flat_map(&:type).compact
  end.uniq
end

#find_coverage_info_actions_in_response(request, request_index) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 95

def find_coverage_info_actions_in_response(request, request_index)
  response = JSON.parse(request.response_body)
  return [] unless response.is_a?(Hash) && response.key?('systemActions')

  response['systemActions'].map.with_index do |action, action_index|
    if coverage_information_response_type?(action)
      extract_coverage_information_details(action, action_index, request_index)
    end
  end.compact
rescue JSON::ParserError
  [] # no responses to check, error registered elsewhere
end

#find_coverage_info_responses(requests) ⇒ Object

important information to record:

  • relative resource reference (resource type + id)

  • coverage-information extension

  • position (response index + systemAction index)



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 70

def find_coverage_info_responses(requests)
  all_responses = requests.flat_map.with_index do |request, request_index|
    find_coverage_info_actions_in_response(request, request_index)
  end

  all_responses.group_by { |resource_details| [resource_details[:resource_type], resource_details[:target_id]] }
    .filter_map do |(_type, _id), entries|
      if entries.size > 1
        add_message('info',
                    "#{error_prefix(entries.first)}Multiple coverage-info responses found. Due to the " \
                    'complexity of determining the expected state, this resource will not be verified.')
        next
      end

      if entries.first[:coverage_information_extensions].size > 1
        add_message('info',
                    "#{error_prefix(entries.first)}Multiple coverage-information extensions found. Due to the " \
                    'complexity of determining the expected state, this resource will not be verified.')
        next
      end

      entries.first
    end
end

#normalize_extension(value) ⇒ Object

Recursively sort nested arrays so sub-extension order doesn’t affect equality.



197
198
199
200
201
202
203
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 197

def normalize_extension(value)
  case value
  when Hash  then value.transform_values { |v| normalize_extension(v) }
  when Array then value.map { |item| normalize_extension(item) }.sort_by(&:to_json)
  else value
  end
end

#normalized_extensions(extensions) ⇒ Object



192
193
194
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 192

def normalized_extensions(extensions)
  extensions.map { |e| normalize_extension(e.to_hash) }.sort_by(&:to_json)
end

#supports_read?(resource) ⇒ Boolean

Returns:

  • (Boolean)


132
133
134
135
136
# File 'lib/davinci_crd_test_kit/client/v2.2.1/api/client_coverage_info_update_test.rb', line 132

def supports_read?(resource)
  resource.interaction&.any? do |interaction|
    interaction.code == 'read'
  end
end