From e4f73e58bd383a52945fa9f5c88020f5335f6822 Mon Sep 17 00:00:00 2001 From: Emily Semple <59289146+emichaud998@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:29:17 -0400 Subject: [PATCH] FI-2947: Allow Some /metadata Requests to Fail (#27) * Add input to allow user to select if some metadata requests can fail and still pass the test * Fix issue with get not being protected and update endpoint availability limit description --- .../service_base_url_validate_group.rb | 69 +++++++++++++++++-- .../service_base_url/service_base_url_spec.rb | 54 ++++++++++++++- 2 files changed, 113 insertions(+), 10 deletions(-) diff --git a/lib/service_base_url_test_kit/service_base_url_validate_group.rb b/lib/service_base_url_test_kit/service_base_url_validate_group.rb index 7cea915..0dfe122 100644 --- a/lib/service_base_url_test_kit/service_base_url_validate_group.rb +++ b/lib/service_base_url_test_kit/service_base_url_validate_group.rb @@ -22,11 +22,37 @@ class ServiceBaseURLBundleTestGroup < Inferno::TestGroup input :endpoint_availability_limit, title: 'Endpoint Availability Limit', description: %( - Input a number to cap the number of Endpoints that Inferno will send requests to check for availability. - This can help speed up validation when there are large number of endpoints in the Service Base URL Bundle. + In the case where the Endpoint Availability Success Rate is 'All', input a number to cap the number of + Endpoints that Inferno will send requests to check for availability. This can help speed up validation when + there are large number of endpoints in the Service Base URL Bundle. ), optional: true + input :endpoint_availability_success_rate, + title: 'Endpoint Availability Success Rate', + description: %( + Select an option to choose how many Endpoints have to be available and send back a valid capability + statement for the Endpoint validation test to pass. + ), + type: 'radio', + options: { + list_options: [ + { + label: 'All', + value: 'all' + }, + { + label: 'At Least One', + value: 'at_least_1' + }, + { + label: 'None', + value: 'none' + } + ] + }, + default: 'all' + # @private def find_referenced_org(bundle_resource, endpoint_id) bundle_resource @@ -170,16 +196,45 @@ def find_referenced_endpoint(bundle_resource, endpoint_id_ref) ) end + one_endpoint_valid = false + endpoint_list.each_with_index do |address, index| assert_valid_http_uri(address) - next if endpoint_availability_limit.present? && endpoint_availability_limit.to_i <= index + next if endpoint_availability_success_rate == 'none' || + (endpoint_availability_limit.present? && endpoint_availability_limit.to_i <= index) address = address.delete_suffix('/') - get("#{address}/metadata", client: nil, headers: { Accept: 'application/fhir+json' }) - assert_response_status(200) - assert resource.present?, 'The content received does not appear to be a valid FHIR resource' - assert_resource_type(:capability_statement) + warning do + get("#{address}/metadata", client: nil, headers: { Accept: 'application/fhir+json' }) + end + + if endpoint_availability_success_rate == 'all' + assert response.present?, "Encountered issues while trying to make a request to #{address}/metadata." + assert_response_status(200) + assert resource.present?, 'The content received does not appear to be a valid FHIR resource' + assert_resource_type(:capability_statement) + else + if response.present? + warning do + assert_response_status(200) + assert resource.present?, 'The content received does not appear to be a valid FHIR resource' + assert_resource_type(:capability_statement) + end + end + + if !one_endpoint_valid && response && response[:status] == 200 && resource.present? && + resource.resourceType == 'CapabilityStatement' + one_endpoint_valid = true + end + end + end + + if endpoint_availability_success_rate == 'at_least_1' + assert(one_endpoint_valid, %( + There were no Endpoints that were available and returned a valid Capability Statement in the Service Base + URL Bundle' + )) end end end diff --git a/spec/service_base_url/service_base_url_spec.rb b/spec/service_base_url/service_base_url_spec.rb index 1341871..112f495 100644 --- a/spec/service_base_url/service_base_url_spec.rb +++ b/spec/service_base_url/service_base_url_spec.rb @@ -9,7 +9,8 @@ let(:input) do { - service_base_url_list_url: + service_base_url_list_url:, + endpoint_availability_success_rate: 'all' } end let(:validator_response_success) do @@ -99,7 +100,7 @@ def run(runnable, inputs = {}) .with(query: hash_including({})) .to_return(status: 200, body: validator_response_success.to_json) - result = run(test, service_base_url_bundle: bundle_resource.to_json) + result = run(test, service_base_url_bundle: bundle_resource.to_json, endpoint_availability_success_rate: 'all') expect(result.result).to eq('pass'), %( Expected a valid inputted service base url Bundle to pass @@ -181,13 +182,60 @@ def run(runnable, inputs = {}) .with(query: hash_including({})) .to_return(status: 200, body: validator_response_success.to_json) - result = run(test, service_base_url_list_url:, endpoint_availability_limit: 2) + result = run(test, service_base_url_list_url:, endpoint_availability_success_rate: 'all', + endpoint_availability_limit: 2) expect(result.result).to eq('pass') expect(capability_statement_request_success).to have_been_made.times(2) expect(validation_request).to have_been_made.times(7) end + it 'passes if at least 1 endpoint is available when success rate input is set to at least 1' do + bundle_resource.entry[4].resource.address = "#{base_url}/fake/address/3" + bundle_resource.entry[0].resource.address = "#{base_url}/fake/address/1" + + stub_request(:get, service_base_url_list_url) + .to_return(status: 200, body: bundle_resource.to_json, headers: {}) + + fake_uri_template = Addressable::Template.new "#{base_url}/fake/address/{id}/metadata" + capability_statement_request_fail = stub_request(:get, fake_uri_template) + .to_return(status: 404, body: '', headers: {}) + + uri_template = Addressable::Template.new "#{base_url}/{id}/metadata" + capability_statement_request_success = stub_request(:get, uri_template) + .to_return(status: 200, body: capability_statement.to_json, headers: {}) + + validation_request = stub_request(:post, "#{validator_url}/validate") + .with(query: hash_including({})) + .to_return(status: 200, body: validator_response_success.to_json) + + result = run(test, service_base_url_list_url:, endpoint_availability_success_rate: 'at_least_1') + + expect(result.result).to eq('pass') + expect(capability_statement_request_fail).to have_been_made.times(2) + expect(capability_statement_request_success).to have_been_made + expect(validation_request).to have_been_made.times(7) + end + + it 'passes and does not retrieve any capability statements if success rate input set to none' do + stub_request(:get, service_base_url_list_url) + .to_return(status: 200, body: bundle_resource.to_json, headers: {}) + + uri_template = Addressable::Template.new "#{base_url}/{id}/metadata" + capability_statement_request_success = stub_request(:get, uri_template) + .to_return(status: 200, body: capability_statement.to_json, headers: {}) + + validation_request = stub_request(:post, "#{validator_url}/validate") + .with(query: hash_including({})) + .to_return(status: 200, body: validator_response_success.to_json) + + result = run(test, service_base_url_list_url:, endpoint_availability_success_rate: 'none') + + expect(result.result).to eq('pass') + expect(capability_statement_request_success).to have_been_made.times(0) + expect(validation_request).to have_been_made.times(7) + end + it 'fails if Bundle contains endpoint that has an invalid URL in the address field' do bundle_resource.entry[4].resource.address = 'invalid_url%.com'