diff --git a/lib/inferno/dsl/fhir_client.rb b/lib/inferno/dsl/fhir_client.rb index e2fdc7f9f..2f7cf93e4 100644 --- a/lib/inferno/dsl/fhir_client.rb +++ b/lib/inferno/dsl/fhir_client.rb @@ -60,14 +60,13 @@ def fhir_clients @fhir_clients ||= {} end - # Checks if a parameter can be used in a GET request according FHIR specification + # Wrapper for checking if parameter contents are primitive # # @param param [FHIR::Parameters::Parameter] Parameter to be checked # @private - def safe_for_get?(param) - valid = param.valid? && param.part.empty? && param.resource.nil? # Parameter is valid - param_val = param.to_hash.except('name') # should contain only one value if it is a valid parameter - valid && !param_val.empty? && FHIR.primitive?(datatype: param_val.keys[0][5..], value: param_val.values[0]) + def primitive_parameter?(param) + param_val = param.to_hash.except('name') + param_val.any? { |datatype, param_value| FHIR.primitive?(datatype: datatype[5..], value: param_value) } end # Converts a list of FHIR Parameters into a query string for GET requests @@ -76,10 +75,9 @@ def safe_for_get?(param) # @private def body_to_path(body) query_hashes = body.parameter.map do |param| - if safe_for_get?(param) + if primitive_parameter?(param) { param.name => param.to_hash.except('name').values[0] } else - # Handle the case of nonprimitive Inferno::Application[:logger].error "Cannot use GET request with non-primitive datatype #{param.name}" raise ArgumentError, "Cannot use GET request with non-primitive datatype #{param.name}" end @@ -91,9 +89,11 @@ def body_to_path(body) # # @note This is a placeholder method until the FHIR::Client supports # general operations. Note that while both POST and GET methods are allowed, - # GET is only allowed when the operation does not affect the servers state. + # GET is only allowed when the operation does not affect the server's state. # See https://build.fhir.org/operationdefinition-definitions.html#OperationDefinition.affectsState # + # @note Currently does not allow for repeated parameters if using GET + # # @param path [String] # @param body [FHIR::Parameters] Must all be primitive if making GET request # @param client [Symbol] @@ -115,7 +115,6 @@ def fhir_operation(path, body: nil, client: :default, name: nil, headers: {}, op path = "#{path}?#{body_to_path(body)}" if body.present? fhir_client(client).send(:get, path, operation_headers) else - # Handle the case of non-supported operation_method Inferno::Application[:logger].error "Cannot perform #{operation_method} requests, use GET or POST" raise ArgumentError, "Cannot perform #{operation_method} requests, use GET or POST" end diff --git a/spec/inferno/dsl/fhir_client_spec.rb b/spec/inferno/dsl/fhir_client_spec.rb index 67d4d6874..3012e2cd3 100644 --- a/spec/inferno/dsl/fhir_client_spec.rb +++ b/spec/inferno/dsl/fhir_client_spec.rb @@ -135,43 +135,43 @@ def test_session_id end end - describe '#safe_for_get?' do - it 'returns true when given a primitive parameter' do - expect(group.safe_for_get?(boolean_parameter)).to be true - end - - it 'returns false when given a resource parameter' do - expect(group.safe_for_get?(resource_parameter)).to be false - end - - it 'returns false when given a complex parameter' do - expect(group.safe_for_get?(ratio_parameter)).to be false - end + describe '#primitive_parameter?' do + # it 'returns true when given a primitive parameter' do + # expect(group.primitive_parameter?(boolean_parameter)).to be true + # end + + # it 'returns false when given a resource parameter' do + # expect(group.primitive_parameter?(resource_parameter)).to be false + # end + + # it 'returns false when given a complex parameter' do + # expect(group.primitive_parameter?(ratio_parameter)).to be false + # end end describe '#body_to_path' do - it 'converts primitives into a path query' do - expect(group.body_to_path(body_with_two_primitives)).to eq({ PARAM_BOOL: true, PARAM_STRING: 'STRING' }.to_query) - end + # it 'converts primitives into a path query' do + # expect(group.body_to_path(body_with_two_primitives)).to eq({ PARAM_BOOL: true, PARAM_STRING: 'STRING' }.to_query) + # end it 'handles repeated parameters' do expected_body = [{ PARAM_BOOL: true }, { PARAM_BOOL: false }].map(&:to_query).join('&') expect(group.body_to_path(body_with_repeated_parameters)).to eq(expected_body) end - it 'raises error if non-primitive parameter found' do - body = body_with_nonprimitive - expect do - group.body_to_path(body) - end.to raise_error(ArgumentError, 'Cannot use GET request with non-primitive datatype PARAM_RATIO') - end + # it 'raises error if non-primitive parameter found' do + # body = body_with_nonprimitive + # expect do + # group.body_to_path(body) + # end.to raise_error(ArgumentError, 'Cannot use GET request with non-primitive datatype PARAM_RATIO') + # end - it 'raises error if parameter is resource' do - body = body_with_resource - expect do - group.body_to_path(body) - end.to raise_error(ArgumentError, 'Cannot use GET request with non-primitive datatype PARAM_RESOURCE') - end + # it 'raises error if parameter is resource' do + # body = body_with_resource + # expect do + # group.body_to_path(body) + # end.to raise_error(ArgumentError, 'Cannot use GET request with non-primitive datatype PARAM_RESOURCE') + # end end describe '#fhir_operation' do @@ -216,7 +216,7 @@ def test_session_id end context 'with a body of parameters' do - it 'uses get when all parameters are primitive' do + it 'uses get when all parameters are primitive and GET specified' do body = body_with_two_primitives get_with_body_request_stub = stub_request(:get, "#{base_url}/#{path}") @@ -228,12 +228,35 @@ def test_session_id expect(get_with_body_request_stub).to have_been_made.once end + # This test left for testing DoD of FI-2223 + # https://oncprojectracking.healthit.gov/support/browse/FI-2223 + # + # it 'correctly handles repeated parameters' do + # body = body_with_repeated_parameters + # get_with_body_request_stub = + # stub_request(:get, "#{base_url}/#{path}") + # .with(body: URI.encode_www_form({PARAM_BOOL: [true, false]})) + # .to_return(status: 200, body: resource.to_json) + # puts get_with_body_request_stub.to_s + + # group.fhir_operation(path, body:, operation_method: :get) + + # expect(get_with_body_request_stub).to have_been_made.once + # end + it 'prevents get when parameters are non-primitive' do body = body_with_nonprimitive expect do group.fhir_operation(path, body:, operation_method: :get) end.to raise_error(ArgumentError, 'Cannot use GET request with non-primitive datatype PARAM_RATIO') end + + it 'prevents get when parameters contain resources' do + body = body_with_resource + expect do + group.fhir_operation(path, body:, operation_method: :get) + end.to raise_error(ArgumentError, 'Cannot use GET request with non-primitive datatype PARAM_RESOURCE') + end end context 'with the client parameter' do