webmock 1.13.0 → 1.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.14.0
4
+
5
+ * Handling non UTF-8 characters in query params.
6
+
7
+ Thanks to [Florian Dütsch](https://github.com/der-flo) for reporting the issue.
8
+
9
+ * Added support for `request_block` param in Excon
10
+
11
+ Thanks to [Dmitry Gutov](https://github.com/dgutov) for reporting the issue.
12
+
13
+ * Fixed compatibility with latest Curb
14
+
15
+ Thanks to [Ian Lesperance](https://github.com/elliterate) and [Matthew Horan](https://github.com/mhoran)
16
+
17
+ * Triggering errbacks assynchronously in em-http-request adapter.
18
+
19
+ Thanks to [Ian Lesperance](https://github.com/elliterate) and [Matthew Horan](https://github.com/mhoran)
20
+
21
+ * Handling query params with a hashes nested inside arrays.
22
+
23
+ Thanks to [Ian Asaff](https://github.com/montague)
24
+
25
+ * Changed NetConnectNotAllowedError to inherit from Exception to allow it to bubble up into a test suite.
26
+
27
+ Thanks to [Daniel van Hoesel](https://github.com/s0meone)
28
+
29
+ * HTTPClient adapter is thread safe.
30
+
31
+ Thanks to [Tom Beauvais](https://github.com/tbeauvais)
32
+
3
33
  ## 1.13.0
4
34
 
5
35
  * Net::HTTP::Persistent compatibility.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- WebMock [![Build Status](https://secure.travis-ci.org/bblimke/webmock.png?branch=master)](http://travis-ci.org/bblimke/webmock) [![Dependency Status](https://gemnasium.com/bblimke/webmock.png)](http://gemnasium.com/bblimke/webmock) [![Stories in Ready](http://badge.waffle.io/bblimke/webmock.png)](http://waffle.io/bblimke/webmock)
1
+ WebMock [![Build Status](https://secure.travis-ci.org/bblimke/webmock.png?branch=master)](http://travis-ci.org/bblimke/webmock) [![Dependency Status](https://gemnasium.com/bblimke/webmock.png)](http://gemnasium.com/bblimke/webmock)
2
2
  =======
3
3
 
4
4
  Library for stubbing and setting expectations on HTTP requests in Ruby.
@@ -258,7 +258,10 @@ Net::HTTP.start("www.example.com") {|http| http.request(req)}.message # ===>
258
258
 
259
259
  ### Replaying raw responses recorded with `curl -is`
260
260
 
261
- `curl -is www.example.com > /tmp/example_curl_-is_output.txt`
261
+ ```
262
+ curl -is www.example.com > /tmp/example_curl_-is_output.txt
263
+ ```
264
+
262
265
  ```ruby
263
266
  raw_response_file = File.new("/tmp/example_curl_-is_output.txt")
264
267
  ```
@@ -850,6 +853,13 @@ People who submitted patches and new features or suggested improvements. Many th
850
853
  * Leif Bladt
851
854
  * Alex Tomlins
852
855
  * Mitsutaka Mimura
856
+ * Tomy Kaira
857
+ * Daniel van Hoesel
858
+ * Ian Asaff
859
+ * Ian Lesperance
860
+ * Matthew Horan
861
+ * Dmitry Gutov
862
+ * Florian Dütsch
853
863
 
854
864
  For a full list of contributors you can visit the
855
865
  [contributors](https://github.com/bblimke/webmock/contributors) page.
@@ -1,6 +1,6 @@
1
1
  module WebMock
2
2
 
3
- class NetConnectNotAllowedError < StandardError
3
+ class NetConnectNotAllowedError < Exception
4
4
  def initialize(request_signature)
5
5
  text = "Real HTTP connections are disabled. Unregistered request: #{request_signature}"
6
6
  text << "\n\n"
@@ -94,7 +94,6 @@ if defined?(EventMachine::HttpClient)
94
94
  WebMock::RequestRegistry.instance.requested_signatures.put(request_signature)
95
95
 
96
96
  if stubbed_webmock_response
97
- on_error("WebMock timeout error") if stubbed_webmock_response.should_timeout
98
97
  WebMock::CallbackRegistry.invoke_callbacks({:lib => :em_http_request}, request_signature, stubbed_webmock_response)
99
98
  EM.next_tick {
100
99
  setup(make_raw_response(stubbed_webmock_response), @uri,
@@ -13,7 +13,7 @@ if defined?(Excon)
13
13
  class ExconAdapter < HttpLibAdapter
14
14
  PARAMS_TO_DELETE = [:expects, :idempotent,
15
15
  :instrumentor_name, :instrumentor,
16
- :response_block, :request_block,
16
+ :response_block,
17
17
  :__construction_args, :stack,
18
18
  :connection, :response]
19
19
 
@@ -37,6 +37,7 @@ module WebMock::Util
37
37
  # "?one=two&one=three").query_values(:notation => :flat_array)
38
38
  # #=> [['one', 'two'], ['one', 'three']]
39
39
  def self.query_to_values(query, options={})
40
+ query.force_encoding('utf-8') if query.respond_to?(:force_encoding)
40
41
  defaults = {:notation => :subscript}
41
42
  options = defaults.merge(options)
42
43
  if ![:flat, :dot, :subscript, :flat_array].include?(options[:notation])
@@ -65,6 +66,7 @@ module WebMock::Util
65
66
  end).compact.inject(empty_accumulator.dup) do |accumulator, (key, value)|
66
67
  value = true if value.nil?
67
68
  key = Addressable::URI.unencode_component(key)
69
+ key = key.dup.force_encoding(Encoding::ASCII_8BIT) if key.respond_to?(:force_encoding)
68
70
  if value != true
69
71
  value = Addressable::URI.unencode_component(value.gsub(/\+/, " "))
70
72
  end
@@ -90,6 +92,9 @@ module WebMock::Util
90
92
  current_hash = current_hash[subkey]
91
93
  end
92
94
  if array_value
95
+ if current_hash[subkeys.last] && !current_hash[subkeys.last].is_a?(Array)
96
+ current_hash[subkeys.last] = [current_hash[subkeys.last]]
97
+ end
93
98
  current_hash[subkeys.last] = [] unless current_hash[subkeys.last]
94
99
  current_hash[subkeys.last] << value
95
100
  else
@@ -78,7 +78,10 @@ module WebMock
78
78
  end
79
79
 
80
80
  def self.uris_with_inferred_port_and_without(uris)
81
- uris.map { |uri| [ uri, uri.gsub(%r{(:80)|(:443)}, "").freeze ] }.flatten
81
+ uris.map { |uri|
82
+ uri = uri.dup.force_encoding(Encoding::ASCII_8BIT) if uri.respond_to?(:force_encoding)
83
+ [ uri, uri.gsub(%r{(:80)|(:443)}, "").freeze ]
84
+ }.flatten
82
85
  end
83
86
 
84
87
  def self.uris_encoded_and_unencoded(uris)
@@ -88,11 +91,17 @@ module WebMock
88
91
  end
89
92
 
90
93
  def self.uris_with_scheme_and_without(uris)
91
- uris.map { |uri| [ uri, uri.gsub(%r{^https?://},"").freeze ] }.flatten
94
+ uris.map { |uri|
95
+ uri = uri.dup.force_encoding(Encoding::ASCII_8BIT) if uri.respond_to?(:force_encoding)
96
+ [ uri, uri.gsub(%r{^https?://},"").freeze ]
97
+ }.flatten
92
98
  end
93
99
 
94
100
  def self.uris_with_trailing_slash_and_without(uris)
95
- uris = uris.map { |uri| [ uri, uri.omit(:path).freeze ] }.flatten
101
+ uris = uris.map { |uri|
102
+ uri = uri.dup.force_encoding(Encoding::ASCII_8BIT) if uri.respond_to?(:force_encoding)
103
+ [ uri, uri.omit(:path).freeze ]
104
+ }.flatten
96
105
  end
97
106
 
98
107
  end
@@ -1,3 +1,3 @@
1
1
  module WebMock
2
- VERSION = '1.13.0' unless defined?(::WebMock::VERSION)
2
+ VERSION = '1.14.0' unless defined?(::WebMock::VERSION)
3
3
  end
@@ -66,7 +66,7 @@ module CurbSpecHelper
66
66
  curl.put_data = body
67
67
  end
68
68
 
69
- curl.http(method)
69
+ curl.http(method.to_s.upcase)
70
70
  curl
71
71
  end
72
72
  end
@@ -127,6 +127,23 @@ unless RUBY_PLATFORM =~ /java/
127
127
  end
128
128
  end
129
129
 
130
+ it 'should trigger error callbacks asynchronously' do
131
+ stub_request(:get, 'www.example.com').to_timeout
132
+ called = false
133
+
134
+ EM.run do
135
+ conn = EventMachine::HttpRequest.new('http://www.example.com/')
136
+ http = conn.get
137
+ http.errback do
138
+ called = true
139
+ EM.stop
140
+ end
141
+ called.should == false
142
+ end
143
+
144
+ called.should == true
145
+ end
146
+
130
147
  # not pretty, but it works
131
148
  if defined?(EventMachine::Synchrony)
132
149
  describe "with synchrony" do
@@ -83,7 +83,7 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
83
83
  let(:host_with_port){ WebMockServer.instance.host_with_port }
84
84
 
85
85
  before(:each) do
86
- WebMock.disable_net_connect!(:allow => ["www.example.org", host_with_port])
86
+ WebMock.disable_net_connect!(:allow => ["www.example.org", "httpstat.us", host_with_port])
87
87
  end
88
88
 
89
89
  context "when the host is not allowed" do
@@ -120,7 +120,7 @@ shared_context "allowing and disabling net connect" do |*adapter_info|
120
120
  end
121
121
 
122
122
  it "should make a real request to allowed host", :net_connect => true do
123
- http_request(:get, "http://www.example.org/").status.should == "302"
123
+ http_request(:get, "http://httpstat.us/200").status.should == "200"
124
124
  end
125
125
  end
126
126
 
@@ -101,20 +101,20 @@ shared_context "callbacks" do |*adapter_info|
101
101
  WebMock.after_request(:except => [:other_lib]) do |_, response|
102
102
  @response = response
103
103
  end
104
- http_request(:get, "http://www.example.com/")
104
+ http_request(:get, "http://httpstat.us/200")
105
105
  end
106
106
 
107
107
  it "should pass real response to callback with status and message" do
108
- @response.status[0].should == 302
109
- @response.status[1].should == "Found" unless adapter_info.include?(:no_status_message)
108
+ @response.status[0].should == 200
109
+ @response.status[1].should == "OK" unless adapter_info.include?(:no_status_message)
110
110
  end
111
111
 
112
112
  it "should pass real response to callback with headers" do
113
- @response.headers["Content-Length"].should == "0"
113
+ @response.headers["Content-Length"].should == "6"
114
114
  end
115
115
 
116
116
  it "should pass response to callback with body" do
117
- @response.body.size.should == 0
117
+ @response.body.size.should == 6
118
118
  end
119
119
  end
120
120
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  shared_examples_for "stubbing requests" do |*adapter_info|
2
4
  describe "when requests are stubbed" do
3
5
  describe "based on uri" do
@@ -16,6 +18,13 @@ shared_examples_for "stubbing requests" do |*adapter_info|
16
18
  http_request(:get, "http://www.example.com/hello+/?#{NOT_ESCAPED_PARAMS}").body.should == "abc"
17
19
  end
18
20
 
21
+ it "should return stubbed response for url with non utf query params", "ruby>1.9" => true do
22
+ param = 'aäoöuü'.encode('iso-8859-1')
23
+ param = CGI.escape(param)
24
+ stub_request(:get, "www.example.com/?#{param}").to_return(:body => "abc")
25
+ http_request(:get, "http://www.example.com/?#{param}").body.should == "abc"
26
+ end
27
+
19
28
  it "should return stubbed response even if stub uri is declared as regexp and request params are escaped" do
20
29
  stub_request(:get, /.*x=ab c.*/).to_return(:body => "abc")
21
30
  http_request(:get, "http://www.example.com/hello/?#{ESCAPED_PARAMS}").body.should == "abc"
@@ -28,6 +28,10 @@ RSpec.configure do |config|
28
28
  config.filter_run_excluding :net_connect => true
29
29
  end
30
30
 
31
+ if RUBY_VERSION <= "1.8.7"
32
+ config.filter_run_excluding "ruby>1.9" => true
33
+ end
34
+
31
35
  config.filter_run_excluding :without_webmock => true
32
36
 
33
37
  config.before(:suite) do
@@ -16,7 +16,7 @@ module NetworkConnection
16
16
 
17
17
  def self.is_network_available?
18
18
  begin
19
- self.connect_to("192.0.32.10", 80, 5)
19
+ self.connect_to("173.194.113.176", 80, 5)
20
20
  true
21
21
  rescue
22
22
  false
@@ -4,11 +4,11 @@ describe "errors" do
4
4
  describe WebMock::NetConnectNotAllowedError do
5
5
  describe "message" do
6
6
  it "should have message with request signature and snippet" do
7
- request_signature = mock(:to_s => "aaa")
8
- request_stub = mock
9
- WebMock::RequestStub.stub!(:from_request_signature).and_return(request_stub)
10
- WebMock::StubRequestSnippet.stub!(:new).
11
- with(request_stub).and_return(mock(:to_s => "bbb"))
7
+ request_signature = double(:to_s => "aaa")
8
+ request_stub = double
9
+ WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
10
+ WebMock::StubRequestSnippet.stub(:new).
11
+ with(request_stub).and_return(double(:to_s => "bbb"))
12
12
  expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
13
13
  "\n\nYou can stub this request with the following snippet:\n\n" +
14
14
  "bbb\n\n============================================================"
@@ -16,16 +16,34 @@ describe "errors" do
16
16
  end
17
17
 
18
18
  it "should have message with registered stubs if available" do
19
+ request_signature = double(:to_s => "aaa")
20
+ request_stub = double
21
+ WebMock::StubRegistry.instance.stub(:request_stubs).and_return([request_stub])
22
+ WebMock::RequestStub.stub(:from_request_signature).and_return(request_stub)
23
+ WebMock::StubRequestSnippet.stub(:new).
24
+ with(request_stub).and_return(double(:to_s => "bbb"))
25
+ expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
26
+ "\n\nYou can stub this request with the following snippet:\n\n" +
27
+ "bbb\n\nregistered request stubs:\n\nbbb\n\n============================================================"
28
+ WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
29
+ end
30
+
31
+ it "should not be caught by a rescue block without arguments" do
19
32
  request_signature = mock(:to_s => "aaa")
20
33
  request_stub = mock
21
- WebMock::StubRegistry.instance.stub!(:request_stubs).and_return([request_stub])
22
34
  WebMock::RequestStub.stub!(:from_request_signature).and_return(request_stub)
23
35
  WebMock::StubRequestSnippet.stub!(:new).
24
36
  with(request_stub).and_return(mock(:to_s => "bbb"))
25
- expected = "Real HTTP connections are disabled. Unregistered request: aaa" +
26
- "\n\nYou can stub this request with the following snippet:\n\n" +
27
- "bbb\n\nregistered request stubs:\n\nbbb\n\n============================================================"
28
- WebMock::NetConnectNotAllowedError.new(request_signature).message.should == expected
37
+
38
+ exception = WebMock::NetConnectNotAllowedError.new(request_signature)
39
+
40
+ expect do
41
+ begin
42
+ raise exception
43
+ rescue
44
+ raise "exception should not be caught"
45
+ end
46
+ end.to raise_exception exception
29
47
  end
30
48
  end
31
49
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe WebMock::RequestExecutionVerifier do
4
4
  before(:each) do
5
5
  @verifier = WebMock::RequestExecutionVerifier.new
6
- @request_pattern = mock(WebMock::RequestPattern, :to_s => "www.example.com")
6
+ @request_pattern = double(WebMock::RequestPattern, :to_s => "www.example.com")
7
7
  @verifier.request_pattern = @request_pattern
8
8
  WebMock::RequestRegistry.instance.stub(:to_s).and_return("executed requests")
9
9
  @executed_requests_info = "\n\nThe following requests were made:\n\nexecuted requests\n" + "="*60
@@ -6,14 +6,14 @@ describe WebMock::ResponseFactory do
6
6
 
7
7
  it "should create response with options passed as arguments" do
8
8
  options = {:body => "abc", :headers => {:a => :b}}
9
- WebMock::Response.should_receive(:new).with(options).and_return(@response = mock(WebMock::Response))
9
+ WebMock::Response.should_receive(:new).with(options).and_return(@response = double(WebMock::Response))
10
10
  WebMock::ResponseFactory.response_for(options).should == @response
11
11
  end
12
12
 
13
13
 
14
14
  it "should create dynamic response for argument responding to call" do
15
- callable = mock(:call => {:body => "abc"})
16
- WebMock::DynamicResponse.should_receive(:new).with(callable).and_return(@response = mock(WebMock::Response))
15
+ callable = double(:call => {:body => "abc"})
16
+ WebMock::DynamicResponse.should_receive(:new).with(callable).and_return(@response = double(WebMock::Response))
17
17
  WebMock::ResponseFactory.response_for(callable).should == @response
18
18
  end
19
19
 
@@ -184,6 +184,19 @@ describe WebMock::Util::URI do
184
184
  uri = WebMock::Util::URI.normalize_uri(uri_string)
185
185
  WebMock::Util::QueryMapper.query_to_values(uri.query).should == {"one"=>{"two"=>{"three" => ["four", "five"]}}}
186
186
  end
187
+
188
+ it "should successfully handle mixed array and hash parameters" do
189
+ # derived from an elasticsearch query:
190
+ # load => {
191
+ # :include => [
192
+ # { :staff => :email },
193
+ # :business_name
194
+ # ]
195
+ # }
196
+ uri_string = "http://www.example.com:80/path?load[include][][staff]=email&load[include][]=business_name"
197
+ uri = WebMock::Util::URI.normalize_uri(uri_string)
198
+ WebMock::Util::QueryMapper.query_to_values(uri.query).should == {"load"=>{"include"=>[{"staff"=>"email"},"business_name"]}}
199
+ end
187
200
  end
188
201
 
189
202
  describe "stripping default port" do
@@ -10,13 +10,13 @@ module SharedTest
10
10
  end
11
11
 
12
12
  def test_assert_requested_with_stub_and_block_raises_error
13
- assert_raise ArgumentError do
13
+ assert_raises ArgumentError do
14
14
  assert_requested(@stub_http) {}
15
15
  end
16
16
  end
17
17
 
18
18
  def test_assert_not_requested_with_stub_and_block_raises_error
19
- assert_raise ArgumentError do
19
+ assert_raises ArgumentError do
20
20
  assert_not_requested(@stub_http) {}
21
21
  end
22
22
  end
@@ -9,7 +9,7 @@ require 'test/unit'
9
9
  class Test::Unit::TestCase
10
10
  AssertionFailedError = Test::Unit::AssertionFailedError rescue MiniTest::Assertion
11
11
  def assert_raise_with_message(e, message, &block)
12
- e = assert_raise(e, &block)
12
+ e = assert_raises(e, &block)
13
13
  if message.is_a?(Regexp)
14
14
  assert_match(message, e.message)
15
15
  else
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webmock
3
3
  version: !ruby/object:Gem::Version
4
- hash: 35
4
+ hash: 47
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 13
8
+ - 14
9
9
  - 0
10
- version: 1.13.0
10
+ version: 1.14.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Bartosz Blimke
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-07-05 00:00:00 Z
18
+ date: 2013-10-03 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: addressable