Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions app/services/doc_auth/dos/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,24 @@ def handle_invalid_response(http_response)
{}
end

# Handle both nested error format and simple string error format
error_value = response_body['error']
error_code, error_message, error_reason = case error_value
when Hash
# Nested format: {"error": {"code": "...", "message": "...", "reason": "..."}}
[error_value['code'], error_value['message'], error_value['reason']]
when String
# Simple format: {"error": "Invalid Client"} or {"error": "Authentication denied."}
[nil, error_value, nil]
else
[nil, nil, nil]
end

handle_connection_error(
exception: exception,
# TODO: update for DoS
error_code: response_body.dig('error', 'code'),
error_message: response_body.dig('error', 'message'),
error_reason: response_body.dig('error', 'reason'),
error_code: error_code,
error_message: error_message,
error_reason: error_reason,
correlation_id_received: http_response.headers['X-Correlation-ID'],
)
end
Expand All @@ -95,7 +107,7 @@ def handle_connection_error(
error_reason: error_reason,
correlation_id_sent: correlation_id,
correlation_id_received:,
}.compact,
},
)
end

Expand Down
88 changes: 88 additions & 0 deletions spec/services/doc_auth/dos/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,92 @@
end
end
end

describe '#handle_invalid_response' do
let(:http_response) do
instance_double(
Faraday::Response,
status: status,
body: response_body,
headers: { 'X-Correlation-ID' => '12345' },
)
end
let(:status) { 401 }

context 'with nested error format' do
let(:response_body) do
{ error: { code: 'ERR001', message: 'Invalid request', reason: 'Bad format' } }.to_json
end

it 'extracts error details from nested hash' do
response = subject.send(:handle_invalid_response, http_response)

expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: 'ERR001',
error_message: 'Invalid request',
error_reason: 'Bad format',
correlation_id_received: '12345',
)
end
end

context 'with simple string error format' do
let(:response_body) do
{ error: 'Authentication denied.' }.to_json
end

it 'extracts error message from string' do
response = subject.send(:handle_invalid_response, http_response)

expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: nil,
error_message: 'Authentication denied.',
error_reason: nil,
correlation_id_received: '12345',
)
end
end

context 'with invalid JSON' do
let(:response_body) { 'Not JSON' }

it 'handles non-JSON response gracefully' do
response = subject.send(:handle_invalid_response, http_response)

expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: nil,
error_message: nil,
error_reason: nil,
correlation_id_received: '12345',
)
end
end

context 'with empty response body' do
let(:response_body) { '' }

it 'handles empty response gracefully' do
response = subject.send(:handle_invalid_response, http_response)

expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: nil,
error_message: nil,
error_reason: nil,
correlation_id_received: '12345',
)
end
end
end
end
71 changes: 56 additions & 15 deletions spec/services/doc_auth/dos/requests/mrz_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,64 @@
end

context 'when the request fails' do
let(:http_status) { 500 }
let(:response_body) do
{ error: { code: 'ERR', message: 'issues @ State', reason: 'just because' } }.to_json
let(:http_status) { 401 }

context 'when the response error is a hash' do
let(:response_body) do
{ error: { code: 'ERR', message: 'issues @ State', reason: 'just because' } }.to_json
end

it 'handles the nested error without throwing an exception' do
response = subject.fetch
expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: 'ERR',
error_message: 'issues @ State',
error_reason: 'just because',
correlation_id_sent: correlation_id,
correlation_id_received: correlation_id,
)
end
end

it 'fails with a message' do
response = subject.fetch
expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: 'ERR',
error_message: 'issues @ State',
error_reason: 'just because',
correlation_id_sent: correlation_id,
correlation_id_received: correlation_id,
)
context 'when the response error is a string' do
let(:response_body) do
{ error: 'Authentication denied.' }.to_json
end

it 'handles the string error without throwing an exception' do
response = subject.fetch
expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: nil,
error_message: 'Authentication denied.',
error_reason: nil,
correlation_id_sent: correlation_id,
correlation_id_received: correlation_id,
)
end
end

context 'when the response error is empty' do
let(:response_body) { '' }

it 'handles empty response gracefully' do
response = subject.fetch
expect(response.success?).to be(false)
expect(response.errors).to include(network: true)
expect(response.extra).to include(
vendor: 'DoS',
error_code: nil,
error_message: nil,
error_reason: nil,
correlation_id_sent: correlation_id,
correlation_id_received: correlation_id,
)
end
end
end
end