Module: DaVinciPASTestKit::ResponseSelectionUtils

Included in:
ClaimEndpoint
Defined in:
lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb

Overview

Selection of a response from a tester-provided list of candidates. Each candidate is either a bare FHIR Bundle or a plain JSON wrapper object pairing the response Bundle ("bundle") with the selection criteria ("criteria") that the incoming request must meet for that Bundle to be returned. The wrapper is plain JSON rather than FHIR because Bundle resources cannot carry top-level extensions. Candidates are handled as parsed JSON hashes; the inner Bundle is a clean FHIR resource and needs no modification before use. Requires FhirpathUtils and access to result (Inferno::Entities::Result).

Constant Summary collapse

CRITERIA_KEY =
'criteria'.freeze
BUNDLE_KEY =
'bundle'.freeze
REQUEST_RANGE_KEY =
'requestRange'.freeze
FHIRPATH_KEY =
'fhirpath'.freeze

Instance Method Summary collapse

Instance Method Details

#bare_bundle?(entity) ⇒ Boolean


Candidate handling


Returns:

  • (Boolean)


22
23
24
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 22

def bare_bundle?(entity)
  entity.is_a?(Hash) && entity['resourceType'] == 'Bundle'
end

#count_previous_successful_requests(operation) ⇒ Object



62
63
64
65
66
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 62

def count_previous_successful_requests(operation)
  requests_repo = Inferno::Repositories::Requests.new
  previous_requests = requests_repo.requests_for_result(result.id)
  previous_requests.count { |req| req.url.include?(operation) && req.status == 200 }
end

#entity_bundle(entity) ⇒ Object



26
27
28
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 26

def entity_bundle(entity)
  bare_bundle?(entity) ? entity : entity[BUNDLE_KEY]
end

#entity_criteria(entity) ⇒ Object



30
31
32
33
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 30

def entity_criteria(entity)
  criteria = bare_bundle?(entity) ? nil : entity[CRITERIA_KEY]
  criteria.is_a?(Hash) ? criteria : {}
end

#include_entity?(entity, request_fhir_obj, operation) ⇒ Boolean

Returns:

  • (Boolean)


35
36
37
38
39
40
41
42
43
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 35

def include_entity?(entity, request_fhir_obj, operation)
  criteria = entity_criteria(entity)
  return false if criteria[REQUEST_RANGE_KEY].present? &&
                  !request_meets_request_range_criteria?(criteria[REQUEST_RANGE_KEY], operation)
  return false if criteria[FHIRPATH_KEY].present? &&
                  !request_meets_inclusion_criteria?(criteria[FHIRPATH_KEY], request_fhir_obj)

  true
end

#ranges_cover_value?(value, ranges_string) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 68

def ranges_cover_value?(value, ranges_string)
  unless /\A(\d+(-\d+)?,)*\d+(-\d+)?\z/.match?(ranges_string)
    raise ArgumentError,
          "Invalid range string: #{ranges_string.inspect}"
  end

  ranges_string.split(',').any? do |part|
    if part.include?('-')
      low, high = part.split('-').map(&:to_i)
      raise ArgumentError, "Inverted range in: #{part.inspect}" if low > high

      (low..high).cover?(value)
    else
      part.to_i == value
    end
  end
rescue ArgumentError => e
  raise Inferno::Exceptions::TestSuiteImplementationException.new('pas response range criteria', e.message)
end

#request_meets_inclusion_criteria?(expression, request_fhir_obj) ⇒ Boolean


FHIRPath-based selection criteria


Returns:

  • (Boolean)


49
50
51
52
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 49

def request_meets_inclusion_criteria?(expression, request_fhir_obj)
  fhirpath_result = execute_fhirpath(request_fhir_obj, expression)
  interpret_fhirpath_result_as_boolean(fhirpath_result)
end

#request_meets_request_range_criteria?(ranges, operation) ⇒ Boolean


Request index-based selection criteria


Returns:

  • (Boolean)


58
59
60
# File 'lib/davinci_pas_test_kit/cross_suite/response_selection_utils.rb', line 58

def request_meets_request_range_criteria?(ranges, operation)
  ranges_cover_value?(count_previous_successful_requests(operation) + 1, ranges.to_s)
end