174 lines
5.1 KiB
Ruby
174 lines
5.1 KiB
Ruby
# typed: true
|
|
class HttpClientMockHelpers
|
|
extend T::Sig
|
|
include HasColorLogger
|
|
extend FactoryBot::Syntax::Methods
|
|
extend RSpec::Mocks::ExampleMethods
|
|
extend RSpec::Matchers
|
|
|
|
def self.init_from_manifest(http_client_mock, manifest_directory_path)
|
|
manifest =
|
|
YAML.safe_load(
|
|
File.read(Rails.root.join(manifest_directory_path, "manifest.yml")),
|
|
)
|
|
|
|
requests =
|
|
manifest.map do |request_info|
|
|
{
|
|
uri: request_info["url"],
|
|
content_type:
|
|
(
|
|
if request_info["url"].include?(".json")
|
|
"application/json"
|
|
else
|
|
"text/html"
|
|
end
|
|
),
|
|
contents:
|
|
File.read(
|
|
Rails.root.join(manifest_directory_path, request_info["file"]),
|
|
),
|
|
status_code: request_info["status"],
|
|
method: request_info["method"],
|
|
caused_by_entry: :any,
|
|
requested_at: request_info["requested_at"],
|
|
}
|
|
end
|
|
|
|
HttpClientMockHelpers.init_http_client_mock(
|
|
http_client_mock,
|
|
requests,
|
|
any_order: true,
|
|
)
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
http_client_mock: Scraper::HttpClient,
|
|
requests: T::Array[T.untyped],
|
|
any_order: T::Boolean,
|
|
).returns(T::Array[HttpLogEntry])
|
|
end
|
|
def self.init_http_client_mock(http_client_mock, requests, any_order: false)
|
|
if any_order
|
|
init_any_order(http_client_mock, requests)
|
|
else
|
|
init_ordered(http_client_mock, requests)
|
|
end
|
|
end
|
|
|
|
sig do
|
|
params(requests: T::Array[T.untyped], any_order: T::Boolean).returns(
|
|
T::Array[HttpLogEntry],
|
|
)
|
|
end
|
|
def self.init_with(requests, any_order: false)
|
|
if any_order
|
|
init_any_order(Scraper::ClientFactory.http_client_mock, requests)
|
|
else
|
|
init_ordered(Scraper::ClientFactory.http_client_mock, requests)
|
|
end
|
|
end
|
|
|
|
def self.init_ordered(http_client_mock, requests)
|
|
log_entries = []
|
|
|
|
requests.each do |request|
|
|
sha256 = Digest::SHA256.digest(request[:contents])
|
|
log_entry =
|
|
build(
|
|
:http_log_entry,
|
|
uri: request[:uri],
|
|
verb: :get,
|
|
content_type: request[:content_type],
|
|
status_code: request[:status_code] || 200,
|
|
performed_by: "direct",
|
|
response_time_ms: rand(20..100),
|
|
requested_at: request[:requested_at] || Time.now,
|
|
request_headers: build(:http_log_entry_header),
|
|
response_headers: build(:http_log_entry_header),
|
|
response:
|
|
BlobFile.find_by(sha256: sha256) ||
|
|
build(
|
|
:blob_file,
|
|
content_type: request[:content_type],
|
|
contents: request[:contents],
|
|
),
|
|
)
|
|
log_entry.save!
|
|
log_entries << log_entry
|
|
caused_by_entry = nil
|
|
if request[:caused_by_entry_idx]
|
|
caused_by_entry = log_entries[request[:caused_by_entry_idx]]
|
|
elsif request[:caused_by_entry] == :any
|
|
caused_by_entry = :any
|
|
elsif request[:caused_by_entry]
|
|
caused_by_entry = request[:caused_by_entry]
|
|
end
|
|
|
|
method = request[:method] || :get
|
|
expect(http_client_mock).to(
|
|
receive(method).with(
|
|
log_entry.uri.to_s,
|
|
http_client_opts_with(
|
|
caused_by_entry: caused_by_entry,
|
|
use_http_cache: request[:use_http_cache],
|
|
),
|
|
) do |uri, opts|
|
|
logger.info "[mock http client] [#{method}] [#{uri}] [#{opts.inspect.truncate(80)}]"
|
|
Scraper::HttpClient::Response.new(
|
|
status_code: log_entry.status_code,
|
|
body: log_entry.response.content_bytes,
|
|
log_entry: log_entry,
|
|
)
|
|
end,
|
|
)
|
|
end
|
|
|
|
log_entries
|
|
end
|
|
|
|
def self.init_any_order(http_client_mock, requests)
|
|
log_entries_by_uri =
|
|
requests
|
|
.map do |request|
|
|
sha256 = Digest::SHA256.digest(request[:contents])
|
|
log_entry =
|
|
create(
|
|
:http_log_entry,
|
|
uri: request[:uri],
|
|
verb: :get,
|
|
content_type: request[:content_type],
|
|
status_code: request[:status_code] || 200,
|
|
performed_by: "direct",
|
|
response_time_ms: rand(20..100),
|
|
response:
|
|
BlobFile.find_by(sha256: sha256) ||
|
|
build(
|
|
:blob_file,
|
|
content_type: request[:content_type],
|
|
contents: request[:contents],
|
|
),
|
|
)
|
|
[request[:uri], log_entry]
|
|
end
|
|
.to_h
|
|
|
|
allow(http_client_mock).to receive(:get) do |uri, opts|
|
|
log_entry = log_entries_by_uri[uri]
|
|
expect(log_entry).not_to(
|
|
be_nil,
|
|
"no log entry found for uri: #{uri}\nValid uris: \n#{log_entries_by_uri.keys.join("\n")}",
|
|
)
|
|
logger.info "[mock http client] [get] [#{uri}] [#{opts.inspect.truncate(80)}]"
|
|
Scraper::HttpClient::Response.new(
|
|
status_code: log_entry.status_code,
|
|
body: log_entry.response.content_bytes,
|
|
log_entry: log_entry,
|
|
)
|
|
end
|
|
|
|
log_entries_by_uri.values
|
|
end
|
|
end
|