diff --git a/app/services/proofing/aamva/response/verification_response.rb b/app/services/proofing/aamva/response/verification_response.rb index a5784fcd868..c1e748f9f6c 100644 --- a/app/services/proofing/aamva/response/verification_response.rb +++ b/app/services/proofing/aamva/response/verification_response.rb @@ -33,9 +33,17 @@ def initialize(http_response) @missing_attributes = [] @verification_results = {} @http_response = http_response + @errors = [] + handle_http_error handle_soap_error + parse_response + + return if @errors.empty? + + error_message = @errors.join('; ') + raise VerificationError.new(error_message) end def reasons @@ -63,8 +71,7 @@ def success? def handle_http_error status = http_response.status - return if status == 200 - raise VerificationError, "Unexpected status code in response: #{status}" + @errors.push("Unexpected status code in response: #{status}") if status != 200 end def handle_missing_attribute(attribute_name) @@ -76,13 +83,13 @@ def handle_soap_error error_handler = SoapErrorHandler.new(http_response) return unless error_handler.error_present? - msg = error_handler.error_message - raise ::Proofing::TimeoutError, msg if mva_timeout?(msg) - raise VerificationError, msg + @errors.push(error_handler.error_message) end def node_for_match_indicator(match_indicator_name) REXML::XPath.first(rexml_document, "//#{match_indicator_name}") + rescue REXML::ParseException + nil end def parse_response @@ -104,7 +111,7 @@ def parse_response end def rexml_document - @rexml_document ||= REXML::Document.new(http_response.body) + return @rexml_document ||= REXML::Document.new(http_response.body) end def mva_timeout?(error_message) diff --git a/app/services/proofing/aamva/soap_error_handler.rb b/app/services/proofing/aamva/soap_error_handler.rb index e498bf0be24..b8bbaf704f2 100644 --- a/app/services/proofing/aamva/soap_error_handler.rb +++ b/app/services/proofing/aamva/soap_error_handler.rb @@ -9,6 +9,9 @@ class SoapErrorHandler def initialize(http_response) @document = REXML::Document.new(http_response.body) parse_error_message + rescue REXML::ParseException => e + @error_present = true + @error_message = e.to_s end def error_present? diff --git a/spec/services/proofing/aamva/response/verification_response_spec.rb b/spec/services/proofing/aamva/response/verification_response_spec.rb index 5f5aeff4348..39ff9c207ba 100644 --- a/spec/services/proofing/aamva/response/verification_response_spec.rb +++ b/spec/services/proofing/aamva/response/verification_response_spec.rb @@ -49,7 +49,7 @@ it 'raises a VerificationError' do expect { subject }.to raise_error( Proofing::Aamva::VerificationError, - 'Unexpected status code in response: 504', + /Unexpected status code in response: 504/, ) end end diff --git a/spec/services/proofing/aamva/verification_client_spec.rb b/spec/services/proofing/aamva/verification_client_spec.rb index 46348a8a73e..1412531714a 100644 --- a/spec/services/proofing/aamva/verification_client_spec.rb +++ b/spec/services/proofing/aamva/verification_client_spec.rb @@ -19,11 +19,13 @@ subject(:verification_client) { described_class.new(AamvaFixtures.example_config) } describe '#send_verification_request' do - it 'should get the auth token from the auth client' do + before do auth_client = instance_double(Proofing::Aamva::AuthenticationClient) allow(auth_client).to receive(:fetch_token).and_return('ThisIsTheToken') allow(Proofing::Aamva::AuthenticationClient).to receive(:new).and_return(auth_client) + end + it 'gets the auth token from the auth client' do verification_stub = stub_request(:post, AamvaFixtures.example_config.verification_url). to_return(body: AamvaFixtures.verification_response, status: 200). with do |request| @@ -37,45 +39,149 @@ expect(verification_stub).to have_been_requested end + end - context 'when verification is successful' do - it 'should return a successful response' do - auth_client = instance_double(Proofing::Aamva::AuthenticationClient) - allow(auth_client).to receive(:fetch_token).and_return('ThisIsTheToken') - allow(Proofing::Aamva::AuthenticationClient).to receive(:new).and_return(auth_client) - stub_request(:post, AamvaFixtures.example_config.verification_url). - to_return(body: AamvaFixtures.verification_response, status: 200) - - response = verification_client.send_verification_request( - applicant: applicant, - session_id: '1234-abcd-efgh', - ) + describe '#send_verification_request' do + let(:response_body) { AamvaFixtures.verification_response } + let(:response_http_status) { 200 } + + before do + auth_client = instance_double(Proofing::Aamva::AuthenticationClient) + allow(auth_client).to receive(:fetch_token).and_return('ThisIsTheToken') + allow(Proofing::Aamva::AuthenticationClient).to receive(:new).and_return(auth_client) + + stub_request(:post, AamvaFixtures.example_config.verification_url). + to_return(body: response_body, status: response_http_status) + end + + let(:response) do + verification_client.send_verification_request( + applicant: applicant, + session_id: '1234-abcd-efgh', + ) + end + context 'when verification is successful' do + it 'returns a successful response' do expect(response).to be_a Proofing::Aamva::Response::VerificationResponse expect(response.success?).to eq(true) end end context 'when verification is not successful' do - it 'should return an unsuccessful response with errors' do - auth_client = instance_double(Proofing::Aamva::AuthenticationClient) - allow(auth_client).to receive(:fetch_token).and_return('ThisIsTheToken') - allow(Proofing::Aamva::AuthenticationClient).to receive(:new).and_return(auth_client) + context 'because we have a valid response and a 200 status, but the response says "no"' do + let(:response_body) do + modify_xml_at_xpath( + AamvaFixtures.verification_response, + '//PersonBirthDateMatchIndicator', + 'false', + ) + end + + it 'returns an unsuccessful response with errors' do + expect(response).to be_a Proofing::Aamva::Response::VerificationResponse + expect(response.success?).to eq(false) + end + end - stub_request(:post, AamvaFixtures.example_config.verification_url). - to_return(status: 200, body: modify_xml_at_xpath( + context 'because we have a valid response and a non-200 status, and the response says "no"' do + let(:response_body) do + modify_xml_at_xpath( AamvaFixtures.verification_response, '//PersonBirthDateMatchIndicator', 'false', - )) + ) + end + let(:response_http_status) { 500 } + + it 'throws an exception about the status code' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /Unexpected status code in response: 500/, + ) + end + end - response = verification_client.send_verification_request( - applicant: applicant, - session_id: '1234-abcd-efgh', - ) + context 'because we have an MVA timeout and 500 status' do + let(:response_body) { AamvaFixtures.soap_fault_response } + let(:response_http_status) { 500 } - expect(response).to be_a Proofing::Aamva::Response::VerificationResponse - expect(response.success?).to eq(false) + it 'throws an exception about the MVA timeout' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /#{Proofing::Aamva::Response::VerificationResponse::MVA_TIMEOUT_EXCEPTION}/o, + ) + end + + it 'throws an exception about the status code' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /Unexpected status code in response: 500/, + ) + end + end + + context 'because we have an MVA timeout and 200 status' do + let(:response_body) { AamvaFixtures.soap_fault_response } + let(:response_http_status) { 200 } + + it 'parses the raw response body' do + begin + response + rescue Proofing::Aamva::VerificationError + end + end + + it 'throws an exception about the MVA timeout' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /#{Proofing::Aamva::Response::VerificationResponse::MVA_TIMEOUT_EXCEPTION}/o, + ) + end + end + + context 'because we have an invalid response and a 200 status' do + let(:response_body) { 'error: computer has no brain.
' } + + it 'tries to parse the raw response body' do + begin + response + rescue Proofing::Aamva::VerificationError + end + end + + it 'throws a SOAP exception' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /No close tag for \/br/, + ) + end + end + + context 'because we have an invalid response and a non-200 status' do + let(:response_body) { '

I\'m a teapot' } + let(:response_http_status) { 418 } + + it 'tries to parse the raw response body' do + begin + response + rescue Proofing::Aamva::VerificationError + end + end + + it 'throws an error which complains about the invalid response' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /No close tag for \/h1/, + ) + end + + it 'throws an error which complains about the HTTP error code' do + expect { response }.to raise_error( + Proofing::Aamva::VerificationError, + /Unexpected status code in response: 418/, + ) + end end end end