Class: DaVinciCRDTestKit::V221::CoverageInformationSystemActionValidationTest

Inherits:
Inferno::Test
  • Object
show all
Includes:
ServerHookHelper, ServerHookRequestValidation, ServerTestHelper, HookRequestResourceResolution
Defined in:
lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb

Constant Summary collapse

COVERAGE_INFO_EXT_URL =
'http://hl7.org/fhir/us/davinci-crd/StructureDefinition/ext-coverage-information'.freeze

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 HookRequestResourceResolution

#appointment_based_on_matches_target?, #appointment_book_service_request, #fallback_source_resource, #find_action_source_resource, #find_appointment_book_resource, #find_draft_orders_resource, #find_resource_by_reference, #find_resource_in_bundle, #find_resource_in_prefetch, #hook_context_resource, #matching_request_for_action, #mock_ehr_bundle_resource, #parse_bundle, #parse_request_body, #reference_parts

Methods included from ServerHookHelper

#discovered_service_id_for_hook, #identify_hook, #target_service_id, #tested_hook_name

Methods included from ServerTestHelper

#parse_json, #verify_at_least_one_test_passes

Methods included from ServerHookRequestValidation

#client_test?, #server_test?

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?

Instance Method Details

#collect_extensions_id(extensions, url, *properties) ⇒ Object



92
93
94
95
96
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 92

def collect_extensions_id(extensions, url, *properties)
  extensions.map do |extension|
    find_extension_value(extension, url, *properties)
  end
end

#coverage_info_system_action_check(coverage_info_system_action) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 152

def coverage_info_system_action_check(coverage_info_system_action)
  type = coverage_info_system_action['type']
  assert type, '`type` field is missing.'
  assert type == 'update', "`type` must be `update`, but was `#{type}`"

  resource = FHIR.from_contents(coverage_info_system_action['resource'].to_json)
  profile_url = structure_definition_map('v221')[resource.resourceType]
  resource_is_valid?(resource:, profile_url:)

  grouped_coverage_info = extract_and_group_coverage_info(resource)
  multiple_extensions_conformance_check(grouped_coverage_info, resource)
  verify_only_coverage_info_changed(coverage_info_system_action)
end

#different_coverage_conformance_error_msg(resource_ref, id_name) ⇒ Object



102
103
104
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 102

def different_coverage_conformance_error_msg(resource_ref, id_name)
  "#{resource_ref}: extensions referencing differing coverage SHALL have distinct #{id_name}."
end

#extract_and_group_coverage_info(resource) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 53

def extract_and_group_coverage_info(resource)
  resource.extension.each_with_object({}) do |extension, grouped_extensions|
    next unless extension.url == COVERAGE_INFO_EXT_URL

    coverage_key = find_extension_value(extension, 'coverage', 'valueReference', 'reference')
    grouped_extensions[coverage_key] ||= []
    grouped_extensions[coverage_key] << extension
  end
end

#find_extension_value(extension, url, *properties) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 42

def find_extension_value(extension, url, *properties)
  found_extension = extension.extension.find { |ext| ext.url == url }
  return nil unless found_extension

  properties.reduce(found_extension) do |current, prop|
    return current unless current.respond_to?(prop)

    current.send(prop)
  end
end

#multiple_extensions_conformance_check(grouped_coverage_info, resource) ⇒ Object

For the same coverage, ensure coverage-assertion-ids and satisfied-pa-ids are the same. For different coverages, ensure coverage-assertion-ids and satisfied-pa-ids are distinct.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 65

def multiple_extensions_conformance_check(grouped_coverage_info, resource)
  resource_ref = "#{resource.resourceType}/#{resource.id}"
  assertion_ids_across_coverages = Set.new
  pa_ids_across_coverages = Set.new

  grouped_coverage_info.each do |coverage, extensions|
    coverage_assertion_ids = collect_extensions_id(extensions, 'coverage-assertion-id', 'valueString').uniq
    satisfied_pa_ids = collect_extensions_id(extensions, 'satisfied-pa-id', 'valueString').uniq.compact
    assert coverage_assertion_ids.length == 1,
           same_coverage_conformance_error_msg(resource_ref, coverage, 'coverage-assertion-ids')

    assert satisfied_pa_ids.length <= 1,
           same_coverage_conformance_error_msg(resource_ref, coverage, 'satisfied-pa-ids')

    assertion_id = coverage_assertion_ids.first
    assert !assertion_ids_across_coverages.include?(assertion_id),
           different_coverage_conformance_error_msg(resource_ref, 'coverage-assertion-ids')
    assertion_ids_across_coverages.add(assertion_id)
    pa_id = satisfied_pa_ids.first
    next unless pa_id

    assert !pa_ids_across_coverages.include?(pa_id),
           different_coverage_conformance_error_msg(resource_ref, 'satisfied-pa-ids')
    pa_ids_across_coverages.add(pa_id)
  end
end

#normalize_value(value) ⇒ Object



106
107
108
109
110
111
112
113
114
115
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 106

def normalize_value(value)
  case value
  when Hash
    value.transform_values { |child| normalize_value(child) }
  when Array
    value.map { |child| normalize_value(child) }.sort_by(&:to_json)
  else
    value
  end
end

#same_coverage_conformance_error_msg(resource_ref, coverage, id_name) ⇒ Object



98
99
100
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 98

def same_coverage_conformance_error_msg(resource_ref, coverage, id_name)
  "#{resource_ref}: extension has multiple repetitions of coverage `#{coverage}` with different #{id_name}."
end

#strip_coverage_info_extensions(resource_hash) ⇒ Object



117
118
119
120
121
122
123
124
125
126
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 117

def strip_coverage_info_extensions(resource_hash)
  normalized_hash = resource_hash.deep_dup
  return normalized_hash unless normalized_hash['extension'].is_a?(Array)

  normalized_hash['extension'] = normalized_hash['extension'].reject do |extension|
    extension['url'] == COVERAGE_INFO_EXT_URL
  end
  normalized_hash.delete('extension') if normalized_hash['extension'].empty?
  normalized_hash
end

#verify_only_coverage_info_changed(action) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/davinci_crd_test_kit/server/v2.2.1/verify_response/coverage_information_system_action_validation_test.rb', line 128

def verify_only_coverage_info_changed(action)
  request = matching_request_for_action(action)
  source_resource = find_action_source_resource(action, request)
  updated_resource_hash = action['resource']
  resource_ref = "#{updated_resource_hash['resourceType']}/#{updated_resource_hash['id']}"
  unless source_resource
    messages << {
      type: 'warning',
      message: 'Inferno could not resolve the original source resource for Coverage Information systemAction ' \
               "targeting #{resource_ref}, so it could not verify that only coverage-information extensions " \
               'were changed.'
    }
    return
  end

  source_resource_hash = source_resource.to_hash

  source_without_coverage_info = normalize_value(strip_coverage_info_extensions(source_resource_hash))
  updated_without_coverage_info = normalize_value(strip_coverage_info_extensions(updated_resource_hash))

  assert source_without_coverage_info == updated_without_coverage_info,
         "#{resource_ref}: resource content changed outside the coverage-information extension."
end