webmock 0.7.3 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ module WebMock
2
+
3
+ class Request
4
+ attr_accessor :method, :uri, :body, :headers
5
+
6
+ def initialize(method, uri, options = {})
7
+ self.method = method
8
+ self.uri = uri.is_a?(Addressable::URI) ? uri : WebMock::Util::URI.normalize_uri(uri)
9
+ assign_options(options)
10
+ end
11
+
12
+ def to_s
13
+ string = "#{self.method.to_s.upcase} #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}"
14
+ string << " with body '#{body.to_s}'" if body && body.to_s != ''
15
+ if headers && !headers.empty?
16
+ string << " with headers #{WebMock::Util::Headers.normalize_headers(headers).inspect.gsub("\"","'")}"
17
+ end
18
+ string
19
+ end
20
+
21
+ private
22
+
23
+ def assign_options(options)
24
+ self.body = options[:body] if options.has_key?(:body)
25
+ self.headers = WebMock::Util::Headers.normalize_headers(options[:headers]) if options.has_key?(:headers)
26
+ end
27
+
28
+ end
29
+ end
@@ -1,28 +1,41 @@
1
1
  module WebMock
2
2
 
3
- class RequestProfile < Struct.new(:method, :uri, :body, :headers)
4
-
5
- def initialize(method, uri, body = nil, headers = nil)
6
- super
7
- self.uri = WebMock::Util::URI.normalize_uri(self.uri) unless self.uri.is_a?(Addressable::URI)
8
- self.headers = WebMock::Util::Headers.normalize_headers(self.headers)
9
- end
3
+ class RequestProfile < Request
10
4
 
11
5
  def with(options)
12
- self.body = options[:body] if options.has_key?(:body)
13
- self.headers = WebMock::Util::Headers.normalize_headers(options[:headers]) if options.has_key?(:headers)
6
+ assign_options(options)
14
7
  self
15
8
  end
9
+
10
+ def body=(body)
11
+ @body = Body.new(body)
12
+ end
13
+
14
+ class Body
15
+
16
+ attr_reader :data
17
+
18
+ def initialize(data)
19
+ @data = data
20
+ end
16
21
 
17
- def to_s
18
- string = "#{self.method.to_s.upcase} #{WebMock::Util::URI.strip_default_port_from_uri_string(self.uri.to_s)}"
19
- string << " with body '#{body}'" if body
20
- if headers && !headers.empty?
21
- string << " with headers #{WebMock::Util::Headers.normalize_headers(headers).inspect.gsub("\"","'")}"
22
+ def ==(other)
23
+ other = Body.new(other) unless other.is_a?(Body)
24
+ other.is_a?(Body) &&
25
+ (other.is_empty? && self.is_empty? || other.data == self.data)
22
26
  end
23
- string
27
+
28
+ def is_empty?
29
+ @data.nil? || @data == ""
30
+ end
31
+
32
+ def to_s
33
+ @data
34
+ end
35
+
24
36
  end
25
37
 
26
38
  end
27
39
 
40
+
28
41
  end
@@ -25,9 +25,9 @@ module WebMock
25
25
 
26
26
  def response_for_request(request_signature)
27
27
  stub = request_stub_for(request_signature)
28
- stub ? stub.response : nil
28
+ stub ? evaluate_response_for_request(stub.response, request_signature) : nil
29
29
  end
30
-
30
+
31
31
  def times_executed(request_profile)
32
32
  self.requested_signatures.hash.select { |request_signature, times_executed|
33
33
  request_signature.match(request_profile)
@@ -42,5 +42,15 @@ module WebMock
42
42
  }
43
43
  end
44
44
 
45
+ def evaluate_response_for_request(response, request_signature)
46
+ evaluated_response = response.dup
47
+ [:body, :headers].each do |attribute|
48
+ if response.options[attribute].is_a?(Proc)
49
+ evaluated_response.options[attribute] = response.options[attribute].call(request_signature)
50
+ end
51
+ end
52
+ evaluated_response
53
+ end
54
+
45
55
  end
46
56
  end
@@ -1,8 +1,9 @@
1
1
  module WebMock
2
2
 
3
- class RequestSignature < RequestProfile
3
+ class RequestSignature < Request
4
4
 
5
5
  def match(request_profile)
6
+ raise ArgumentError unless request_profile.is_a?(RequestProfile)
6
7
  match_method(request_profile) &&
7
8
  match_body(request_profile) &&
8
9
  match_headers(request_profile) &&
@@ -9,8 +9,7 @@ module WebMock
9
9
  end
10
10
 
11
11
  def with(params)
12
- @request_profile.body = params[:body]
13
- @request_profile.headers = Util::Headers.normalize_headers(params[:headers])
12
+ @request_profile.with(params)
14
13
  self
15
14
  end
16
15
 
@@ -1,24 +1,26 @@
1
1
  module WebMock
2
2
  class Response
3
+ attr_accessor :options
3
4
 
4
5
  def initialize(options = {})
5
6
  @options = options
7
+ @options[:headers] = Util::Headers.normalize_headers(@options[:headers]) unless @options[:headers].is_a?(Proc)
6
8
  end
7
9
 
8
10
  def headers
9
- Util::Headers.normalize_headers(@options[:headers])
11
+ @options[:headers]
10
12
  end
11
13
 
12
14
  def body
13
15
  return '' unless @options.has_key?(:body)
14
-
15
- if !@options[:body].include?("\0") && File.exists?(@options[:body]) && !File.directory?(@options[:body])
16
- File.read(@options[:body])
17
- else
16
+ case @options[:body]
17
+ when IO
18
+ @options[:body].read
19
+ when String
18
20
  @options[:body]
19
21
  end
20
22
  end
21
-
23
+
22
24
  def status
23
25
  @options.has_key?(:status) ? @options[:status] : 200
24
26
  end
@@ -27,5 +29,15 @@ module WebMock
27
29
  raise @options[:exception].new('Exception from WebMock') if @options.has_key?(:exception)
28
30
  end
29
31
 
32
+ def dup
33
+ dup_response = super
34
+ dup_response.options = options.dup
35
+ dup_response
36
+ end
37
+
38
+ def ==(other)
39
+ options == other.options
40
+ end
41
+
30
42
  end
31
43
  end
@@ -18,7 +18,7 @@ module WebMock
18
18
  normalized_uri = Addressable::URI.heuristic_parse(uri)
19
19
  normalized_uri.query_values = normalized_uri.query_values if normalized_uri.query_values
20
20
  normalized_uri.normalize!
21
- normalized_uri.port = normalized_uri.inferred_port unless normalized_uri.port && normalized_uri.inferred_port
21
+ normalized_uri.port = normalized_uri.inferred_port unless normalized_uri.port
22
22
  normalized_uri
23
23
  end
24
24
 
@@ -34,7 +34,7 @@ module WebMock
34
34
  uris = uris_with_scheme_and_without(uris)
35
35
  end
36
36
 
37
- if normalized_uri.path == '/' && normalized_uri.query == nil
37
+ if normalized_uri.path == '/'
38
38
  uris = uris_with_trailing_slash_and_without(uris)
39
39
  end
40
40
 
@@ -13,13 +13,13 @@ module WebMock
13
13
 
14
14
  def assert_requested(method, uri, options = {})
15
15
  expected_times_executed = options.delete(:times) || 1
16
- request = RequestProfile.new(method, uri, options[:body], options[:headers])
16
+ request = RequestProfile.new(method, uri, options)
17
17
  verifier = RequestExecutionVerifier.new(request, expected_times_executed)
18
18
  assertion_failure(verifier.failure_message) unless verifier.matches?
19
19
  end
20
20
 
21
21
  def assert_not_requested(method, uri, options = {})
22
- request = RequestProfile.new(method, uri, options[:body], options[:headers])
22
+ request = RequestProfile.new(method, uri, options)
23
23
  verifier = RequestExecutionVerifier.new(request, options.delete(:times))
24
24
  assertion_failure(verifier.negative_failure_message) unless verifier.does_not_match?
25
25
  end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'webmock_spec'
3
+ require 'ostruct'
4
+
5
+ require 'httpclient'
6
+ require 'httpclient_spec_helper'
7
+
8
+ describe "Webmock with HTTPClient" do
9
+ include HTTPClientSpecHelper
10
+
11
+ before(:each) do
12
+ HTTPClientSpecHelper.async_mode = false
13
+ end
14
+
15
+ it_should_behave_like "WebMock"
16
+
17
+ it "should yield block on response if block provided" do
18
+ stub_http_request(:get, "www.example.com").to_return(:body => "abc")
19
+ response_body = ""
20
+ http_request(:get, "http://www.example.com/") do |body|
21
+ response_body = body
22
+ end
23
+ response_body.should == "abc"
24
+ end
25
+
26
+ describe "async requests" do
27
+
28
+ before(:each) do
29
+ HTTPClientSpecHelper.async_mode = true
30
+ end
31
+
32
+ it_should_behave_like "WebMock"
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,57 @@
1
+ module HTTPClientSpecHelper
2
+ class << self
3
+ attr_accessor :async_mode
4
+ end
5
+
6
+ def http_request(method, uri, options = {}, &block)
7
+ uri = Addressable::URI.heuristic_parse(uri)
8
+ c = HTTPClient.new
9
+ c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
10
+ c.set_basic_auth(nil, uri.user, uri.password) if uri.user
11
+ params = [method, "#{uri.omit(:userinfo, :query).normalize.to_s}",
12
+ uri.query_values, options[:body], options[:headers] || {}]
13
+ if HTTPClientSpecHelper.async_mode
14
+ connection = c.request_async(*params)
15
+ connection.join
16
+ response = connection.pop
17
+ else
18
+ response = c.request(*params, &block)
19
+ end
20
+ OpenStruct.new({
21
+ :body => HTTPClientSpecHelper.async_mode ? response.content.read : response.content,
22
+ :headers => Hash[response.header.all],
23
+ :status => response.code.to_s })
24
+ end
25
+
26
+ def setup_expectations_for_real_request(options = {})
27
+ socket = mock("TCPSocket")
28
+ TCPSocket.should_receive(:new).
29
+ with(options[:host], options[:port]).at_least(:once).and_return(socket)
30
+
31
+ socket.stub!(:closed?).and_return(false)
32
+ socket.stub!(:close).and_return(true)
33
+
34
+ request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"]
35
+
36
+ if options[:port] == 443
37
+ OpenSSL::SSL::SSLSocket.should_receive(:new).
38
+ with(socket, instance_of(OpenSSL::SSL::SSLContext)).
39
+ at_least(:once).and_return(socket = mock("SSLSocket"))
40
+ socket.should_receive(:connect).at_least(:once).with()
41
+ socket.should_receive(:peer_cert).and_return(mock('peer cert', :extensions => []))
42
+ socket.should_receive(:write).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
43
+ else
44
+ socket.should_receive(:<<).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
45
+ end
46
+
47
+ socket.stub!(:sync=).with(true)
48
+
49
+ socket.should_receive(:gets).with("\n").once.and_return("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}")
50
+
51
+ socket.stub!(:eof?).and_return(true)
52
+ socket.stub!(:close).and_return(true)
53
+
54
+ socket.should_receive(:readpartial).any_number_of_times.and_raise(EOFError)
55
+ end
56
+
57
+ end
@@ -1,34 +1,25 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require 'webmock_spec'
3
3
  require 'ostruct'
4
+ require 'net_http_spec_helper'
4
5
 
5
- def http_request(method, uri, options = {})
6
- begin
7
- uri = URI.parse(uri)
8
- rescue
9
- uri = Addressable::URI.heuristic_parse(uri)
10
- end
11
- response = nil
12
- clazz = Net::HTTP.const_get("#{method.to_s.capitalize}")
13
- req = clazz.new("#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers])
14
- req.basic_auth uri.user, uri.password if uri.user
15
- http = Net::HTTP.new(uri.host, uri.port)
16
- http.use_ssl = true if uri.scheme == "https"
17
- response = http.start {|http|
18
- http.request(req, options[:body])
19
- }
20
- OpenStruct.new({
21
- :body => response.body,
22
- :headers => response,
23
- :status => response.code })
24
- end
6
+ include NetHTTPSpecHelper
25
7
 
26
8
  describe "Webmock with Net:HTTP" do
27
-
9
+
28
10
  it_should_behave_like "WebMock"
29
-
11
+
30
12
  it "should work with block provided" do
31
- stub_http_request(:get, "www.google.com").to_return(:body => "abc"*100000)
32
- Net::HTTP.start("www.google.com") { |query| query.get("/") }.body.should == "abc"*100000
13
+ stub_http_request(:get, "www.example.com").to_return(:body => "abc"*100000)
14
+ Net::HTTP.start("www.example.com") { |query| query.get("/") }.body.should == "abc"*100000
15
+ end
16
+
17
+ it "should yield block on response" do
18
+ stub_http_request(:get, "www.example.com").to_return(:body => "abc")
19
+ response_body = ""
20
+ http_request(:get, "http://www.example.com/") do |response|
21
+ response_body = response.body
22
+ end
23
+ response_body.should == "abc"
33
24
  end
34
25
  end
@@ -0,0 +1,53 @@
1
+ module NetHTTPSpecHelper
2
+ def http_request(method, uri, options = {}, &block)
3
+ begin
4
+ uri = URI.parse(uri)
5
+ rescue
6
+ uri = Addressable::URI.heuristic_parse(uri)
7
+ end
8
+ response = nil
9
+ clazz = Net::HTTP.const_get("#{method.to_s.capitalize}")
10
+ req = clazz.new("#{uri.path}#{uri.query ? '?' : ''}#{uri.query}", options[:headers])
11
+
12
+ req.basic_auth uri.user, uri.password if uri.user
13
+ http = Net::HTTP.new(uri.host, uri.port)
14
+ http.use_ssl = true if uri.scheme == "https"
15
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
16
+ response = http.start {|http|
17
+ http.request(req, options[:body], &block)
18
+ }
19
+ OpenStruct.new({
20
+ :body => response.body,
21
+ :headers => response,
22
+ :status => response.code })
23
+ end
24
+
25
+ # Sets several expectations that a real HTTP request makes it
26
+ # past WebMock to the socket layer. You can use this when you need to check
27
+ # that a request isn't handled by WebMock
28
+ #This solution is copied from FakeWeb project
29
+ def setup_expectations_for_real_request(options = {})
30
+ # Socket handling
31
+ if options[:port] == 443
32
+ socket = mock("SSLSocket")
33
+ OpenSSL::SSL::SSLSocket.should_receive(:===).with(socket).at_least(:once).and_return(true)
34
+ OpenSSL::SSL::SSLSocket.should_receive(:new).with(socket, instance_of(OpenSSL::SSL::SSLContext)).at_least(:once).and_return(socket)
35
+ socket.stub!(:sync_close=).and_return(true)
36
+ socket.should_receive(:connect).at_least(:once).with()
37
+ else
38
+ socket = mock("TCPSocket")
39
+ Socket.should_receive(:===).with(socket).at_least(:once).and_return(true)
40
+ end
41
+
42
+ TCPSocket.should_receive(:open).with(options[:host], options[:port]).at_least(:once).and_return(socket)
43
+ socket.stub!(:closed?).and_return(false)
44
+ socket.stub!(:close).and_return(true)
45
+
46
+ # Request/response handling
47
+ request_parts = ["#{options[:method]} #{options[:path]} HTTP/1.1", "Host: #{options[:host]}"]
48
+ socket.should_receive(:write).with(/#{request_parts[0]}.*#{request_parts[1]}.*/m).and_return(100)
49
+
50
+ socket.should_receive(:sysread).once.and_return("HTTP/1.1 #{options[:response_code]} #{options[:response_message]}\nContent-Length: #{options[:response_body].length}\n\n#{options[:response_body]}")
51
+ socket.should_receive(:sysread).any_number_of_times.and_raise(EOFError)
52
+ end
53
+ end
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe RequestExecutionVerifier do
4
4
  before(:each) do
5
5
  @verifier = RequestExecutionVerifier.new
6
- @request_profile = mock(RequestProfile, :to_s => "www.google.com")
6
+ @request_profile = mock(RequestProfile, :to_s => "www.example.com")
7
7
  @verifier.request_profile = @request_profile
8
8
  end
9
9
 
@@ -13,13 +13,13 @@ describe RequestExecutionVerifier do
13
13
  it "should report failure message" do
14
14
  @verifier.times_executed = 0
15
15
  @verifier.expected_times_executed = 2
16
- @verifier.failure_message.should == "The request www.google.com was expected to execute 2 times but it executed 0 times"
16
+ @verifier.failure_message.should == "The request www.example.com was expected to execute 2 times but it executed 0 times"
17
17
  end
18
18
 
19
19
  it "should report failure message correctly when executed times is one" do
20
20
  @verifier.times_executed = 1
21
21
  @verifier.expected_times_executed = 1
22
- @verifier.failure_message.should == "The request www.google.com was expected to execute 1 time but it executed 1 time"
22
+ @verifier.failure_message.should == "The request www.example.com was expected to execute 1 time but it executed 1 time"
23
23
  end
24
24
 
25
25
  end
@@ -29,12 +29,12 @@ describe RequestExecutionVerifier do
29
29
  it "should report failure message if it executed number of times specified" do
30
30
  @verifier.times_executed = 2
31
31
  @verifier.expected_times_executed = 2
32
- @verifier.negative_failure_message.should == "The request www.google.com was not expected to execute 2 times but it executed 2 times"
32
+ @verifier.negative_failure_message.should == "The request www.example.com was not expected to execute 2 times but it executed 2 times"
33
33
  end
34
34
 
35
35
  it "should report failure message when not expected request but it executed" do
36
36
  @verifier.times_executed = 1
37
- @verifier.negative_failure_message.should == "The request www.google.com was expected to execute 0 times but it executed 1 time"
37
+ @verifier.negative_failure_message.should == "The request www.example.com was expected to execute 0 times but it executed 1 time"
38
38
  end
39
39
 
40
40
  end