This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Callbacks do
|
||||
let!(:easy) { Ethon::Easy.new }
|
||||
|
||||
describe "#set_callbacks" do
|
||||
before do
|
||||
expect(Ethon::Curl).to receive(:set_option).exactly(3).times
|
||||
end
|
||||
|
||||
it "sets write-, debug-, and headerfunction" do
|
||||
easy.set_callbacks
|
||||
end
|
||||
|
||||
it "resets @response_body" do
|
||||
easy.set_callbacks
|
||||
expect(easy.instance_variable_get(:@response_body)).to eq("")
|
||||
end
|
||||
|
||||
it "resets @response_headers" do
|
||||
easy.set_callbacks
|
||||
expect(easy.instance_variable_get(:@response_headers)).to eq("")
|
||||
end
|
||||
|
||||
it "resets @debug_info" do
|
||||
easy.set_callbacks
|
||||
expect(easy.instance_variable_get(:@debug_info).to_a).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#progress_callback" do
|
||||
it "returns 0" do
|
||||
expect(easy.progress_callback.call(0,1,1,1,1)).to be(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#body_write_callback" do
|
||||
let(:body_write_callback) { easy.instance_variable_get(:@body_write_callback) }
|
||||
let(:stream) { double(:read_string => "") }
|
||||
context "when body returns not :abort" do
|
||||
it "returns number bigger than 0" do
|
||||
expect(body_write_callback.call(stream, 1, 1, nil) > 0).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "when body returns :abort" do
|
||||
before do
|
||||
easy.on_body.clear
|
||||
easy.on_body { :abort }
|
||||
end
|
||||
let(:body_write_callback) { easy.instance_variable_get(:@body_write_callback) }
|
||||
|
||||
it "returns -1 to indicate abort to libcurl" do
|
||||
expect(body_write_callback.call(stream, 1, 1, nil)).to eq(-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#header_write_callback" do
|
||||
let(:header_write_callback) { easy.instance_variable_get(:@header_write_callback) }
|
||||
let(:stream) { double(:read_string => "") }
|
||||
context "when header returns not :abort" do
|
||||
it "returns number bigger than 0" do
|
||||
expect(header_write_callback.call(stream, 1, 1, nil) > 0).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "when header returns :abort" do
|
||||
before do
|
||||
easy.on_headers.clear
|
||||
easy.on_headers { :abort }
|
||||
end
|
||||
let(:header_write_callback) { easy.instance_variable_get(:@header_write_callback) }
|
||||
|
||||
it "returns -1 to indicate abort to libcurl" do
|
||||
expect(header_write_callback.call(stream, 1, 1, nil)).to eq(-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::DebugInfo do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
before do
|
||||
easy.url = "http://localhost:3001/"
|
||||
easy.perform
|
||||
end
|
||||
|
||||
describe "#debug_info" do
|
||||
context "when verbose is not set to true" do
|
||||
it "does not save any debug info after a request" do
|
||||
expect(easy.debug_info.to_a.length).to eq(0)
|
||||
expect(easy.debug_info.to_h.values.flatten.length).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
context "when verbose is set to true" do
|
||||
before do
|
||||
easy.verbose = true
|
||||
easy.perform
|
||||
end
|
||||
|
||||
after do
|
||||
easy.verbose = false
|
||||
easy.reset
|
||||
end
|
||||
|
||||
it "saves debug info after a request" do
|
||||
expect(easy.debug_info.to_a.length).to be > 0
|
||||
end
|
||||
|
||||
it "saves request headers" do
|
||||
expect(easy.debug_info.header_out.join).to include('GET / HTTP/1.1')
|
||||
end
|
||||
|
||||
it "saves response headers" do
|
||||
expect(easy.debug_info.header_in.length).to be > 0
|
||||
expect(easy.response_headers).to include(easy.debug_info.header_in.join)
|
||||
end
|
||||
|
||||
it "saves incoming data" do
|
||||
expect(easy.debug_info.data_in.length).to be > 0
|
||||
expect(easy.response_body).to include(easy.debug_info.data_in.join)
|
||||
end
|
||||
|
||||
it "saves debug text" do
|
||||
expect(easy.debug_info.text.length).to be > 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Informations do
|
||||
|
||||
describe "#supports_asynch_dns?" do
|
||||
it "returns boolean" do
|
||||
expect([true, false].include? Ethon::Easy.supports_asynch_dns?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe "#supports_zlib?" do
|
||||
it "returns boolean" do
|
||||
expect([true, false].include? Ethon::Easy.supports_zlib?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe "#supports_timeout_ms?" do
|
||||
it "returns boolean" do
|
||||
expect([true, false].include? Ethon::Easy.supports_timeout_ms?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,104 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Form do
|
||||
let(:hash) { {} }
|
||||
let!(:easy) { Ethon::Easy.new }
|
||||
let(:form) { Ethon::Easy::Form.new(easy, hash) }
|
||||
|
||||
describe ".new" do
|
||||
it "assigns attribute to @params" do
|
||||
expect(form.instance_variable_get(:@params)).to eq(hash)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#first" do
|
||||
it "returns a pointer" do
|
||||
expect(form.first).to be_a(FFI::Pointer)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#last" do
|
||||
it "returns a pointer" do
|
||||
expect(form.first).to be_a(FFI::Pointer)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#multipart?" do
|
||||
before { form.instance_variable_set(:@query_pairs, pairs) }
|
||||
|
||||
context "when query_pairs contains string values" do
|
||||
let(:pairs) { [['a', '1'], ['b', '2']] }
|
||||
|
||||
it "returns false" do
|
||||
expect(form.multipart?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs contains file" do
|
||||
let(:pairs) { [['a', '1'], ['b', ['path', 'encoding', 'abs_path']]] }
|
||||
|
||||
it "returns true" do
|
||||
expect(form.multipart?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context "when options contains multipart=true" do
|
||||
before { form.instance_variable_set(:@multipart, true) }
|
||||
let(:pairs) { [['a', '1'], ['b', '2']] }
|
||||
|
||||
it "returns true" do
|
||||
expect(form.multipart?).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#materialize" do
|
||||
before { form.instance_variable_set(:@query_pairs, pairs) }
|
||||
|
||||
context "when query_pairs contains string values" do
|
||||
let(:pairs) { [['a', '1']] }
|
||||
|
||||
it "adds params to form" do
|
||||
expect(Ethon::Curl).to receive(:formadd)
|
||||
form.materialize
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs contains nil" do
|
||||
let(:pairs) { [['a', nil]] }
|
||||
|
||||
it "adds params to form" do
|
||||
expect(Ethon::Curl).to receive(:formadd)
|
||||
form.materialize
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs contains file" do
|
||||
let(:pairs) { [['a', ["file", "type", "path/file"]]] }
|
||||
|
||||
it "adds file to form" do
|
||||
expect(Ethon::Curl).to receive(:formadd)
|
||||
form.materialize
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs contains file and string values" do
|
||||
let(:pairs) { [['a', ["file", "type", "path/file"]], ['b', '1']] }
|
||||
|
||||
it "adds file to form" do
|
||||
expect(Ethon::Curl).to receive(:formadd).twice
|
||||
form.materialize
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs contains file, string and int values" do
|
||||
let(:pairs) { [['a', ["file", "type", "path/file"]], ['b', '1'], ['c', 1]] }
|
||||
|
||||
it "adds file to form" do
|
||||
expect(Ethon::Curl).to receive(:formadd).exactly(3).times
|
||||
form.materialize
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Header do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
describe "#headers=" do
|
||||
let(:headers) { { 'User-Agent' => 'Ethon' } }
|
||||
|
||||
it "sets header" do
|
||||
expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks)
|
||||
expect(Ethon::Curl).to receive(:set_option)
|
||||
easy.headers = headers
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = headers
|
||||
easy.url = "http://localhost:3001"
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "sends" do
|
||||
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
|
||||
end
|
||||
|
||||
context "when header value contains null byte" do
|
||||
let(:headers) { { 'User-Agent' => "Ethon\0" } }
|
||||
|
||||
it "escapes" do
|
||||
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon\\\\0"')
|
||||
end
|
||||
end
|
||||
|
||||
context "when header value has leading whitespace" do
|
||||
let(:headers) { { 'User-Agent' => " Ethon" } }
|
||||
|
||||
it "removes" do
|
||||
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
|
||||
end
|
||||
end
|
||||
|
||||
context "when header value has traiing whitespace" do
|
||||
let(:headers) { { 'User-Agent' => "Ethon " } }
|
||||
|
||||
it "removes" do
|
||||
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#compose_header" do
|
||||
it "has space in between" do
|
||||
expect(easy.compose_header('a', 'b')).to eq('a: b')
|
||||
end
|
||||
|
||||
context "when value is a symbol" do
|
||||
it "works" do
|
||||
expect{ easy.compose_header('a', :b) }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#header_list" do
|
||||
context "when no set_headers" do
|
||||
it "returns nil" do
|
||||
expect(easy.header_list).to eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context "when set_headers" do
|
||||
it "returns pointer to header list" do
|
||||
easy.headers = {'User-Agent' => 'Custom'}
|
||||
expect(easy.header_list).to be_a(FFI::Pointer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,177 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Custom do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:custom) { described_class.new("PURGE", url, {:params => params, :body => form}) }
|
||||
|
||||
describe "#setup" do
|
||||
context "when nothing" do
|
||||
it "sets url" do
|
||||
custom.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
|
||||
it "makes a custom request" do
|
||||
custom.setup(easy)
|
||||
easy.perform
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
|
||||
end
|
||||
end
|
||||
|
||||
context "when params" do
|
||||
let(:params) { {:a => "1&"} }
|
||||
|
||||
it "attaches escaped to url" do
|
||||
custom.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26")
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
custom.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "is a custom verb" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
|
||||
end
|
||||
|
||||
it "does not use application/x-www-form-urlencoded content type" do
|
||||
expect(easy.response_body).to_not include('"CONTENT_TYPE":"application/x-www-form-urlencoded"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?a=1%26"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when body" do
|
||||
context "when multipart" do
|
||||
let(:form) { {:a => File.open(__FILE__, 'r')} }
|
||||
|
||||
it "sets httppost" do
|
||||
expect(easy).to receive(:httppost=)
|
||||
custom.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
custom.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a custom verb" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
|
||||
end
|
||||
|
||||
it "uses multipart/form-data content type" do
|
||||
expect(easy.response_body).to include('"CONTENT_TYPE":"multipart/form-data')
|
||||
end
|
||||
|
||||
it "submits a body" do
|
||||
expect(easy.response_body).to match('"body":".+"')
|
||||
end
|
||||
|
||||
it "submits the data" do
|
||||
expect(easy.response_body).to include('"filename":"custom_spec.rb"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when not multipart" do
|
||||
let(:form) { {:a => "1&b=2"} }
|
||||
let(:encoded) { "a=1%26b%3D2" }
|
||||
|
||||
it "sets escaped copypostfields" do
|
||||
expect(easy).to receive(:copypostfields=).with(encoded)
|
||||
custom.setup(easy)
|
||||
end
|
||||
|
||||
it "sets postfieldsize" do
|
||||
expect(easy).to receive(:postfieldsize=).with(encoded.bytesize)
|
||||
custom.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
custom.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a custom verb" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PURGE"')
|
||||
end
|
||||
|
||||
it "uses multipart/form-data content type" do
|
||||
expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded')
|
||||
end
|
||||
|
||||
it "submits a body" do
|
||||
expect(easy.response_body).to match('"body":"a=1%26b%3D2"')
|
||||
end
|
||||
|
||||
it "submits the data" do
|
||||
expect(easy.response_body).to include('"rack.request.form_hash":{"a":"1&b=2"}')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when string" do
|
||||
let(:form) { "{a: 1}" }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
custom.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "sends string" do
|
||||
expect(easy.response_body).to include('"body":"{a: 1}"')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when params and body" do
|
||||
let(:form) { {:a => "1"} }
|
||||
let(:params) { {:b => "2"} }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
custom.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "url contains params" do
|
||||
expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?b=2"')
|
||||
end
|
||||
|
||||
it "body contains form" do
|
||||
expect(easy.response_body).to include('"body":"a=1"')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Delete do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:delete) { described_class.new(url, {:params => params, :body => form}) }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
delete.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "makes a delete request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"DELETE"')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Get do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:options) { {} }
|
||||
let(:get) { described_class.new(url, {:params => params, :body => form}.merge(options)) }
|
||||
|
||||
describe "#setup" do
|
||||
it "sets url" do
|
||||
get.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
|
||||
context "when body" do
|
||||
let(:form) { { :a => 1 } }
|
||||
|
||||
it "sets customrequest" do
|
||||
expect(easy).to receive(:customrequest=).with("GET")
|
||||
get.setup(easy)
|
||||
end
|
||||
end
|
||||
|
||||
context "when no body" do
|
||||
it "doesn't set customrequest" do
|
||||
expect(easy).to receive(:customrequest=).never
|
||||
get.setup(easy)
|
||||
end
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
get.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
context "when url already contains params" do
|
||||
let(:url) { "http://localhost:3001/?query=here" }
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a get request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"GET"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
|
||||
context "when params and no body" do
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a get request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"GET"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
|
||||
context "when params and body" do
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
let(:form) { {:b => "2"} }
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a get request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"GET"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
|
||||
context "with :escape" do
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
|
||||
context 'missing' do
|
||||
it "escapes values" do
|
||||
expect(easy.url).to eq("#{url}?a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
|
||||
context 'nil' do
|
||||
let(:options) { {:escape => nil} }
|
||||
|
||||
it "escapes values" do
|
||||
expect(easy.url).to eq("#{url}?a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
|
||||
context 'true' do
|
||||
let(:options) { {:escape => true} }
|
||||
|
||||
it "escapes values" do
|
||||
expect(easy.url).to eq("#{url}?a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
|
||||
context 'false' do
|
||||
let(:options) { {:escape => false} }
|
||||
|
||||
it "sends raw values" do
|
||||
expect(easy.url).to eq("#{url}?a=1&b=2")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,80 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Head do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:head) { described_class.new(url, {:params => params, :body => form}) }
|
||||
|
||||
describe "#setup" do
|
||||
context "when nothing" do
|
||||
it "sets nobody" do
|
||||
expect(easy).to receive(:nobody=).with(true)
|
||||
head.setup(easy)
|
||||
end
|
||||
|
||||
it "sets url" do
|
||||
head.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
end
|
||||
|
||||
context "when params" do
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
|
||||
it "sets nobody" do
|
||||
expect(easy).to receive(:nobody=).with(true)
|
||||
head.setup(easy)
|
||||
end
|
||||
|
||||
it "attaches escaped to url" do
|
||||
head.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26b%3D2")
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
head.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "has no body" do
|
||||
expect(easy.response_body).to be_empty
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2")
|
||||
end
|
||||
|
||||
context "when url already contains params" do
|
||||
let(:url) { "http://localhost:3001/?query=here" }
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when body" do
|
||||
let(:form) { {:a => 1} }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
head.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Options do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:options) { described_class.new(url, {:params => params, :body => form}) }
|
||||
|
||||
describe "#setup" do
|
||||
it "sets customrequest" do
|
||||
expect(easy).to receive(:customrequest=).with("OPTIONS")
|
||||
options.setup(easy)
|
||||
end
|
||||
|
||||
it "sets url" do
|
||||
options.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
|
||||
before do
|
||||
options.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a options request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"OPTIONS"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2")
|
||||
end
|
||||
|
||||
context "when url already contains params" do
|
||||
let(:url) { "http://localhost:3001/?query=here" }
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Patch do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:patch) { described_class.new(url, {:params => params, :body => form}) }
|
||||
|
||||
describe "#setup" do
|
||||
it "sets customrequest" do
|
||||
expect(easy).to receive(:customrequest=).with("PATCH")
|
||||
patch.setup(easy)
|
||||
end
|
||||
|
||||
it "sets url" do
|
||||
patch.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
let(:params) { {:a => "1&b=2"} }
|
||||
|
||||
before do
|
||||
patch.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a patch request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PATCH"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?a=1%26b%3D2")
|
||||
end
|
||||
|
||||
context "when url already contains params" do
|
||||
let(:url) { "http://localhost:3001/?query=here" }
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.effective_url).to eq("http://localhost:3001/?query=here&a=1%26b%3D2")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,317 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Post do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:options) { Hash.new }
|
||||
let(:post) { described_class.new(url, options.merge({:params => params, :body => form})) }
|
||||
|
||||
describe "#setup" do
|
||||
context "when nothing" do
|
||||
it "sets url" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
|
||||
it "sets postfield_size" do
|
||||
expect(easy).to receive(:postfieldsize=).with(0)
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
it "sets copy_postfields" do
|
||||
expect(easy).to receive(:copypostfields=).with("")
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
it "makes a post request" do
|
||||
post.setup(easy)
|
||||
easy.perform
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"POST"')
|
||||
end
|
||||
end
|
||||
|
||||
context "when params" do
|
||||
let(:params) { {:a => "1&"} }
|
||||
|
||||
it "attaches escaped to url" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26")
|
||||
end
|
||||
|
||||
context "with arrays" do
|
||||
let(:params) { {:a => %w( foo bar )} }
|
||||
|
||||
context "by default" do
|
||||
it "encodes them with indexes" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a%5B0%5D=foo&a%5B1%5D=bar")
|
||||
end
|
||||
end
|
||||
|
||||
context "when params_encoding is :rack" do
|
||||
let(:options) { {:params_encoding => :rack} }
|
||||
it "encodes them without indexes" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a%5B%5D=foo&a%5B%5D=bar")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with :escape" do
|
||||
context 'missing' do
|
||||
it "escapes values" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26")
|
||||
end
|
||||
end
|
||||
|
||||
context 'nil' do
|
||||
let(:options) { {:escape => nil} }
|
||||
|
||||
it "escapes values" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26")
|
||||
end
|
||||
end
|
||||
|
||||
context 'true' do
|
||||
let(:options) { {:escape => true} }
|
||||
|
||||
it "escapes values" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26")
|
||||
end
|
||||
end
|
||||
|
||||
context 'false' do
|
||||
let(:options) { {:escape => false} }
|
||||
|
||||
it "sends raw values" do
|
||||
post.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1&")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "sets postfieldsize" do
|
||||
expect(easy).to receive(:postfieldsize=).with(0)
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
it "sets copypostfields" do
|
||||
expect(easy).to receive(:copypostfields=).with("")
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
let(:postredir) { nil }
|
||||
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
post.setup(easy)
|
||||
easy.postredir = postredir
|
||||
easy.followlocation = true
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "is a post" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"POST"')
|
||||
end
|
||||
|
||||
it "uses application/x-www-form-urlencoded content type" do
|
||||
expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded"')
|
||||
end
|
||||
|
||||
it "requests parameterized url" do
|
||||
expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?a=1%26"')
|
||||
end
|
||||
|
||||
context "when redirection" do
|
||||
let(:url) { "localhost:3001/redirect" }
|
||||
|
||||
context "when no postredirs" do
|
||||
it "is a get" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"GET"')
|
||||
end
|
||||
end
|
||||
|
||||
unless ENV['TRAVIS']
|
||||
context "when postredirs" do
|
||||
let(:postredir) { :post_all }
|
||||
|
||||
it "is a post" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"POST"')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when body" do
|
||||
context "when multipart" do
|
||||
let(:form) { {:a => File.open(__FILE__, 'r')} }
|
||||
|
||||
it "sets httppost" do
|
||||
expect(easy).to receive(:httppost=)
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
post.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a post" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"POST"')
|
||||
end
|
||||
|
||||
it "uses multipart/form-data content type" do
|
||||
expect(easy.response_body).to include('"CONTENT_TYPE":"multipart/form-data')
|
||||
end
|
||||
|
||||
it "submits a body" do
|
||||
expect(easy.response_body).to match('"body":".+"')
|
||||
end
|
||||
|
||||
it "submits the data" do
|
||||
expect(easy.response_body).to include('"filename":"post_spec.rb"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when not multipart" do
|
||||
let(:form) { {:a => "1&b=2"} }
|
||||
let(:encoded) { "a=1%26b%3D2" }
|
||||
|
||||
it "sets escaped copypostfields" do
|
||||
expect(easy).to receive(:copypostfields=).with(encoded)
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
it "sets postfieldsize" do
|
||||
expect(easy).to receive(:postfieldsize=).with(encoded.bytesize)
|
||||
post.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
post.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "is a post" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"POST"')
|
||||
end
|
||||
|
||||
it "uses multipart/form-data content type" do
|
||||
expect(easy.response_body).to include('"CONTENT_TYPE":"application/x-www-form-urlencoded')
|
||||
end
|
||||
|
||||
it "submits a body" do
|
||||
expect(easy.response_body).to match('"body":"a=1%26b%3D2"')
|
||||
end
|
||||
|
||||
it "submits the data" do
|
||||
expect(easy.response_body).to include('"rack.request.form_hash":{"a":"1&b=2"}')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when string" do
|
||||
let(:form) { "{a: 1}" }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
post.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "sends string" do
|
||||
expect(easy.response_body).to include('"body":"{a: 1}"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when binary with null bytes" do
|
||||
let(:form) { [1, 0, 1].pack('c*') }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
post.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "sends binary data" do
|
||||
expect(easy.response_body).to include('"body":"\\u0001\\u0000\\u0001"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when arrays" do
|
||||
let(:form) { {:a => %w( foo bar )} }
|
||||
|
||||
context "by default" do
|
||||
it "sets copypostfields with indexed, escaped representation" do
|
||||
expect(easy).to receive(:copypostfields=).with('a%5B0%5D=foo&a%5B1%5D=bar')
|
||||
post.setup(easy)
|
||||
end
|
||||
end
|
||||
|
||||
context "when params_encoding is :rack" do
|
||||
let(:options) { {:params_encoding => :rack} }
|
||||
|
||||
it "sets copypostfields with non-indexed, escaped representation" do
|
||||
expect(easy).to receive(:copypostfields=).with('a%5B%5D=foo&a%5B%5D=bar')
|
||||
post.setup(easy)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when params and body" do
|
||||
let(:form) { {:a => "1"} }
|
||||
let(:params) { {:b => "2"} }
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
post.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "url contains params" do
|
||||
expect(easy.response_body).to include('"REQUEST_URI":"http://localhost:3001/?b=2"')
|
||||
end
|
||||
|
||||
it "body contains form" do
|
||||
expect(easy.response_body).to include('"body":"a=1"')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,168 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http::Put do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:params) { nil }
|
||||
let(:form) { nil }
|
||||
let(:options) { Hash.new }
|
||||
let(:put) { described_class.new(url, options.merge({:params => params, :body => form})) }
|
||||
|
||||
describe "#setup" do
|
||||
context "when nothing" do
|
||||
it "sets url" do
|
||||
put.setup(easy)
|
||||
expect(easy.url).to eq(url)
|
||||
end
|
||||
|
||||
it "sets upload" do
|
||||
expect(easy).to receive(:upload=).with(true)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
it "sets infilesize" do
|
||||
expect(easy).to receive(:infilesize=).with(0)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
it "makes a put request" do
|
||||
put.setup(easy)
|
||||
easy.perform
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when params" do
|
||||
let(:params) { {:a => "1&"} }
|
||||
|
||||
it "attaches escaped to url" do
|
||||
put.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a=1%26")
|
||||
end
|
||||
|
||||
context "with arrays" do
|
||||
let(:params) { {:a => %w( foo bar )} }
|
||||
|
||||
context "by default" do
|
||||
it "encodes them with indexes" do
|
||||
put.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a%5B0%5D=foo&a%5B1%5D=bar")
|
||||
end
|
||||
end
|
||||
|
||||
context "when params_encoding is :rack" do
|
||||
let(:options) { {:params_encoding => :rack} }
|
||||
it "encodes them without indexes" do
|
||||
put.setup(easy)
|
||||
expect(easy.url).to eq("#{url}?a%5B%5D=foo&a%5B%5D=bar")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "sets upload" do
|
||||
expect(easy).to receive(:upload=).with(true)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
it "sets infilesize" do
|
||||
expect(easy).to receive(:infilesize=).with(0)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
before do
|
||||
put.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "makes a put request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when body" do
|
||||
let(:form) { {:a => "1&b=2"} }
|
||||
|
||||
it "sets infilesize" do
|
||||
expect(easy).to receive(:infilesize=).with(11)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
it "sets readfunction" do
|
||||
expect(easy).to receive(:readfunction)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
it "sets upload" do
|
||||
expect(easy).to receive(:upload=).with(true)
|
||||
put.setup(easy)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
context "sending string body" do
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
put.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "makes a put request" do
|
||||
expect(easy.response_body).to include('"REQUEST_METHOD":"PUT"')
|
||||
end
|
||||
|
||||
it "submits a body" do
|
||||
expect(easy.response_body).to include('"body":"a=1%26b%3D2"')
|
||||
end
|
||||
end
|
||||
|
||||
context "when injecting a file as body" do
|
||||
let(:file) { File.open(__FILE__) }
|
||||
let(:easy) do
|
||||
e = Ethon::Easy.new(:url => url, :upload => true)
|
||||
e.set_read_callback(file)
|
||||
e.infilesize = File.size(file.path)
|
||||
e
|
||||
end
|
||||
|
||||
before do
|
||||
easy.headers = { 'Expect' => '' }
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "submits file" do
|
||||
expect(easy.response_body).to include("injecting")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when arrays" do
|
||||
let(:form) { {:a => %w( foo bar )} }
|
||||
|
||||
before do
|
||||
put.setup(easy)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
context "by default" do
|
||||
it "submits an indexed, escaped representation" do
|
||||
expect(easy.response_body).to include('"body":"a%5B0%5D=foo&a%5B1%5D=bar"')
|
||||
end
|
||||
end
|
||||
|
||||
context "when params_encoding is :rack" do
|
||||
let(:options) { {:params_encoding => :rack} }
|
||||
|
||||
it "submits an non-indexed, escaped representation" do
|
||||
expect(easy.response_body).to include('"body":"a%5B%5D=foo&a%5B%5D=bar"')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when params and body"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,64 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Http do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
describe "#http_request" do
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
let(:action_name) { :get }
|
||||
let(:options) { {} }
|
||||
|
||||
let(:get) { double(:setup) }
|
||||
let(:get_class) { Ethon::Easy::Http::Get }
|
||||
|
||||
it "instanciates action" do
|
||||
expect(get).to receive(:setup)
|
||||
expect(get_class).to receive(:new).and_return(get)
|
||||
easy.http_request(url, action_name, options)
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
[ :get, :post, :put, :delete, :head, :patch, :options ].map do |action|
|
||||
it "returns ok" do
|
||||
easy.http_request(url, action, options)
|
||||
easy.perform
|
||||
expect(easy.return_code).to be(:ok)
|
||||
end
|
||||
|
||||
unless action == :head
|
||||
it "makes a #{action.to_s.upcase} request" do
|
||||
easy.http_request(url, action, options)
|
||||
easy.perform
|
||||
expect(easy.response_body).to include("\"REQUEST_METHOD\":\"#{action.to_s.upcase}\"")
|
||||
end
|
||||
|
||||
it "streams the response body from the #{action.to_s.upcase} request" do
|
||||
bytes_read = 0
|
||||
easy.on_body { |chunk, response| bytes_read += chunk.bytesize }
|
||||
easy.http_request(url, action, options)
|
||||
easy.perform
|
||||
content_length = ((easy.response_headers =~ /Content-Length: (\d+)/) && $1.to_i)
|
||||
expect(bytes_read).to eq(content_length)
|
||||
expect(easy.response_body).to eq("")
|
||||
end
|
||||
|
||||
it "notifies when headers are ready" do
|
||||
headers = []
|
||||
easy.on_headers { |r| headers << r.response_headers }
|
||||
easy.http_request(url, action, options)
|
||||
easy.perform
|
||||
expect(headers).to eq([easy.response_headers])
|
||||
expect(headers.first).to match(/Content-Length: (\d+)/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "makes requests with custom HTTP verbs" do
|
||||
easy.http_request(url, :purge, options)
|
||||
easy.perform
|
||||
expect(easy.response_body).to include(%{"REQUEST_METHOD":"PURGE"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Informations do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
before do
|
||||
easy.url = "http://localhost:3001"
|
||||
easy.perform
|
||||
end
|
||||
|
||||
describe "#httpauth_avail" do
|
||||
it "returns" do
|
||||
expect(easy.httpauth_avail).to be
|
||||
end
|
||||
end
|
||||
|
||||
describe "#total_time" do
|
||||
it "returns float" do
|
||||
expect(easy.total_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#starttransfer_time" do
|
||||
it "returns float" do
|
||||
expect(easy.starttransfer_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#appconnect_time" do
|
||||
it "returns float" do
|
||||
expect(easy.appconnect_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#pretransfer_time" do
|
||||
it "returns float" do
|
||||
expect(easy.pretransfer_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#connect_time" do
|
||||
it "returns float" do
|
||||
expect(easy.connect_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#namelookup_time" do
|
||||
it "returns float" do
|
||||
expect(easy.namelookup_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#redirect_time" do
|
||||
it "returns float" do
|
||||
expect(easy.redirect_time).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#effective_url" do
|
||||
it "returns url" do
|
||||
expect(easy.effective_url).to match(/^http:\/\/localhost:3001\/?/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#primary_ip" do
|
||||
it "returns localhost" do
|
||||
expect(easy.primary_ip).to match(/::1|127\.0\.0\.1/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#response_code" do
|
||||
it "returns 200" do
|
||||
expect(easy.response_code).to eq(200)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#redirect_count" do
|
||||
it "returns 0" do
|
||||
expect(easy.redirect_count).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#redirect_url" do
|
||||
it "returns nil as there is no redirect" do
|
||||
expect(easy.redirect_url).to be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#request_size" do
|
||||
it "returns 53" do
|
||||
expect(easy.request_size).to eq(53)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#supports_zlib?" do
|
||||
it "returns true" do
|
||||
expect(Kernel).to receive(:warn)
|
||||
expect(easy.supports_zlib?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe "#size_upload" do
|
||||
it "returns float" do
|
||||
expect(easy.size_upload).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#size_download" do
|
||||
it "returns float" do
|
||||
expect(easy.size_download).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#speed_upload" do
|
||||
it "returns float" do
|
||||
expect(easy.speed_upload).to be_a(Float)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#speed_download" do
|
||||
it "returns float" do
|
||||
expect(easy.speed_download).to be_a(Float)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Mirror do
|
||||
let(:options) { nil }
|
||||
let(:mirror) { described_class.new(options) }
|
||||
|
||||
describe "::INFORMATIONS_TO_LOG" do
|
||||
[
|
||||
:return_code, :response_code, :response_body, :response_headers,
|
||||
:total_time, :starttransfer_time, :appconnect_time,
|
||||
:pretransfer_time, :connect_time, :namelookup_time, :redirect_time,
|
||||
:size_upload, :size_download, :speed_upload, :speed_upload,
|
||||
:effective_url, :primary_ip, :redirect_count, :redirect_url, :debug_info
|
||||
].each do |name|
|
||||
it "contains #{name}" do
|
||||
expect(described_class::INFORMATIONS_TO_MIRROR).to include(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#to_hash" do
|
||||
let(:options) { {:return_code => 1} }
|
||||
|
||||
it "returns mirror as hash" do
|
||||
expect(mirror.to_hash).to eq(options)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#log_informations" do
|
||||
let(:options) { {:return_code => 1} }
|
||||
|
||||
it "returns hash" do
|
||||
expect(mirror.log_informations).to be_a(Hash)
|
||||
end
|
||||
|
||||
it "only calls methods that exist" do
|
||||
described_class::INFORMATIONS_TO_LOG.each do |method_name|
|
||||
expect(mirror.respond_to? method_name).to eql(true)
|
||||
end
|
||||
end
|
||||
|
||||
it "includes return code" do
|
||||
expect(mirror.log_informations).to include(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,271 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Operations do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
describe "#handle" do
|
||||
it "returns a pointer" do
|
||||
expect(easy.handle).to be_a(FFI::Pointer)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "#perform" do
|
||||
let(:url) { nil }
|
||||
let(:timeout) { nil }
|
||||
let(:connect_timeout) { nil }
|
||||
let(:follow_location) { nil }
|
||||
let(:max_redirs) { nil }
|
||||
let(:user_pwd) { nil }
|
||||
let(:http_auth) { nil }
|
||||
let(:headers) { nil }
|
||||
let(:protocols) { nil }
|
||||
let(:redir_protocols) { nil }
|
||||
let(:username) { nil }
|
||||
let(:password) { nil }
|
||||
|
||||
before do
|
||||
Ethon.logger.level = Logger::DEBUG
|
||||
easy.url = url
|
||||
easy.timeout = timeout
|
||||
easy.connecttimeout = connect_timeout
|
||||
easy.followlocation = follow_location
|
||||
easy.maxredirs = max_redirs
|
||||
easy.httpauth = http_auth
|
||||
easy.headers = headers
|
||||
easy.protocols = protocols
|
||||
easy.redir_protocols = redir_protocols
|
||||
|
||||
if user_pwd
|
||||
easy.userpwd = user_pwd
|
||||
else
|
||||
easy.username = username
|
||||
easy.password = password
|
||||
end
|
||||
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "calls Curl.easy_perform" do
|
||||
expect(Ethon::Curl).to receive(:easy_perform)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "calls Curl.easy_cleanup" do
|
||||
expect_any_instance_of(FFI::AutoPointer).to receive(:free)
|
||||
easy.cleanup
|
||||
end
|
||||
|
||||
it "logs" do
|
||||
expect(Ethon.logger).to receive(:debug)
|
||||
easy.perform
|
||||
end
|
||||
|
||||
it "doesn't log after completing because completing could reset" do
|
||||
easy.on_complete{ expect(Ethon.logger).to receive(:debug).never }
|
||||
easy.perform
|
||||
end
|
||||
|
||||
context "when url" do
|
||||
let(:url) { "http://localhost:3001/" }
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to eq(:ok)
|
||||
end
|
||||
|
||||
it "sets response body" do
|
||||
expect(easy.response_body).to be
|
||||
end
|
||||
|
||||
it "sets response headers" do
|
||||
expect(easy.response_headers).to be
|
||||
end
|
||||
|
||||
context "when request timed out" do
|
||||
let(:url) { "http://localhost:3001/?delay=1" }
|
||||
let(:timeout) { 1 }
|
||||
|
||||
it "returns operation_timedout" do
|
||||
expect(easy.return_code).to eq(:operation_timedout)
|
||||
end
|
||||
end
|
||||
|
||||
context "when connection timed out" do
|
||||
let(:url) { "http://localhost:3009" }
|
||||
let(:connect_timeout) { 1 }
|
||||
|
||||
it "returns couldnt_connect" do
|
||||
expect(easy.return_code).to eq(:couldnt_connect)
|
||||
end
|
||||
end
|
||||
|
||||
context "when no follow location" do
|
||||
let(:url) { "http://localhost:3001/redirect" }
|
||||
let(:follow_location) { false }
|
||||
|
||||
it "doesn't follow" do
|
||||
expect(easy.response_code).to eq(302)
|
||||
expect(easy.redirect_url).to eq("http://localhost:3001/")
|
||||
end
|
||||
end
|
||||
|
||||
context "when follow location" do
|
||||
let(:url) { "http://localhost:3001/redirect" }
|
||||
let(:follow_location) { true }
|
||||
|
||||
it "follows" do
|
||||
expect(easy.response_code).to eq(200)
|
||||
expect(easy.redirect_url).to eq(nil)
|
||||
end
|
||||
|
||||
context "when infinite redirect loop" do
|
||||
let(:url) { "http://localhost:3001/bad_redirect" }
|
||||
let(:max_redirs) { 5 }
|
||||
|
||||
context "when max redirect set" do
|
||||
it "follows only x times" do
|
||||
expect(easy.response_code).to eq(302)
|
||||
expect(easy.redirect_url).to eq("http://localhost:3001/bad_redirect")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when user agent" do
|
||||
let(:headers) { { 'User-Agent' => 'Ethon' } }
|
||||
|
||||
it "sets" do
|
||||
expect(easy.response_body).to include('"HTTP_USER_AGENT":"Ethon"')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when auth url" do
|
||||
before { easy.url = url }
|
||||
|
||||
context "when basic auth" do
|
||||
let(:url) { "http://localhost:3001/auth_basic/username/password" }
|
||||
|
||||
context "when no user_pwd" do
|
||||
it "returns 401" do
|
||||
expect(easy.response_code).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
context "when invalid user_pwd" do
|
||||
let(:user_pwd) { "invalid:invalid" }
|
||||
|
||||
it "returns 401" do
|
||||
expect(easy.response_code).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
context "when valid user_pwd" do
|
||||
let(:user_pwd) { "username:password" }
|
||||
|
||||
it "returns 200" do
|
||||
expect(easy.response_code).to eq(200)
|
||||
end
|
||||
end
|
||||
|
||||
context "when user and password" do
|
||||
let(:username) { "username" }
|
||||
let(:password) { "password" }
|
||||
|
||||
it "returns 200" do
|
||||
expect(easy.response_code).to eq(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when ntlm" do
|
||||
let(:url) { "http://localhost:3001/auth_ntlm" }
|
||||
let(:http_auth) { :ntlm }
|
||||
|
||||
context "when no user_pwd" do
|
||||
it "returns 401" do
|
||||
expect(easy.response_code).to eq(401)
|
||||
end
|
||||
end
|
||||
|
||||
context "when user_pwd" do
|
||||
let(:user_pwd) { "username:password" }
|
||||
|
||||
it "returns 200" do
|
||||
expect(easy.response_code).to eq(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when protocols" do
|
||||
context "when asking for a allowed url" do
|
||||
let(:url) { "http://localhost:3001" }
|
||||
let(:protocols) { :http }
|
||||
|
||||
it "returns ok" do
|
||||
expect(easy.return_code).to be(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context "when asking for a not allowed url" do
|
||||
let(:url) { "http://localhost:3001" }
|
||||
let(:protocols) { :https }
|
||||
|
||||
it "returns unsupported_protocol" do
|
||||
expect(easy.return_code).to be(:unsupported_protocol)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when multiple protocols" do
|
||||
context "when asking for a allowed url" do
|
||||
let(:protocols) { [:http, :https] }
|
||||
|
||||
context "when http" do
|
||||
let(:url) { "http://localhost:3001" }
|
||||
|
||||
it "returns ok for http" do
|
||||
expect(easy.return_code).to be(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context "when https" do
|
||||
let(:url) { "https://localhost:3001" }
|
||||
|
||||
it "returns ssl_connect_error for https" do
|
||||
expect(easy.return_code).to be(:ssl_connect_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when asking for a not allowed url" do
|
||||
let(:url) { "ssh://localhost" }
|
||||
let(:protocols) { [:https, :http] }
|
||||
|
||||
it "returns unsupported_protocol" do
|
||||
expect(easy.return_code).to be(:unsupported_protocol)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when redir_protocols" do
|
||||
context "when redirecting to a not allowed url" do
|
||||
let(:url) { "http://localhost:3001/redirect" }
|
||||
let(:follow_location) { true }
|
||||
let(:redir_protocols) { :https }
|
||||
|
||||
it "returns unsupported_protocol" do
|
||||
expect(easy.return_code).to be(:unsupported_protocol)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when no url" do
|
||||
it "returns url_malformat" do
|
||||
expect(easy.perform).to eq(:url_malformat)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,193 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Options do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
[
|
||||
:accept_encoding, :cainfo, :capath, :connecttimeout, :connecttimeout_ms, :cookie,
|
||||
:cookiejar, :cookiefile, :copypostfields, :customrequest, :dns_cache_timeout,
|
||||
:followlocation, :forbid_reuse, :http_version, :httpauth, :httpget, :httppost,
|
||||
:infilesize, :interface, :keypasswd, :maxredirs, :nobody, :nosignal,
|
||||
:postfieldsize, :postredir, :protocols, :proxy, :proxyauth, :proxyport, :proxytype,
|
||||
:proxyuserpwd, :readdata, :readfunction, :redir_protocols, :ssl_verifyhost,
|
||||
:ssl_verifypeer, :sslcert, :sslcerttype, :sslkey, :sslkeytype, :sslversion,
|
||||
:timeout, :timeout_ms, :unrestricted_auth, :upload, :url, :useragent,
|
||||
:userpwd, :verbose, :pipewait, :dns_shuffle_addresses, :path_as_is
|
||||
].each do |name|
|
||||
describe "#{name}=" do
|
||||
it "responds_to" do
|
||||
expect(easy).to respond_to("#{name}=")
|
||||
end
|
||||
|
||||
it "sets option" do
|
||||
expect_any_instance_of(Ethon::Easy).to receive(:set_callbacks)
|
||||
expect(Ethon::Curl).to receive(:set_option).with(name, anything, anything)
|
||||
value = case name
|
||||
when :http_version
|
||||
:httpv1_0
|
||||
when :httpauth
|
||||
:basic
|
||||
when :protocols, :redir_protocols
|
||||
:http
|
||||
when :postredir
|
||||
:post_301
|
||||
when :proxytype
|
||||
:http
|
||||
when :sslversion
|
||||
:default
|
||||
when :httppost
|
||||
FFI::Pointer::NULL
|
||||
else
|
||||
1
|
||||
end
|
||||
easy.method("#{name}=").call(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#escape?' do
|
||||
context 'by default' do
|
||||
it 'returns true' do
|
||||
expect(easy.escape?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when #escape=nil' do
|
||||
it 'returns true' do
|
||||
easy.escape = nil
|
||||
expect(easy.escape?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when #escape=true' do
|
||||
it 'returns true' do
|
||||
easy.escape = true
|
||||
expect(easy.escape?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when #escape=false' do
|
||||
it 'returns true' do
|
||||
easy.escape = false
|
||||
expect(easy.escape?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#multipart?' do
|
||||
context 'by default' do
|
||||
it 'returns false' do
|
||||
expect(easy.multipart?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'when #multipart=nil' do
|
||||
it 'returns false' do
|
||||
easy.multipart = nil
|
||||
expect(easy.multipart?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
context 'when #multipart=true' do
|
||||
it 'returns true' do
|
||||
easy.multipart = true
|
||||
expect(easy.multipart?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when #multipart=false' do
|
||||
it 'returns false' do
|
||||
easy.multipart = false
|
||||
expect(easy.multipart?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#httppost=" do
|
||||
it "raises unless given a FFI::Pointer" do
|
||||
expect{ easy.httppost = 1 }.to raise_error(Ethon::Errors::InvalidValue)
|
||||
end
|
||||
end
|
||||
|
||||
context "when requesting" do
|
||||
let(:url) { "localhost:3001" }
|
||||
let(:timeout) { nil }
|
||||
let(:timeout_ms) { nil }
|
||||
let(:connecttimeout) { nil }
|
||||
let(:connecttimeout_ms) { nil }
|
||||
let(:userpwd) { nil }
|
||||
|
||||
before do
|
||||
easy.url = url
|
||||
easy.timeout = timeout
|
||||
easy.timeout_ms = timeout_ms
|
||||
easy.connecttimeout = connecttimeout
|
||||
easy.connecttimeout_ms = connecttimeout_ms
|
||||
easy.userpwd = userpwd
|
||||
easy.perform
|
||||
end
|
||||
|
||||
context "when userpwd" do
|
||||
context "when contains /" do
|
||||
let(:url) { "localhost:3001/auth_basic/test/te%2Fst" }
|
||||
let(:userpwd) { "test:te/st" }
|
||||
|
||||
it "works" do
|
||||
expect(easy.response_code).to eq(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when timeout" do
|
||||
let(:timeout) { 1 }
|
||||
|
||||
context "when request takes longer" do
|
||||
let(:url) { "localhost:3001?delay=2" }
|
||||
|
||||
it "times out" do
|
||||
expect(easy.return_code).to eq(:operation_timedout)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when connecttimeout" do
|
||||
let(:connecttimeout) { 1 }
|
||||
|
||||
context "when cannot connect" do
|
||||
let(:url) { "localhost:3002" }
|
||||
|
||||
it "times out" do
|
||||
expect(easy.return_code).to eq(:couldnt_connect)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if Ethon::Easy.supports_timeout_ms?
|
||||
context "when timeout_ms" do
|
||||
let(:timeout_ms) { 100 }
|
||||
|
||||
context "when request takes longer" do
|
||||
let(:url) { "localhost:3001?delay=1" }
|
||||
|
||||
it "times out" do
|
||||
expect(easy.return_code).to eq(:operation_timedout)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when connecttimeout_ms" do
|
||||
let(:connecttimeout_ms) { 100 }
|
||||
|
||||
context "when cannot connect" do
|
||||
let(:url) { "localhost:3002" }
|
||||
|
||||
it "times out" do
|
||||
# this can either lead to a timeout or couldnt connect depending on which happens first
|
||||
expect([:couldnt_connect, :operation_timedout]).to include(easy.return_code)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,235 @@
|
||||
# encoding: utf-8
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Queryable do
|
||||
let(:hash) { {} }
|
||||
let!(:easy) { Ethon::Easy.new }
|
||||
let(:params) { Ethon::Easy::Params.new(easy, hash) }
|
||||
|
||||
describe "#to_s" do
|
||||
context "when query_pairs empty" do
|
||||
before { params.instance_variable_set(:@query_pairs, []) }
|
||||
|
||||
it "returns empty string" do
|
||||
expect(params.to_s).to eq("")
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs not empty" do
|
||||
context "when escape" do
|
||||
before do
|
||||
params.escape = true
|
||||
end
|
||||
|
||||
{
|
||||
'!' => '%21', '*' => '%2A', "'" => '%27', '(' => '%28',
|
||||
')' => '%29', ';' => '%3B', ':' => '%3A', '@' => '%40',
|
||||
'&' => '%26', '=' => '%3D', '+' => '%2B', '$' => '%24',
|
||||
',' => '%2C', '/' => '%2F', '?' => '%3F', '#' => '%23',
|
||||
'[' => '%5B', ']' => '%5D',
|
||||
|
||||
'<' => '%3C', '>' => '%3E', '"' => '%22', '{' => '%7B',
|
||||
'}' => '%7D', '|' => '%7C', '\\' => '%5C', '`' => '%60',
|
||||
'^' => '%5E', '%' => '%25', ' ' => '%20', "\0" => '%00',
|
||||
|
||||
'まつもと' => '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8',
|
||||
}.each do |value, percent|
|
||||
it "turns #{value.inspect} into #{percent}" do
|
||||
params.instance_variable_set(:@query_pairs, [[:a, value]])
|
||||
expect(params.to_s).to eq("a=#{percent}")
|
||||
end
|
||||
end
|
||||
|
||||
{
|
||||
'.' => '%2E', '-' => '%2D', '_' => '%5F', '~' => '%7E',
|
||||
}.each do |value, percent|
|
||||
it "leaves #{value.inspect} instead of turning into #{percent}" do
|
||||
params.instance_variable_set(:@query_pairs, [[:a, value]])
|
||||
expect(params.to_s).to eq("a=#{value}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when no escape" do
|
||||
before { params.instance_variable_set(:@query_pairs, [[:a, 1], [:b, 2]]) }
|
||||
|
||||
it "returns concatenated query string" do
|
||||
expect(params.to_s).to eq("a=1&b=2")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when query_pairs contains a string" do
|
||||
before { params.instance_variable_set(:@query_pairs, ["{a: 1}"]) }
|
||||
|
||||
it "returns correct string" do
|
||||
expect(params.to_s).to eq("{a: 1}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#build_query_pairs" do
|
||||
let(:pairs) { params.method(:build_query_pairs).call(hash) }
|
||||
|
||||
context "when params is empty" do
|
||||
it "returns empty array" do
|
||||
expect(pairs).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params is string" do
|
||||
let(:hash) { "{a: 1}" }
|
||||
|
||||
it "wraps it in an array" do
|
||||
expect(pairs).to eq([hash])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params is simple hash" do
|
||||
let(:hash) { {:a => 1, :b => 2} }
|
||||
|
||||
it "transforms" do
|
||||
expect(pairs).to include([:a, 1])
|
||||
expect(pairs).to include([:b, 2])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params is a nested hash" do
|
||||
let(:hash) { {:a => 1, :b => {:c => 2}} }
|
||||
|
||||
it "transforms" do
|
||||
expect(pairs).to include([:a, 1])
|
||||
expect(pairs).to include(["b[c]", 2])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params contains an array" do
|
||||
let(:hash) { {:a => 1, :b => [2, 3]} }
|
||||
|
||||
context "by default" do
|
||||
it "transforms" do
|
||||
expect(pairs).to include([:a, 1])
|
||||
expect(pairs).to include(["b[0]", 2])
|
||||
expect(pairs).to include(["b[1]", 3])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params_encoding is :rack" do
|
||||
before { params.params_encoding = :rack }
|
||||
it "transforms without indexes" do
|
||||
expect(pairs).to include([:a, 1])
|
||||
expect(pairs).to include(["b[]", 2])
|
||||
expect(pairs).to include(["b[]", 3])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params_encoding is :none" do
|
||||
before { params.params_encoding = :none }
|
||||
it "does no transformation" do
|
||||
expect(pairs).to include([:a, 1])
|
||||
expect(pairs).to include([:b, [2, 3]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when params contains something nested in an array" do
|
||||
context "when string" do
|
||||
let(:hash) { {:a => {:b => ["hello", "world"]}} }
|
||||
|
||||
it "transforms" do
|
||||
expect(pairs).to eq([["a[b][0]", "hello"], ["a[b][1]", "world"]])
|
||||
end
|
||||
end
|
||||
|
||||
context "when hash" do
|
||||
let(:hash) { {:a => {:b => [{:c =>1}, {:d => 2}]}} }
|
||||
|
||||
it "transforms" do
|
||||
expect(pairs).to eq([["a[b][0][c]", 1], ["a[b][1][d]", 2]])
|
||||
end
|
||||
end
|
||||
|
||||
context "when file" do
|
||||
let(:file) { File.open("spec/spec_helper.rb") }
|
||||
let(:file_info) { params.method(:file_info).call(file) }
|
||||
let(:hash) { {:a => {:b => [file]}} }
|
||||
let(:mime_type) { file_info[1] }
|
||||
|
||||
it "transforms" do
|
||||
expect(pairs).to eq([["a[b][0]", file_info]])
|
||||
end
|
||||
|
||||
context "when MIME" do
|
||||
if defined?(MIME)
|
||||
context "when mime type" do
|
||||
it "sets mime type to text" do
|
||||
expect(mime_type).to eq("application/x-ruby")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when no mime type" do
|
||||
let(:file) { Tempfile.new("fubar") }
|
||||
|
||||
it "sets mime type to default application/octet-stream" do
|
||||
expect(mime_type).to eq("application/octet-stream")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when no MIME" do
|
||||
before { hide_const("MIME") }
|
||||
|
||||
it "sets mime type to default application/octet-stream" do
|
||||
expect(mime_type).to eq("application/octet-stream")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
context "when params contains file" do
|
||||
let(:file) { Tempfile.new("fubar") }
|
||||
let(:file_info) { params.method(:file_info).call(file) }
|
||||
let(:hash) { {:a => 1, :b => file} }
|
||||
|
||||
it "transforms" do
|
||||
expect(pairs).to include([:a, 1])
|
||||
expect(pairs).to include([:b, file_info])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params key contains a null byte" do
|
||||
let(:hash) { {:a => "1\0" } }
|
||||
|
||||
it "preserves" do
|
||||
expect(pairs).to eq([[:a, "1\0"]])
|
||||
end
|
||||
end
|
||||
|
||||
context "when params value contains a null byte" do
|
||||
let(:hash) { {"a\0" => 1 } }
|
||||
|
||||
it "preserves" do
|
||||
expect(pairs).to eq([["a\0", 1]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#empty?" do
|
||||
context "when params empty" do
|
||||
it "returns true" do
|
||||
expect(params.empty?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context "when params not empty" do
|
||||
let(:hash) { {:a => 1} }
|
||||
|
||||
it "returns false" do
|
||||
expect(params.empty?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,152 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::ResponseCallbacks do
|
||||
let(:easy) { Ethon::Easy.new }
|
||||
|
||||
[:on_complete, :on_headers, :on_body, :on_progress].each do |callback_type|
|
||||
describe "##{callback_type}" do
|
||||
it "responds" do
|
||||
expect(easy).to respond_to("#{callback_type}")
|
||||
end
|
||||
|
||||
context "when no block given" do
|
||||
it "returns @#{callback_type}" do
|
||||
expect(easy.send("#{callback_type}")).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
context "when block given" do
|
||||
it "stores" do
|
||||
easy.send(callback_type) { p 1 }
|
||||
expect(easy.instance_variable_get("@#{callback_type}").size).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
context "when multiple blocks given" do
|
||||
it "stores" do
|
||||
easy.send(callback_type) { p 1 }
|
||||
easy.send(callback_type) { p 2 }
|
||||
expect(easy.instance_variable_get("@#{callback_type}").size).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#complete" do
|
||||
before do
|
||||
easy.on_complete {|r| String.new(r.url) }
|
||||
end
|
||||
|
||||
it "executes blocks and passes self" do
|
||||
expect(String).to receive(:new).with(easy.url)
|
||||
easy.complete
|
||||
end
|
||||
|
||||
context "when @on_complete nil" do
|
||||
it "doesn't raise" do
|
||||
easy.instance_variable_set(:@on_complete, nil)
|
||||
expect{ easy.complete }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#headers" do
|
||||
before do
|
||||
easy.on_headers {|r| String.new(r.url) }
|
||||
end
|
||||
|
||||
it "executes blocks and passes self" do
|
||||
expect(String).to receive(:new).with(easy.url)
|
||||
easy.headers
|
||||
end
|
||||
|
||||
context "when @on_headers nil" do
|
||||
it "doesn't raise" do
|
||||
easy.instance_variable_set(:@on_headers, nil)
|
||||
expect{ easy.headers }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#progress" do
|
||||
context "when requesting for realz" do
|
||||
it "executes callback" do
|
||||
post = Ethon::Easy::Http::Post.new("http://localhost:3001", {:body => "bar=fu"})
|
||||
post.setup(easy)
|
||||
@called = false
|
||||
@has_dltotal = false
|
||||
@has_ultotal = false
|
||||
easy.on_progress { @called = true }
|
||||
easy.on_progress { |dltotal, _, _, _| @has_dltotal ||= true }
|
||||
easy.on_progress { |_, _, ultotal, _| @has_ultotal ||= true }
|
||||
easy.perform
|
||||
expect(@called).to be true
|
||||
expect(@has_dltotal).to be true
|
||||
expect(@has_ultotal).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context "when pretending" do
|
||||
before do
|
||||
@dltotal = nil
|
||||
@dlnow = nil
|
||||
@ultotal = nil
|
||||
@ulnow = nil
|
||||
easy.on_progress { |dltotal, dlnow, ultotal, ulnow| @dltotal = dltotal ; @dlnow = dlnow; @ultotal = ultotal; @ulnow = ulnow }
|
||||
end
|
||||
|
||||
it "executes blocks and passes dltotal" do
|
||||
easy.progress(1, 2, 3, 4)
|
||||
expect(@dltotal).to eq(1)
|
||||
end
|
||||
|
||||
it "executes blocks and passes dlnow" do
|
||||
easy.progress(1, 2, 3, 4)
|
||||
expect(@dlnow).to eq(2)
|
||||
end
|
||||
|
||||
it "executes blocks and passes ultotal" do
|
||||
easy.progress(1, 2, 3, 4)
|
||||
expect(@ultotal).to eq(3)
|
||||
end
|
||||
|
||||
it "executes blocks and passes ulnow" do
|
||||
easy.progress(1, 2, 3, 4)
|
||||
expect(@ulnow).to eq(4)
|
||||
end
|
||||
|
||||
context "when @on_progress nil" do
|
||||
it "doesn't raise" do
|
||||
easy.instance_variable_set(:@on_progress, nil)
|
||||
expect{ easy.progress(1, 2, 3, 4) }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#body" do
|
||||
before do
|
||||
@chunk = nil
|
||||
@r = nil
|
||||
easy.on_body { |chunk, r| @chunk = chunk ; @r = r }
|
||||
end
|
||||
|
||||
it "executes blocks and passes self" do
|
||||
easy.body("the chunk")
|
||||
expect(@r).to be(easy)
|
||||
end
|
||||
|
||||
it "executes blocks and passes chunk" do
|
||||
easy.body("the chunk")
|
||||
expect(@chunk).to eq("the chunk")
|
||||
end
|
||||
|
||||
context "when @on_body nil" do
|
||||
it "doesn't raise" do
|
||||
easy.instance_variable_set(:@on_body, nil)
|
||||
expect{ easy.body("the chunk") }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Ethon::Easy::Util do
|
||||
class Dummy
|
||||
include Ethon::Easy::Util
|
||||
end
|
||||
|
||||
let(:klass) { Dummy.new }
|
||||
|
||||
describe "escape_zero_byte" do
|
||||
context "when value has no zero byte" do
|
||||
let(:value) { "hello world" }
|
||||
|
||||
it "returns same value" do
|
||||
expect(klass.escape_zero_byte(value)).to be(value)
|
||||
end
|
||||
end
|
||||
|
||||
context "when value has zero byte" do
|
||||
let(:value) { "hello \0world" }
|
||||
|
||||
it "returns escaped" do
|
||||
expect(klass.escape_zero_byte(value)).to eq("hello \\0world")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user