diff --git a/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb b/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb index f62f4368663..b8750126ba0 100644 --- a/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb +++ b/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb @@ -2,20 +2,27 @@ module AskVAApi module Correspondences - class CorrespondencesRetrieverError < StandardError; end - - class Retriever < BaseRetriever - attr_reader :inquiry_id, :entity_class + class Retriever + attr_reader :inquiry_id, :entity_class, :user_mock_data def initialize(inquiry_id:, user_mock_data:, entity_class:) - super(user_mock_data:, entity_class:) + @user_mock_data = user_mock_data + @entity_class = entity_class @inquiry_id = inquiry_id end + def call + case fetch_data + when Array + fetch_data.map { |data| entity_class.new(data) } + else + fetch_data + end + end + private def fetch_data - validate_input(inquiry_id, 'Invalid Inquiry ID') if user_mock_data data = File.read('modules/ask_va_api/config/locales/get_replies_mock_data.json') @@ -29,10 +36,6 @@ def fetch_data end end - def validate_input(input, error_message) - raise ArgumentError, error_message if input.blank? - end - def filter_data(data) data.select do |cor| cor[:InquiryId] == inquiry_id @@ -40,7 +43,7 @@ def filter_data(data) end def handle_response_data(response) - response[:Data].presence || raise(CorrespondencesRetrieverError, response[:Message]) + response[:Data].presence || response end end end diff --git a/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb b/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb index 073c35f8832..1ebc679f679 100644 --- a/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb +++ b/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb @@ -38,11 +38,18 @@ def fetch_data(id = nil) end def fetch_correspondences(inquiry_id:) - Correspondences::Retriever.new( + correspondences = Correspondences::Retriever.new( inquiry_id:, user_mock_data:, entity_class: AskVAApi::Correspondences::Entity ).call + + case correspondences + when Hash + [] + else + correspondences + end end def read_mock_data(file_name) @@ -57,12 +64,7 @@ def filter_data(data, id = nil) end def handle_response_data(response) - if response[:Data].nil? - error = JSON.parse(response[:body], symbolize_names: true) - raise InquiriesRetrieverError, error[:Message] - else - response[:Data] - end + response[:Data].presence || raise(InquiriesRetrieverError, response) end end end diff --git a/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb b/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb index 3eed7120732..61b84f11798 100644 --- a/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb +++ b/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb @@ -18,15 +18,6 @@ end describe '#call' do - context 'when id is blank' do - let(:inquiry_id) { nil } - - it 'raises an ArgumentError' do - expect { retriever.call } - .to raise_error(ErrorHandler::ServiceError, 'ArgumentError: Invalid Inquiry ID') - end - end - context 'when Crm raise an error' do let(:endpoint) { 'inquiries/1/replies' } let(:response) do @@ -42,8 +33,12 @@ allow(service).to receive(:call).and_return(response) end - it 'raise CorrespondenceRetrieverError' do - expect { retriever.call }.to raise_error(ErrorHandler::ServiceError) + it 'returns the error' do + expect(retriever.call).to eq({ Data: [], + Message: 'Data Validation: No Inquiry Found', + ExceptionOccurred: true, + ExceptionMessage: 'Data Validation: No Inquiry Found', + MessageId: '2d746074-9e5c-4987-a894-e3f834b156b5' }) end end diff --git a/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb b/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb index ee1f4e45987..910f5232db0 100644 --- a/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb +++ b/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb @@ -164,6 +164,74 @@ end end end + + context 'with Correspondences' do + let(:id) { '123' } + let(:response) do + { Data: [{ Id: '154163f2-8fbb-ed11-9ac4-00155da17a6f', + InquiryNumber: 'A-20230305-306178', + InquiryStatus: 'Reopened', + SubmitterQuestion: 'test', + LastUpdate: '4/1/2024 12:00:00 AM', + InquiryHasAttachments: true, + InquiryHasBeenSplit: true, + VeteranRelationship: 'GIBillBeneficiary', + SchoolFacilityCode: '77a51029-6816-e611-9436-0050568d743d', + InquiryTopic: 'Medical Care Concerns at a VA Medical Facility', + InquiryLevelOfAuthentication: 'Unauthenticated', + AttachmentNames: [{ Id: '367e8d31-6c82-1d3c-81b8-dd2cabed7555', + Name: 'Test.txt' }] }] } + end + + context 'when Correspondence::Retriever returns an error' do + before do + allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token') + allow(service).to receive(:call).and_return(response) + allow_any_instance_of(AskVAApi::Correspondences::Retriever).to receive(:call) + .and_return({ Data: [], + Message: 'Data Validation: No Inquiry Found', + ExceptionOccurred: true, + ExceptionMessage: 'Data Validation: No Inquiry Found', + MessageId: '2d746074-9e5c-4987-a894-e3f834b156b5' }) + end + + it 'returns correspondences as an empty array' do + inquiry = retriever.fetch_by_id(id:) + + expect(inquiry.correspondences).to eq([]) + end + end + + context 'when Correspondence::Retriever returns a success' do + let(:cor_info) do + { + Id: 'f4b12ee3-93bb-ed11-9886-001dd806a6a7', + ModifiedOn: '3/5/2023 8:25:49 PM', + StatusReason: 'Sent', + Description: 'Dear aminul, Thank you for submitting your ' \ + 'Inquiry with the U.S. Department of Veteran Affairs.', + MessageType: 'Notification', + EnableReply: true, + AttachmentNames: nil + } + end + + let(:correspondence) { AskVAApi::Correspondences::Entity.new(cor_info) } + + before do + allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token') + allow(service).to receive(:call).and_return(response) + allow_any_instance_of(AskVAApi::Correspondences::Retriever).to receive(:call) + .and_return([correspondence]) + end + + it 'returns correspondences as an empty array' do + inquiry = retriever.fetch_by_id(id:) + + expect(inquiry.correspondences).to eq([correspondence]) + end + end + end end end end diff --git a/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb b/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb index 03eec8510ca..1cf3c468603 100644 --- a/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb +++ b/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb @@ -234,7 +234,11 @@ it_behaves_like 'common error handling', :unprocessable_entity, 'service_error', 'AskVAApi::Inquiries::InquiriesRetrieverError: ' \ - 'Data Validation: No Inquiries found by ID A-20240423-30709' + '{:status=>400, :body=>"{\"Data\":null,\"Message\":\"Data Validation: ' \ + 'No Inquiries found by ID A-20240423-30709\",\"ExceptionOccurred\":' \ + 'true,\"ExceptionMessage\":\"Data Validation: No Inquiries found by ID ' \ + 'A-20240423-30709\",\"MessageId\":\"ca5b990a-63fe-407d-a364-46caffce12c1\"}",' \ + ' :response_headers=>nil, :url=>nil}' end end end diff --git a/modules/ask_va_api/spec/services/crm/crm_token_spec.rb b/modules/ask_va_api/spec/services/crm/crm_token_spec.rb index c83e5c91b43..ee432210524 100644 --- a/modules/ask_va_api/spec/services/crm/crm_token_spec.rb +++ b/modules/ask_va_api/spec/services/crm/crm_token_spec.rb @@ -30,7 +30,7 @@ def mock_response(status:, body:) end end - context 'with invalid JSON' do + context 'when veis auth service returns a 401 error response' do let(:resp) { mock_response(body: { error: 'invalid_client' }, status: 401) } let(:exception) { Common::Exceptions::BackendServiceException.new(nil, {}, resp.status, resp.body) } diff --git a/modules/ask_va_api/spec/services/crm/service_spec.rb b/modules/ask_va_api/spec/services/crm/service_spec.rb index ba7f2e4dd8b..45269f9a624 100644 --- a/modules/ask_va_api/spec/services/crm/service_spec.rb +++ b/modules/ask_va_api/spec/services/crm/service_spec.rb @@ -5,29 +5,14 @@ RSpec.describe Crm::Service do let(:service) { described_class.new(icn: '123') } - # Helper method to create a mock response def mock_response(status:, body:) instance_double(Faraday::Response, status:, body: body.to_json) end - # Shared examples for error handling - shared_examples 'error handling' do |status, message| - let(:body) { 'Sample error message' } - - it "returns a formatted message for status #{status}" do - response = mock_response(status:, body:) - expected_error_message = "#{message} to #{endpoint}: \"#{body}\"" - - expect do - Crm::ErrorHandler.handle(endpoint, response) - end.to raise_error(Crm::ErrorHandler::ServiceError, expected_error_message) - end - end - describe '#call' do let(:endpoint) { 'inquiries' } - context 'server response' do + context 'when server response successful' do context 'with valid JSON' do let(:response) do mock_response( @@ -64,35 +49,6 @@ def mock_response(status:, body:) end end - describe 'error message formatting' do - context 'when response is nil' do - it 'returns a message indicating no response was received' do - expect do - Crm::ErrorHandler.handle(endpoint, - nil) - end.to raise_error(Crm::ErrorHandler::ServiceError, "Server Error to #{endpoint}: ") - end - end - - context 'with specific response status codes' do - include_examples 'error handling', 400, 'Bad request' - include_examples 'error handling', 401, 'Unauthorized' - include_examples 'error handling', 403, 'Forbidden: You do not have permission to access' - include_examples 'error handling', 404, 'Resource not found' - end - - context 'with unspecified response status codes' do - let(:body) { 'General error message' } - - it 'returns a generic error message' do - response = mock_response(status: 418, body:) - expect do - Crm::ErrorHandler.handle(endpoint, response) - end.to raise_error(Crm::ErrorHandler::ServiceError, "Service Error to #{endpoint}: \"#{body}\"") - end - end - end - context 'when the server returns an error' do let(:resp) { mock_response(body: { error: 'server error' }, status: 500) } let(:exception) { Common::Exceptions::BackendServiceException.new(nil, {}, resp.status, resp.body) }