Module: BulkDataTestKit::BulkDataExportOperationTests

Instance Method Summary collapse

Instance Method Details

#check_bulk_data_output(export_status_response) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/bulk_data_test_kit/export_operation_tests.rb', line 149

def check_bulk_data_output(export_status_response)
  assert export_status_response.present?, 'Bulk Data Server status response not found'

  assert_valid_json(export_status_response)
  status_output = JSON.parse(export_status_response)['output']
  assert status_output, 'Bulk Data Server status response does not contain output'

  skip_if status_output.empty?, 'Bulk Data Server status response does not contain any data in the output'

  begin
    status_output_json = status_output.to_json
    bulk_download_url = status_output[0]['url']

    [status_output_json, bulk_download_url]
  ensure
    status_output.each do |file|
      %w[type url].each do |key|
        assert file.key?(key), "Output file did not contain \"#{key}\" as required"
      end

      if config.options[:require_absolute_urls_in_output]
        assert file['url'].to_s.match?(%r{\Ahttps?://}),
               "URLs in output file must be absolute, but found `#{file['url']}`."
      end
    end
  end
end

#check_export_supportObject



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
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/bulk_data_test_kit/export_operation_tests.rb', line 15

def check_export_support
  fhir_get_capability_statement(client: :bulk_server)
  assert_response_status([200, 201])

  assert_valid_json(request.response_body)
  capability_statement = FHIR.from_contents(request.response_body)

  warning do
    has_instantiates = capability_statement&.instantiates&.any? do |canonical|
      canonical.match(%r{^http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data(\|\S+)?$})
    end
    assert has_instantiates,
           'Server did not declare conformance to the Bulk Data IG by including ' \
           "'http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data' in " \
           "CapabilityStatement.instantiates element (#{capability_statement&.instantiates})"
  end

  group_resource_capabilities = nil

  capability_statement&.rest&.each do |rest|
    group_resource_capabilities = if resource_type == 'system'
                                    rest
                                  else
                                    rest.resource&.find do |resource|
                                      resource.type == resource_type
                                    end
                                  end
  end

  assert group_resource_capabilities.respond_to?(:operation) && group_resource_capabilities.operation&.any?,
         "Server CapabilityStatement did not declare support for any operations on the #{resource_type} resource"

  has_export_operation = group_resource_capabilities.operation&.any? do |operation|
    name_match = (operation.name == 'export')
    operationDefURL = resource_type == 'system' ? 'export' : "#{resource_type.downcase}-export"

    if name_match && !operation.definition&.match(%r{^http://hl7.org/fhir/uv/bulkdata/OperationDefinition/#{operationDefURL}(\|\S+)?$})
      info("Server CapabilityStatement does not include export operation with definition http://hl7.org/fhir/uv/bulkdata/OperationDefinition/#{operationDefURL}")
    end
    name_match
  end
  warning do
    assert has_export_operation,
           "Server CapabilityStatement did not declare support for an operation named export in the #{resource_type} " \
           'resource (operation.name should be export)'
  end
end

#export_kick_off_successObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/bulk_data_test_kit/export_operation_tests.rb', line 76

def export_kick_off_success
  use_token = !bearer_token.blank?

  url = bulk_export_url.dup
  if resource_type == 'Group'
    skip_if group_id.blank?, 'Group id is blank, skipping test.'
    url = bulk_export_url.gsub('[group_id]', group_id) if resource_type == 'Group'
  end

  perform_export_kick_off_request(use_token:, url:)
  assert_response_status(202)

  polling_url = request.response_header('content-location')&.value
  assert polling_url.present?, 'Export response headers did not include "Content-Location"'

  polling_url
end

#export_status_check_success(status_polling_url) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/bulk_data_test_kit/export_operation_tests.rb', line 94

def export_status_check_success(status_polling_url)
  skip 'Server response did not have Content-Location in header' unless status_polling_url.present?

  timeout = bulk_timeout.to_i

  if !timeout.positive?
    timeout = 180
  elsif timeout > 600
    timeout = 600
  end

  wait_time = 1
  start = Time.now
  used_time = 0

  loop do
    get(status_polling_url, headers: { authorization: "Bearer #{bearer_token}", accept: 'application/json' })

    retry_after_val = request.response_header('retry-after')&.value.to_i

    wait_time = retry_after_val.positive? ? retry_after_val : wait_time *= 2

    used_time = Time.now - start

    total_time_to_next_poll = Time.now - start + wait_time

    break if response[:status] != 202 || total_time_to_next_poll > timeout

    sleep wait_time
  end

  if response[:status] == 202
    skip "Server already used #{used_time} seconds processing this request, " \
        "and next poll is #{wait_time} seconds after. " \
        "The total wait time for next poll is more than #{timeout} seconds time out setting."
  end

  assert_response_status(200)

  assert request.response_header('content-type')&.value&.include?('application/json'),
         'Content-Type not application/json'

  assert_valid_json(response[:body])
  response_body = JSON.parse(response[:body])

  %w[transactionTime request requiresAccessToken output error].each do |key|
    assert response_body.key?(key), "Complete Status response did not contain \"#{key}\" as required"
  end

  requires_access_token = response_body['requiresAccessToken'].to_s.downcase
  status_response = response[:body]

  [requires_access_token, status_response]
end

#rejects_without_authorizationObject



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/bulk_data_test_kit/export_operation_tests.rb', line 63

def rejects_without_authorization
  skip_if bearer_token.blank?, 'Bearer token is not set and thus not required to connect to server.'

  url = bulk_export_url.dup
  if resource_type == 'Group'
    skip_if group_id.blank?, 'Group id is blank, skipping test.'
    url = bulk_export_url.gsub('[group_id]', group_id) if resource_type == 'Group'
  end

  perform_export_kick_off_request(use_token: false, url:)
  assert_response_status([400, 401])
end