Module: USCoreTestKit::GranularScopeChecker

Included in:
USCoreV610::ConditionPatientAbatementDateGranularScopeTest, USCoreV610::ConditionPatientAssertedDateGranularScopeTest, USCoreV610::ConditionPatientCategoryClinicalStatusGranularScopeTest, USCoreV610::ConditionPatientCategoryEncounterGranularScopeTest, USCoreV610::ConditionPatientCategoryGranularScopeTest, USCoreV610::ConditionPatientClinicalStatusGranularScopeTest, USCoreV610::ConditionPatientCodeGranularScopeTest, USCoreV610::ConditionPatientGranularScopeTest, USCoreV610::ConditionPatientOnsetDateGranularScopeTest, USCoreV610::ConditionPatientRecordedDateGranularScopeTest, USCoreV610::DiagnosticReportPatientCategoryDateGranularScopeTest, USCoreV610::DiagnosticReportPatientCategoryGranularScopeTest, USCoreV610::DiagnosticReportPatientCodeDateGranularScopeTest, USCoreV610::DiagnosticReportPatientCodeGranularScopeTest, USCoreV610::DiagnosticReportPatientGranularScopeTest, USCoreV610::DiagnosticReportPatientStatusGranularScopeTest, USCoreV610::DocumentReferenceIdGranularScopeTest, USCoreV610::DocumentReferencePatientCategoryDateGranularScopeTest, USCoreV610::DocumentReferencePatientCategoryGranularScopeTest, USCoreV610::DocumentReferencePatientGranularScopeTest, USCoreV610::DocumentReferencePatientStatusGranularScopeTest, USCoreV610::DocumentReferencePatientTypeGranularScopeTest, USCoreV610::DocumentReferencePatientTypePeriodGranularScopeTest, USCoreV610::ObservationPatientCategoryDateGranularScopeTest, USCoreV610::ObservationPatientCategoryGranularScopeTest, USCoreV610::ObservationPatientCategoryStatusGranularScopeTest, USCoreV610::ObservationPatientCodeDateGranularScopeTest, USCoreV610::ObservationPatientCodeGranularScopeTest, USCoreV610::ServiceRequestIdGranularScopeTest, USCoreV610::ServiceRequestPatientCategoryAuthoredGranularScopeTest, USCoreV610::ServiceRequestPatientCategoryGranularScopeTest, USCoreV610::ServiceRequestPatientCodeAuthoredGranularScopeTest, USCoreV610::ServiceRequestPatientCodeGranularScopeTest, USCoreV610::ServiceRequestPatientGranularScopeTest, USCoreV610::ServiceRequestPatientStatusGranularScopeTest, USCoreV700_BALLOT::ConditionPatientAbatementDateGranularScopeTest, USCoreV700_BALLOT::ConditionPatientAssertedDateGranularScopeTest, USCoreV700_BALLOT::ConditionPatientCategoryClinicalStatusGranularScopeTest, USCoreV700_BALLOT::ConditionPatientCategoryEncounterGranularScopeTest, USCoreV700_BALLOT::ConditionPatientCategoryGranularScopeTest, USCoreV700_BALLOT::ConditionPatientClinicalStatusGranularScopeTest, USCoreV700_BALLOT::ConditionPatientCodeGranularScopeTest, USCoreV700_BALLOT::ConditionPatientGranularScopeTest, USCoreV700_BALLOT::ConditionPatientOnsetDateGranularScopeTest, USCoreV700_BALLOT::ConditionPatientRecordedDateGranularScopeTest, USCoreV700_BALLOT::DiagnosticReportPatientCategoryDateGranularScopeTest, USCoreV700_BALLOT::DiagnosticReportPatientCategoryGranularScopeTest, USCoreV700_BALLOT::DiagnosticReportPatientCodeDateGranularScopeTest, USCoreV700_BALLOT::DiagnosticReportPatientCodeGranularScopeTest, USCoreV700_BALLOT::DiagnosticReportPatientGranularScopeTest, USCoreV700_BALLOT::DiagnosticReportPatientStatusGranularScopeTest, USCoreV700_BALLOT::DocumentReferenceIdGranularScopeTest, USCoreV700_BALLOT::DocumentReferencePatientCategoryDateGranularScopeTest, USCoreV700_BALLOT::DocumentReferencePatientCategoryGranularScopeTest, USCoreV700_BALLOT::DocumentReferencePatientGranularScopeTest, USCoreV700_BALLOT::DocumentReferencePatientStatusGranularScopeTest, USCoreV700_BALLOT::DocumentReferencePatientTypeGranularScopeTest, USCoreV700_BALLOT::DocumentReferencePatientTypePeriodGranularScopeTest, USCoreV700_BALLOT::ObservationPatientCategoryDateGranularScopeTest, USCoreV700_BALLOT::ObservationPatientCategoryGranularScopeTest, USCoreV700_BALLOT::ObservationPatientCategoryStatusGranularScopeTest, USCoreV700_BALLOT::ObservationPatientCodeDateGranularScopeTest, USCoreV700_BALLOT::ObservationPatientCodeGranularScopeTest, USCoreV700_BALLOT::ServiceRequestIdGranularScopeTest, USCoreV700_BALLOT::ServiceRequestPatientCategoryAuthoredGranularScopeTest, USCoreV700_BALLOT::ServiceRequestPatientCategoryGranularScopeTest, USCoreV700_BALLOT::ServiceRequestPatientCodeAuthoredGranularScopeTest, USCoreV700_BALLOT::ServiceRequestPatientCodeGranularScopeTest, USCoreV700_BALLOT::ServiceRequestPatientGranularScopeTest, USCoreV700_BALLOT::ServiceRequestPatientStatusGranularScopeTest
Defined in:
lib/us_core_test_kit/granular_scope_checker.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(klass) ⇒ Object



3
4
5
6
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 3

def self.included(klass)
  klass.input(:received_scopes)
  klass.attr_accessor :previous_requests
end

Instance Method Details

#expected_resource_ids(resources) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 118

def expected_resource_ids(resources)
  resources
    .select do |resource|
      granular_scope_search_params.any? do |param|
        resource_matches_param?(resource, param[:name], param[:value])
      end
    end
    .map(&:id)
end

#granular_scope_search_paramsObject



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 82

def granular_scope_search_params
  @granular_scope_search_params ||=
    granular_scopes.map do |scope|
      _, granular_scope = scope.split('?')
      name, value = granular_scope.split('=')

      {
        name:,
        value:
      }
    end
end

#granular_scopesObject



72
73
74
75
76
77
78
79
80
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 72

def granular_scopes
  @granular_scopes ||=
    received_scopes
      .split(' ')
      .select do |scope|
        (scope.start_with?("patient/#{resource_type}") || scope.start_with?("user/#{resource_type}")) &&
          scope.include?('?')
      end
end

#load_previous_requestsObject



95
96
97
98
99
100
101
102
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 95

def load_previous_requests
  search_params_as_hash = search_param_names.each_with_object({}) do |name, hash|
    hash[name] = nil
  end
  @previous_requests ||=
    load_tagged_requests(search_params_tag(search_params_as_hash))
      .sort_by { |request| request.index }
end

#mismatched_resource_ids(resources) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 128

def mismatched_resource_ids(resources)
  resources
    .reject do |resource|
      granular_scope_search_params.any? do |param|
        resource_matches_param?(resource, param[:name], param[:value])
      end
    end
    .map(&:id)
end

#previous_request_resourcesObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 50

def previous_request_resources
  first_request = previous_requests.first
  next_page_url = nil
  hash = Hash.new { |hash, key| hash[key] = [] }
  previous_requests.each_with_object(hash) do |request, request_resource_hash|
    request_resources =
      if request.status == 200
        request.resource.entry.map(&:resource).select { |resource| resource.resourceType == resource_type }
      else
        []
      end

    first_request = request if request.url != next_page_url

    request_resource_hash[first_request].concat(request_resources)

    next if request.resource&.resourceType != 'Bundle'

    next_page_url = request.resource&.link&.find { |link| link.relation == 'next' }&.url
  end
end

#previous_resources(params) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 104

def previous_resources(params)
  previous_requests(params)
    .flat_map do |request|
      resource = request.resource
      if resource.is_a?(FHIR::Bundle)
        resource.entry&.map(&:resource)
      else
        resource
      end
    end
    .compact
    .select { |resource| resource.resourceType == resource_type }
end

#run_scope_check_testObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/us_core_test_kit/granular_scope_checker.rb', line 8

def run_scope_check_test
  assert granular_scopes.present?, "No granular scopes were received for #{resource_type} resources"

  load_previous_requests

  skip_if previous_requests.blank?,
          "No #{resource_type} searches with search params #{search_param_names.join(' & ')} found"

  previous_request_resources.each do |previous_request, all_previous_resources|
    params = previous_request.query_parameters
    search_method = previous_request.verb.to_sym
    fhir_search(resource_type, params:, search_method:)

    found_resources =
      if request.status != 200
        []
      else
        fetch_all_bundled_resources
      end

    mismatched_ids = mismatched_resource_ids(found_resources)

    assert mismatched_ids.empty?,
           'Resources with the following ids were received even though they do not match the ' \
           "granted granular scopes: #{mismatched_ids.join(', ')}"

    found_ids = found_resources.map(&:id)
    previous_ids = expected_resource_ids(all_previous_resources)
    missing_ids = previous_ids - found_ids

    assert missing_ids.empty?,
           'Resources with the following ids were received when using resource-level scopes, ' \
           "but not when using granular scopes: #{missing_ids.join(', ')}"

    unexpected_ids = found_ids - previous_ids

    assert unexpected_ids.empty?,
           'Resources with the following ids were received when using granular scopes, ' \
           "but not when using resource-level scopes: #{unexpected_ids.join(', ')}"
  end
end