From 4eaeef6869b84f39abf5a1c41251b1913def949e Mon Sep 17 00:00:00 2001 From: Kris Pethtel Date: Thu, 15 Jun 2023 21:27:21 -0400 Subject: [PATCH] =?UTF-8?q?4747:=20add=20get=20letter=20as=20json=20method?= =?UTF-8?q?=20to=20lighthouse=20letters=20generator=20s=E2=80=A6=20(#12990?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 4747: add get letter as json method to lighthouse letters generator service --- lib/lighthouse/letters_generator/service.rb | 142 +++++++++--------- .../letters_generator/service_error.rb | 2 +- .../fakeProofOfServiceLetterResponse.json | 20 +++ .../letters_generator/service_spec.rb | 124 +++++++++++++++ 4 files changed, 216 insertions(+), 72 deletions(-) create mode 100644 spec/lib/lighthouse/letters_generator/fakeResponses/fakeProofOfServiceLetterResponse.json diff --git a/lib/lighthouse/letters_generator/service.rb b/lib/lighthouse/letters_generator/service.rb index 2366c34260b..ebf3d526b72 100644 --- a/lib/lighthouse/letters_generator/service.rb +++ b/lib/lighthouse/letters_generator/service.rb @@ -33,6 +33,70 @@ class Service < Common::Client::Base configuration Lighthouse::LettersGenerator::Configuration + def get_letter(icn, letter_type, options = {}) + validate_downloadable_letter_type(letter_type) + + endpoint = "letter-contents/#{letter_type}" + log = "Retrieving letter from #{config.generator_url}/#{endpoint}" + params = { icn: }.merge(options) + + response = get_from_lighthouse(endpoint, params, log) + response.body + end + + def get_eligible_letter_types(icn) + endpoint = 'eligible-letters' + log = "Retrieving eligible letter types and destination from #{config.generator_url}/#{endpoint}" + params = { icn: } + + response = get_from_lighthouse(endpoint, params, log) + { + letters: transform_letters(response.body['letters']), + letter_destination: response.body['letterDestination'] + } + end + + def get_benefit_information(icn) + endpoint = 'eligible-letters' + log = "Retrieving benefit information from #{config.generator_url}/#{endpoint}" + params = { icn: } + + response = get_from_lighthouse(endpoint, params, log) + { + benefitInformation: transform_benefit_information(response.body['benefitInformation']), + militaryService: transform_military_services(response.body['militaryServices']) + } + end + + def download_letter(icn, letter_type, options = {}) + validate_downloadable_letter_type(letter_type) + + endpoint = "letters/#{letter_type}/letter" + log = "Retrieving benefit information from #{config.generator_url}/#{endpoint}" + params = { icn: }.merge(options) + + response = get_from_lighthouse(endpoint, params, log) + response.body + end + + private + + def get_from_lighthouse(endpoint, params, log) + Lighthouse::LettersGenerator.measure_time(log) do + config.connection.get( + endpoint, + params, + { Authorization: "Bearer #{config.get_access_token}" } + ) + end + rescue Faraday::ClientError, Faraday::ServerError => e + Raven.tags_context( + team: 'benefits-claim-appeal-status', + feature: 'letters-generator' + ) + raise Lighthouse::LettersGenerator::ServiceError.new(e.response[:body]), 'Lighthouse error' + end + def transform_letters(letters) letters.map do |letter| { @@ -43,7 +107,6 @@ def transform_letters(letters) end def transform_military_services(services_info) - # transform services_info.map do |service| service[:enteredDate] = service.delete 'enteredDateTime' service[:releasedDate] = service.delete 'releasedDateTime' @@ -80,76 +143,6 @@ def transform_benefit_information(info) ).except(:chapter35EligibilityDateTime) end - def get_eligible_letter_types(icn) - endpoint = 'eligible-letters' - - begin - log = "Retrieving eligible letter types and destination from #{config.generator_url}/#{endpoint}" - response = Lighthouse::LettersGenerator.measure_time(log) do - config.connection.get(endpoint, { icn: }, { Authorization: "Bearer #{config.get_access_token}" }) - end - rescue Faraday::ClientError, Faraday::ServerError => e - Raven.tags_context( - team: 'benefits-claim-appeal-status', - feature: 'letters-generator' - ) - raise Lighthouse::LettersGenerator::ServiceError.new(e.response[:body]), 'Lighthouse error' - end - - { - letters: transform_letters(response.body['letters']), - letter_destination: response.body['letterDestination'] - } - end - - # TODO: repeated code #get_eligible_letter_types - def get_benefit_information(icn) - endpoint = 'eligible-letters' - - begin - log = "Retrieving benefit information from #{config.generator_url}/#{endpoint}" - response = Lighthouse::LettersGenerator.measure_time(log) do - config.connection.get(endpoint, { icn: }, { Authorization: "Bearer #{config.get_access_token}" }) - end - rescue Faraday::ClientError, Faraday::ServerError => e - Raven.tags_context( - team: 'benefits-claim-appeal-status', - feature: 'letters-generator' - ) - raise Lighthouse::LettersGenerator::ServiceError.new(e.response[:body]), 'Lighthouse error' - end - - { - benefitInformation: transform_benefit_information(response.body['benefitInformation']), - militaryService: transform_military_services(response.body['militaryServices']) - } - end - - def download_letter(icn, letter_type, options = {}) - unless LETTER_TYPES.include? letter_type.downcase - error = create_invalid_type_error(letter_type.downcase) - raise error - end - - endpoint = "letters/#{letter_type}/letter" - - begin - log = "Retrieving benefit information from #{config.generator_url}/#{endpoint}" - response = Lighthouse::LettersGenerator.measure_time(log) do - config.connection.get( - endpoint, - { icn: }.merge(options), - { Authorization: "Bearer #{config.get_access_token}" } - ) - end - rescue Faraday::ClientError, Faraday::ServerError => e - Raven.tags_context(team: 'benefits-claim-appeal-status', feature: 'letters-generator') - raise Lighthouse::LettersGenerator::ServiceError.new(e.response[:body]), 'Lighthouse error' - end - - response.body - end - def create_invalid_type_error(letter_type) error = Lighthouse::LettersGenerator::ServiceError.new error.title = 'Invalid letter type' @@ -158,6 +151,13 @@ def create_invalid_type_error(letter_type) error end + + def validate_downloadable_letter_type(letter_type) + unless LETTER_TYPES.include? letter_type.downcase + error = create_invalid_type_error(letter_type.downcase) + raise error + end + end end end end diff --git a/lib/lighthouse/letters_generator/service_error.rb b/lib/lighthouse/letters_generator/service_error.rb index b5f955a277d..6b125a31960 100644 --- a/lib/lighthouse/letters_generator/service_error.rb +++ b/lib/lighthouse/letters_generator/service_error.rb @@ -30,8 +30,8 @@ def initialize(exception = nil) @status ||= exception['status'].to_i @title ||= exception['title'] @message = exception['detail'] || exception['message'] - @key ||= error_key end + @key ||= error_key end def errors diff --git a/spec/lib/lighthouse/letters_generator/fakeResponses/fakeProofOfServiceLetterResponse.json b/spec/lib/lighthouse/letters_generator/fakeResponses/fakeProofOfServiceLetterResponse.json new file mode 100644 index 00000000000..995f58b9bcc --- /dev/null +++ b/spec/lib/lighthouse/letters_generator/fakeResponses/fakeProofOfServiceLetterResponse.json @@ -0,0 +1,20 @@ +{ + "letterDescription": "This card verifies that you served honorably in the Armed Forces.", + "letterContent": [ + { + "contentKey": "front-of-card", + "contentTitle": "", + "content": "This card is to serve as proof the individual listed below served honorably in the Uniformed Services of the United States. Jesse Gray 1708 Tiburon Blvd Tiburon, CA 94921 Effective as of: June 08, 2023 DoD ID Number: 1293307390 Date of Birth: December 15, 1954 Branch Of Service: Army" + }, + { + "contentKey": "back-of-card", + "contentTitle": "", + "content": "United States of America Department of Veterans Affairs General Benefit Information 1-800-827-1000 Health Care Information 1-877-222-VETS (8387) This card does not reflect entitlement to any benefits administered by the Department of Veterans Affairs or serve as proof of receiving such benefits." + }, + { + "contentKey": "contact-us", + "contentTitle": "How You Can Contact Us", + "content": "If you need general information about benefits and eligibility, please visit us at https://www.va.gov. Call us at 1-800-827-1000. Contact us using Telecommunications Relay Services (TTY) at 711 24/7. Send electronic inquiries through the Internet at https://www.va.gov/contact-us." + } + ] +} \ No newline at end of file diff --git a/spec/lib/lighthouse/letters_generator/service_spec.rb b/spec/lib/lighthouse/letters_generator/service_spec.rb index 2d107129761..3043f4c9d80 100644 --- a/spec/lib/lighthouse/letters_generator/service_spec.rb +++ b/spec/lib/lighthouse/letters_generator/service_spec.rb @@ -34,6 +34,130 @@ end end + describe '#get_letter' do + it 'returns a full json representation of a letter without letter options' do + expect_any_instance_of(Lighthouse::LettersGenerator::Configuration) + .to receive(:get_access_token) + .once + .and_return('faketoken') + + fake_response_json = File.read("#{FAKE_RESPONSES_PATH}/fakeProofOfServiceLetterResponse.json") + fake_response_body = JSON.parse(fake_response_json) + + @stubs.get('/letter-contents/proof_of_service?icn=DOLLYPARTON') do + [200, {}, fake_response_body] + end + + client = Lighthouse::LettersGenerator::Service.new + + response = client.get_letter('DOLLYPARTON', 'proof_of_service') + + expect(response).to have_key('letterDescription') + expect(response).to have_key('letterContent') + expect(response['letterContent'].length).to eq(3) + response['letterContent'].each do |content| + expect(content.keys).to match_array(%w[contentKey contentTitle content]) + end + end + + it 'returns a full json representation of a letter with options' do + expect_any_instance_of(Lighthouse::LettersGenerator::Configuration) + .to receive(:get_access_token) + .once + .and_return('faketoken') + + fake_response_json = File.read("#{FAKE_RESPONSES_PATH}/fakeProofOfServiceLetterResponse.json") + fake_response_body = JSON.parse(fake_response_json) + query_params = 'icn=DOLLYPARTON&serviceConnectedDisabilities=true' + + @stubs.get("/letter-contents/proof_of_service?#{query_params}") do + [200, {}, fake_response_body] + end + + client = Lighthouse::LettersGenerator::Service.new + + response = client.get_letter('DOLLYPARTON', 'proof_of_service', { serviceConnectedDisabilities: true }) + expect(response).to have_key('letterDescription') + expect(response).to have_key('letterContent') + expect(response['letterContent'].length).to eq(3) + response['letterContent'].each do |content| + expect(content.keys).to match_array(%w[contentKey contentTitle content]) + end + end + + context 'Error handling' do + it 'handles an error that returns a detailed response' do + ## This test covers classes of client errors in lighthouse that + ## have a detailed response, exemplified in fakeBadRequest.json. + ## Status codes include: 400, 404, 406, 433, 500 + ## Link: https://developer.va.gov/explore/verification/docs/va_letter_generator + + expect_any_instance_of(Lighthouse::LettersGenerator::Configuration) + .to receive(:get_access_token) + .once + .and_return('faketoken') + + fake_response_json = File.read("#{FAKE_RESPONSES_PATH}/fakeBadRequest.json") + fake_response_body = JSON.parse(fake_response_json) + @stubs.get('/letter-contents/proof_of_service?icn=BADREQUEST') do + raise Faraday::BadRequestError.new('YIKES', { body: fake_response_body }) + end + + client = Lighthouse::LettersGenerator::Service.new + + expect { client.get_letter('BADREQUEST', 'proof_of_service') }.to raise_error do |error| + expect(error).to be_an_instance_of(Lighthouse::LettersGenerator::ServiceError) + expect(error.errors.first.status).to eq(fake_response_body['status'].to_s) + expect(error.errors.first.meta[:message]).to eq(fake_response_body['detail']) + end + end + + it 'handles an error that returns a simplified response' do + ## This test covers classes of client errors in lighthouse that + ## have a detailed response, exemplified in fakeBadRequest.json. + ## Status codes include: 401, 403, 413, 429 + ## Link: https://developer.va.gov/explore/verification/docs/va_letter_generator + + expect_any_instance_of(Lighthouse::LettersGenerator::Configuration) + .to receive(:get_access_token) + .once + .and_return('faketoken') + + fake_response_json = File.read("#{FAKE_RESPONSES_PATH}/fakeUnauthorized.json") + fake_response_body = JSON.parse(fake_response_json) + @stubs.get('/letter-contents/proof_of_service?icn=BadActor') do + raise Faraday::UnauthorizedError.new("don't go in there", { body: fake_response_body }) + end + + client = Lighthouse::LettersGenerator::Service.new + + expect { client.get_letter('BadActor', 'proof_of_service') }.to raise_error do |error| + expect(error).to be_an_instance_of(Lighthouse::LettersGenerator::ServiceError) + end + end + + it 'returns a 400 if the letter type is not valid' do + expect_any_instance_of(Lighthouse::LettersGenerator::Configuration) + .not_to receive(:get_access_token) + .and_return('faketoken') + + fake_response_json = File.read("#{FAKE_RESPONSES_PATH}/fakeResponse.json") + fake_response_body = JSON.parse(fake_response_json) + + @stubs.get('/letter-contents/LETTER_TO_GRANDMA?icn=DOLLYPARTON') do + [200, {}, fake_response_body] + end + + client = Lighthouse::LettersGenerator::Service.new + + expect { client.get_letter('DOLLYPARTON', 'LETTER_TO_GRANDMA') }.to raise_error do |error| + expect(error).to be_an_instance_of(Lighthouse::LettersGenerator::ServiceError) + expect(error.status).to eq(400) + end + end + end + end + describe '#get_eligible_letter_types' do it 'returns a list of eligible letter types' do expect_any_instance_of(Lighthouse::LettersGenerator::Configuration)