Files
news.gitea.happylizard.me/bin/gems/faraday-2.9.0/spec/faraday/response/logger_spec.rb
T
pizza2d1 4cee170d66
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s
Add bin and edit workflow
2026-09-16 13:11:16 -06:00

259 lines
8.7 KiB
Ruby

# frozen_string_literal: true
require 'stringio'
require 'logger'
RSpec.describe Faraday::Response::Logger do
let(:string_io) { StringIO.new }
let(:logger) { Logger.new(string_io) }
let(:logger_options) { {} }
let(:conn) do
rubbles = ['Barney', 'Betty', 'Bam Bam']
Faraday.new do |b|
b.response :logger, logger, logger_options do |logger|
logger.filter(/(soylent green is) (.+)/, '\1 tasty')
logger.filter(/(api_key:).*"(.+)."/, '\1[API_KEY]')
logger.filter(/(password)=(.+)/, '\1=[HIDDEN]')
end
b.adapter :test do |stubs|
stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
stubs.post('/ohai') { [200, { 'Content-Type' => 'text/html' }, 'fred'] }
stubs.post('/ohyes') { [200, { 'Content-Type' => 'text/html' }, 'pebbles'] }
stubs.get('/rubbles') { [200, { 'Content-Type' => 'application/json' }, rubbles] }
stubs.get('/filtered_body') { [200, { 'Content-Type' => 'text/html' }, 'soylent green is people'] }
stubs.get('/filtered_headers') { [200, { 'Content-Type' => 'text/html' }, 'headers response'] }
stubs.get('/filtered_params') { [200, { 'Content-Type' => 'text/html' }, 'params response'] }
stubs.get('/filtered_url') { [200, { 'Content-Type' => 'text/html' }, 'url response'] }
stubs.get('/connection_failed') { raise Faraday::ConnectionFailed, 'Failed to open TCP connection' }
end
end
end
before do
logger.level = Logger::DEBUG
end
it 'still returns output' do
resp = conn.get '/hello', nil, accept: 'text/html'
expect(resp.body).to eq('hello')
end
context 'without configuration' do
let(:conn) do
Faraday.new do |b|
b.response :logger
b.adapter :test do |stubs|
stubs.get('/hello') { [200, { 'Content-Type' => 'text/html' }, 'hello'] }
end
end
end
it 'defaults to stdout' do
expect(Logger).to receive(:new).with($stdout).and_return(Logger.new(nil))
conn.get('/hello')
end
end
context 'with default formatter' do
let(:formatter) { instance_double(Faraday::Logging::Formatter, request: true, response: true, filter: []) }
before { allow(Faraday::Logging::Formatter).to receive(:new).and_return(formatter) }
it 'delegates logging to the formatter' do
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
expect(formatter).to receive(:response).with(an_instance_of(Faraday::Env))
conn.get '/hello'
end
context 'when no route' do
it 'delegates logging to the formatter' do
expect(formatter).to receive(:request).with(an_instance_of(Faraday::Env))
expect(formatter).to receive(:exception).with(an_instance_of(Faraday::Adapter::Test::Stubs::NotFound))
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
end
end
end
context 'with custom formatter' do
let(:formatter_class) do
Class.new(Faraday::Logging::Formatter) do
def request(_env)
info 'Custom log formatter request'
end
def response(_env)
info 'Custom log formatter response'
end
end
end
let(:logger_options) { { formatter: formatter_class } }
it 'logs with custom formatter' do
conn.get '/hello'
expect(string_io.string).to match('Custom log formatter request')
expect(string_io.string).to match('Custom log formatter response')
end
end
it 'logs method and url' do
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).to match('GET http:/hello')
end
it 'logs status' do
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).to match('Status 200')
end
it 'does not log error message by default' do
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
expect(string_io.string).not_to match(%(no stubbed request for get http:/noroute))
end
it 'logs request headers by default' do
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).to match(%(Accept: "text/html))
end
it 'logs response headers by default' do
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).to match(%(Content-Type: "text/html))
end
it 'does not log request body by default' do
conn.post '/ohai', 'name=Unagi', accept: 'text/html'
expect(string_io.string).not_to match(%(name=Unagi))
end
it 'does not log response body by default' do
conn.post '/ohai', 'name=Toro', accept: 'text/html'
expect(string_io.string).not_to match(%(fred))
end
it 'logs filter headers' do
conn.headers = { 'api_key' => 'ABC123' }
conn.get '/filtered_headers', nil, accept: 'text/html'
expect(string_io.string).to match(%(api_key:))
expect(string_io.string).to match(%([API_KEY]))
expect(string_io.string).not_to match(%(ABC123))
end
it 'logs filter url' do
conn.get '/filtered_url?password=hunter2', nil, accept: 'text/html'
expect(string_io.string).to match(%([HIDDEN]))
expect(string_io.string).not_to match(%(hunter2))
end
context 'when not logging request headers' do
let(:logger_options) { { headers: { request: false } } }
it 'does not log request headers if option is false' do
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).not_to match(%(Accept: "text/html))
end
end
context 'when not logging response headers' do
let(:logger_options) { { headers: { response: false } } }
it 'does not log response headers if option is false' do
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).not_to match(%(Content-Type: "text/html))
end
end
context 'when logging request body' do
let(:logger_options) { { bodies: { request: true } } }
it 'log only request body' do
conn.post '/ohyes', 'name=Tamago', accept: 'text/html'
expect(string_io.string).to match(%(name=Tamago))
expect(string_io.string).not_to match(%(pebbles))
end
end
context 'when logging response body' do
let(:logger_options) { { bodies: { response: true } } }
it 'log only response body' do
conn.post '/ohyes', 'name=Hamachi', accept: 'text/html'
expect(string_io.string).to match(%(pebbles))
expect(string_io.string).not_to match(%(name=Hamachi))
end
end
context 'when logging request and response bodies' do
let(:logger_options) { { bodies: true } }
it 'log request and response body' do
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
expect(string_io.string).to match(%(name=Ebi))
expect(string_io.string).to match(%(pebbles))
end
it 'log response body object' do
conn.get '/rubbles', nil, accept: 'text/html'
expect(string_io.string).to match(%([\"Barney\", \"Betty\", \"Bam Bam\"]\n))
end
it 'logs filter body' do
conn.get '/filtered_body', nil, accept: 'text/html'
expect(string_io.string).to match(%(soylent green is))
expect(string_io.string).to match(%(tasty))
expect(string_io.string).not_to match(%(people))
end
end
context 'when logging errors' do
let(:logger_options) { { errors: true } }
it 'logs error message' do
expect { conn.get '/noroute' }.to raise_error(Faraday::Adapter::Test::Stubs::NotFound)
expect(string_io.string).to match(%(no stubbed request for get http:/noroute))
end
end
context 'when logging headers and errors' do
let(:logger_options) { { headers: true, errors: true } }
it 'logs error message' do
expect { conn.get '/connection_failed' }.to raise_error(Faraday::ConnectionFailed)
expect(string_io.string).to match(%(Failed to open TCP connection))
end
end
context 'when using log_level' do
let(:logger_options) { { bodies: true, log_level: :debug } }
it 'logs request/request body on the specified level (debug)' do
logger.level = Logger::DEBUG
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
expect(string_io.string).to match(%(name=Ebi))
expect(string_io.string).to match(%(pebbles))
end
it 'logs headers on the debug level' do
logger.level = Logger::DEBUG
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).to match(%(Content-Type: "text/html))
end
it 'does not log request/response body on the info level' do
logger.level = Logger::INFO
conn.post '/ohyes', 'name=Ebi', accept: 'text/html'
expect(string_io.string).not_to match(%(name=Ebi))
expect(string_io.string).not_to match(%(pebbles))
end
it 'does not log headers on the info level' do
logger.level = Logger::INFO
conn.get '/hello', nil, accept: 'text/html'
expect(string_io.string).not_to match(%(Content-Type: "text/html))
end
end
end