Skip to content

Commit

Permalink
Use a real HTTP server instead of Webmock
Browse files Browse the repository at this point in the history
  • Loading branch information
ursm committed Jul 7, 2024
1 parent 45a50cd commit b71ad76
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 84 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ source 'https://rubygems.org'

gemspec

gem 'rackup'
gem 'rake'
gem 'rspec'
gem 'webmock'
21 changes: 5 additions & 16 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,15 @@ PATH
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
bigdecimal (3.1.8)
crack (1.0.0)
bigdecimal
rexml
diff-lcs (1.5.1)
hashdiff (1.1.0)
marcel (1.0.4)
net-http (0.4.1)
uri
public_suffix (6.0.0)
rack (3.1.6)
rackup (2.1.0)
rack (>= 3)
webrick (~> 1.8)
rake (13.2.1)
rexml (3.3.1)
strscan
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
Expand All @@ -41,22 +34,18 @@ GEM
rspec-support (~> 3.13.0)
rspec-support (3.13.1)
singleton (0.2.0)
strscan (3.1.0)
uri (0.13.0)
webmock (3.23.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.8.1)

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
fetch-api!
rackup
rake
rspec
webmock

BUNDLED WITH
2.5.14
111 changes: 48 additions & 63 deletions spec/fetch/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,21 @@
include Fetch::API

example 'simple get' do
stub_request(:get, 'http://example.com').to_return(
headers: {
'Content-Type' => 'text/plain'
},

body: 'Hello, world!'
)

res = fetch('http://example.com')
res = fetch('http://localhost:4423')

expect(res.url).to eq('http://example.com')
expect(res.url).to eq('http://localhost:4423')
expect(res.status).to eq(200)
expect(res.headers.to_h).to eq('content-type' => 'text/plain')
expect(res.body).to eq('Hello, world!')
expect(res.headers.to_h).to include('content-type' => 'application/json')
expect(res.redirected).to eq(false)
end

example 'https' do
stub_request :get, 'https://example.com'

res = fetch('https://example.com')

expect(res.status).to eq(200)
expect(res.json(symbolize_names: true)).to include(
method: 'GET',
body: ''
)
end

example 'post JSON' do
stub_request :post, 'http://example.com'

fetch 'http://example.com', **{
res = fetch('http://localhost:4423', **{
method: :post,

headers: {
Expand All @@ -42,39 +28,41 @@
body: {
name: 'Alice'
}.to_json
}
})

expect(WebMock).to have_requested(:post, 'http://example.com').with(
headers: {
'Content-Type' => 'application/json'
},
expect(res.json(symbolize_names: true)).to match(
method: 'POST',

headers: include(
'content-type': 'application/json'
),

body: '{"name":"Alice"}'
)
end

example 'post urlencoded' do
stub_request :post, 'http://example.com'

fetch 'http://example.com', **{
res = fetch('http://localhost:4423', **{
method: :post,
body: Fetch::URLSearchParams.new(name: 'Alice')
}
})

expect(WebMock).to have_requested(:post, 'http://example.com').with(
headers: {
'Content-Type' => 'application/x-www-form-urlencoded'
},
expect(res.json(symbolize_names: true)).to match(
method: 'POST',

headers: include(
'content-type': 'application/x-www-form-urlencoded'
),

body: 'name=Alice'
)
end

example 'post multipart' do
stub_request :post, 'http://example.com'
res = nil

File.open 'spec/fixtures/files/foo.txt' do |f|
fetch 'http://example.com', **{
res = fetch('http://localhost:4423', **{
method: :post,

headers: {
Expand All @@ -85,51 +73,48 @@
name: 'Alice',
file: f
)
}
})
end

expect(WebMock).to have_requested(:post, 'http://example.com').with(
headers: {
'Content-Type' => 'multipart/form-data'
}
)
expect(res.json(symbolize_names: true)).to match(
method: 'POST',

# The request body should be sent correctly, but with webmock, the body becomes nil.
end
headers: include(
'content-type': start_with('multipart/form-data; boundary=')
),

example 'redirect: follow' do
stub_request(:get, 'http://example.com').to_return(status: 302, headers: {
'Location' => 'http://example.com/redirected'
})
body: include(<<~NAME.gsub("\n", "\r\n"), <<~FILE.gsub("\n", "\r\n"))
Content-Disposition: form-data; name="name"
stub_request :get, 'http://example.com/redirected'
Alice
NAME
Content-Disposition: form-data; name="file"; filename="foo.txt"
Content-Type: application/octet-stream
res = fetch('http://example.com', redirect: :follow)
bar
FILE
)
end

example 'redirect: follow' do
res = fetch('http://localhost:4423/redirect', redirect: :follow)

expect(res.status).to eq(200)
expect(res.redirected).to eq(true)

expect(WebMock).to have_requested(:get, 'http://example.com/redirected')
expect(res.url).to eq('http://localhost:4423/redirected')
end

example 'redirect: error' do
stub_request(:get, 'http://example.com').to_return(status: 302, headers: {
'Location' => 'http://example.com/redirected'
})

expect {
fetch 'http://example.com', redirect: :error
fetch 'http://localhost:4423/redirect', redirect: :error
}.to raise_error(Fetch::RedirectError)
end

example 'redirect: manual' do
stub_request(:get, 'http://example.com').to_return(status: 302, headers: {
'Location' => 'http://example.com/redirected'
})

res = fetch('http://example.com', redirect: :manual)
res = fetch('http://localhost:4423/redirect', redirect: :manual)

expect(res.status).to eq(302)
expect(res.redirected).to eq(false)
expect(res.url).to eq('http://localhost:4423/redirect')
end
end
2 changes: 1 addition & 1 deletion spec/fixtures/files/foo.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bar
bar
63 changes: 63 additions & 0 deletions spec/support/stub_server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'json'
require 'net/http'
require 'rack/request'
require 'rackup'

app = -> (env) {
req = Rack::Request.new(env)

headers = req.each_header.to_h.select {|k,|
k.start_with?('HTTP_') || %w(CONTENT_TYPE CONTENT_LENGTH).include?(k)
}.transform_keys {|k|
k.delete_prefix('HTTP_').downcase.tr('_', '-')
}

case req.path
when '/redirect'
[302, {'Location' => '/redirected'}, []]
else
[
200,
{
'Content-Type' => 'application/json'
},
[
{
method: req.request_method,
headers: ,
body: req.body.read,
}.to_json
]
]
end
}

RSpec.configure do |config|
server = nil

config.before :suite do
server = Thread.new {
Rackup::Server.start(
app: ,
Port: 4423,
Logger: WEBrick::BasicLog.new('/dev/null'),
AccessLog: []
)
}

uri = URI('http://localhost:4423')

Timeout.timeout 3 do
loop do
Net::HTTP.get uri
break
rescue Errno::ECONNREFUSED
sleep 0.1
end
end
end

config.after :suite do
server.kill
end
end
3 changes: 0 additions & 3 deletions spec/support/webmock.rb

This file was deleted.

0 comments on commit b71ad76

Please sign in to comment.