webmock 0.7.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.
Files changed (59) hide show
  1. data/.gitignore +21 -0
  2. data/LICENSE +281 -0
  3. data/README.md +170 -0
  4. data/Rakefile +54 -0
  5. data/VERSION +1 -0
  6. data/lib/webmock.rb +18 -0
  7. data/lib/webmock/adapters/rspec.rb +23 -0
  8. data/lib/webmock/adapters/rspec/matchers.rb +19 -0
  9. data/lib/webmock/adapters/rspec/request_profile_matcher.rb +37 -0
  10. data/lib/webmock/adapters/rspec/webmock_matcher.rb +45 -0
  11. data/lib/webmock/adapters/test_unit.rb +25 -0
  12. data/lib/webmock/config.rb +7 -0
  13. data/lib/webmock/errors.rb +5 -0
  14. data/lib/webmock/http_lib_adapters/net_http.rb +129 -0
  15. data/lib/webmock/request_execution_verifier.rb +22 -0
  16. data/lib/webmock/request_profile.rb +67 -0
  17. data/lib/webmock/request_registry.rb +47 -0
  18. data/lib/webmock/request_stub.rb +26 -0
  19. data/lib/webmock/response.rb +31 -0
  20. data/lib/webmock/url.rb +46 -0
  21. data/lib/webmock/util/hash_counter.rb +12 -0
  22. data/lib/webmock/utility.rb +65 -0
  23. data/lib/webmock/webmock.rb +58 -0
  24. data/spec/net_http_spec.rb +33 -0
  25. data/spec/other_net_http_libs_spec.rb +37 -0
  26. data/spec/request_execution_verifier_spec.rb +51 -0
  27. data/spec/request_profile_spec.rb +166 -0
  28. data/spec/request_registry_spec.rb +114 -0
  29. data/spec/request_stub_spec.rb +54 -0
  30. data/spec/response_spec.rb +59 -0
  31. data/spec/spec.opts +1 -0
  32. data/spec/spec_helper.rb +58 -0
  33. data/spec/util/hash_counter_spec.rb +24 -0
  34. data/spec/utility_spec.rb +70 -0
  35. data/spec/vendor/right_http_connection-1.2.4/History.txt +59 -0
  36. data/spec/vendor/right_http_connection-1.2.4/Manifest.txt +7 -0
  37. data/spec/vendor/right_http_connection-1.2.4/README.txt +54 -0
  38. data/spec/vendor/right_http_connection-1.2.4/Rakefile +103 -0
  39. data/spec/vendor/right_http_connection-1.2.4/lib/net_fix.rb +160 -0
  40. data/spec/vendor/right_http_connection-1.2.4/lib/right_http_connection.rb +435 -0
  41. data/spec/vendor/right_http_connection-1.2.4/setup.rb +1585 -0
  42. data/spec/vendor/samuel-0.2.1/.document +5 -0
  43. data/spec/vendor/samuel-0.2.1/.gitignore +5 -0
  44. data/spec/vendor/samuel-0.2.1/LICENSE +20 -0
  45. data/spec/vendor/samuel-0.2.1/README.rdoc +70 -0
  46. data/spec/vendor/samuel-0.2.1/Rakefile +62 -0
  47. data/spec/vendor/samuel-0.2.1/VERSION +1 -0
  48. data/spec/vendor/samuel-0.2.1/lib/samuel.rb +52 -0
  49. data/spec/vendor/samuel-0.2.1/lib/samuel/net_http.rb +10 -0
  50. data/spec/vendor/samuel-0.2.1/lib/samuel/request.rb +96 -0
  51. data/spec/vendor/samuel-0.2.1/samuel.gemspec +69 -0
  52. data/spec/vendor/samuel-0.2.1/test/request_test.rb +193 -0
  53. data/spec/vendor/samuel-0.2.1/test/samuel_test.rb +42 -0
  54. data/spec/vendor/samuel-0.2.1/test/test_helper.rb +66 -0
  55. data/spec/vendor/samuel-0.2.1/test/thread_test.rb +32 -0
  56. data/spec/webmock_spec.rb +492 -0
  57. data/test/test_helper.rb +9 -0
  58. data/test/test_webmock.rb +56 -0
  59. metadata +144 -0
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "webmock"
8
+ gem.summary = %Q{Library for stubbing HTTP requests in Ruby.}
9
+ gem.description = %Q{WebMock allows stubbing HTTP requests and setting expectations on HTTP requests.}
10
+ gem.email = "bartosz.blimke@gmail.com"
11
+ gem.homepage = "http://github.com/bblimke/webmock"
12
+ gem.authors = ["Bartosz Blimke"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb'].exclude("spec/vendor")
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ require 'rake/testtask'
34
+ Rake::TestTask.new(:test) do |test|
35
+ test.test_files = FileList["test/**/*.rb"].exclude("test/test_helper.rb")
36
+ test.verbose = false
37
+ test.warning = true
38
+ end
39
+
40
+ task :spec => :check_dependencies
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => [:spec, :test]
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "webmock #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/webmock/webmock.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.7.0
@@ -0,0 +1,18 @@
1
+ require 'singleton'
2
+
3
+ require 'webmock/http_lib_adapters/net_http'
4
+
5
+ require 'webmock/errors'
6
+ require 'webmock/request_profile'
7
+ require 'webmock/request_execution_verifier'
8
+ require 'webmock/url'
9
+ require 'webmock/request_stub'
10
+ require 'webmock/utility'
11
+ require 'webmock/config'
12
+ require 'webmock/response'
13
+ require 'webmock/util/hash_counter'
14
+ require 'webmock/request_registry'
15
+ require 'webmock/webmock'
16
+
17
+ require 'webmock/adapters/rspec'
18
+ require 'webmock/adapters/test_unit'
@@ -0,0 +1,23 @@
1
+ if defined?(Spec::Runner)
2
+
3
+ require 'webmock/adapters/rspec/request_profile_matcher'
4
+ require 'webmock/adapters/rspec/webmock_matcher'
5
+ require 'webmock/adapters/rspec/matchers'
6
+
7
+ Spec::Runner.configure { |config|
8
+
9
+ config.include WebMock::Matchers
10
+
11
+ config.before :each do
12
+ WebMock.reset_webmock
13
+ end
14
+ }
15
+
16
+ module WebMock
17
+ private
18
+ def assertion_failure(message)
19
+ raise Spec::Expectations::ExpectationNotMetError.new(message)
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,19 @@
1
+ module WebMock
2
+ module Matchers
3
+ def have_been_made
4
+ WebMock::RequestProfileMatcher.new
5
+ end
6
+
7
+ def have_not_been_made
8
+ WebMock::RequestProfileMatcher.new.times(0)
9
+ end
10
+
11
+ def have_requested(method, url)
12
+ WebMock::WebMockMatcher.new(method, url)
13
+ end
14
+
15
+ def have_not_requested(method, url)
16
+ WebMock::WebMockMatcher.new(method, url).times(0)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ module WebMock
2
+ class RequestProfileMatcher
3
+
4
+ def initialize
5
+ @request_execution_verifier = RequestExecutionVerifier.new
6
+ end
7
+
8
+ def once
9
+ @request_execution_verifier.expected_times_executed = 1
10
+ self
11
+ end
12
+
13
+ def twice
14
+ @request_execution_verifier.expected_times_executed = 2
15
+ self
16
+ end
17
+
18
+ def times(times)
19
+ @request_execution_verifier.expected_times_executed = times.to_i
20
+ self
21
+ end
22
+
23
+ def matches?(request_profile)
24
+ @request_execution_verifier.request_profile = request_profile
25
+ @request_execution_verifier.verify
26
+ end
27
+
28
+ def failure_message
29
+ @request_execution_verifier.failure_message
30
+ end
31
+
32
+
33
+ def negative_failure_message
34
+ @request_execution_verifier.negative_failure_message
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ module WebMock
2
+ class WebMockMatcher
3
+
4
+ def initialize(method, url)
5
+ @request_execution_verifier = RequestExecutionVerifier.new
6
+ @request_execution_verifier.request_profile = RequestProfile.new(method, url)
7
+ end
8
+
9
+ def once
10
+ @request_execution_verifier.expected_times_executed = 1
11
+ self
12
+ end
13
+
14
+ def twice
15
+ @request_execution_verifier.expected_times_executed = 2
16
+ self
17
+ end
18
+
19
+ def with(options)
20
+ @request_execution_verifier.request_profile.body =
21
+ options[:body] if options.has_key?(:body)
22
+ @request_execution_verifier.request_profile.headers =
23
+ options[:headers] if options.has_key?(:headers)
24
+ self
25
+ end
26
+
27
+ def times(times)
28
+ @request_execution_verifier.expected_times_executed = times.to_i
29
+ self
30
+ end
31
+
32
+ def matches?(webmock)
33
+ @request_execution_verifier.verify
34
+ end
35
+
36
+ def failure_message
37
+ @request_execution_verifier.failure_message
38
+ end
39
+
40
+
41
+ def negative_failure_message
42
+ @request_execution_verifier.negative_failure_message
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,25 @@
1
+ if defined?(Test::Unit::TestCase)
2
+
3
+ class Test::Unit::TestCase
4
+ include WebMock
5
+ alias setup_without_webmock setup
6
+ def setup
7
+ reset_webmock
8
+ @original_allow_net_connect = WebMock.net_connect_allowed?
9
+ WebMock.disable_net_connect!
10
+ end
11
+
12
+ alias teardown_without_webmock teardown
13
+ def teardown
14
+ @original_allow_net_connect ? WebMock.allow_net_connect! : WebMock.disable_net_connect!
15
+ end
16
+ end
17
+
18
+ module WebMock
19
+ private
20
+ def assertion_failure(message)
21
+ raise Test::Unit::AssertionFailedError.new(message)
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,7 @@
1
+ module WebMock
2
+ class Config
3
+ include Singleton
4
+
5
+ attr_accessor :allow_net_connect
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module WebMock
2
+
3
+ class NetConnectNotAllowedError < StandardError; end;
4
+
5
+ end
@@ -0,0 +1,129 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'stringio'
4
+
5
+
6
+ class StubSocket #:nodoc:
7
+
8
+ def initialize(*args)
9
+ end
10
+
11
+ def closed?
12
+ @closed ||= true
13
+ end
14
+
15
+ def readuntil(*args)
16
+ end
17
+
18
+ end
19
+
20
+ module StubResponse
21
+ def read_body(*args, &block)
22
+ yield @body if block_given?
23
+ @body
24
+ end
25
+ end
26
+
27
+ module Net #:nodoc: all
28
+
29
+ class BufferedIO
30
+ def initialize_with_webmock(io, debug_output = nil)
31
+ @read_timeout = 60
32
+ @rbuf = ''
33
+ @debug_output = debug_output
34
+
35
+ @io = case io
36
+ when Socket, OpenSSL::SSL::SSLSocket, IO
37
+ io
38
+ when String
39
+ if !io.include?("\0") && File.exists?(io) && !File.directory?(io)
40
+ File.open(io, "r")
41
+ else
42
+ StringIO.new(io)
43
+ end
44
+ end
45
+ raise "Unable to create local socket" unless @io
46
+ end
47
+ alias_method :initialize_without_webmock, :initialize
48
+ alias_method :initialize, :initialize_with_webmock
49
+ end
50
+
51
+ class HTTP
52
+ class << self
53
+ def socket_type_with_webmock
54
+ StubSocket
55
+ end
56
+ alias_method :socket_type_without_webmock, :socket_type
57
+ alias_method :socket_type, :socket_type_with_webmock
58
+ end
59
+
60
+ def request_with_webmock(request, body = nil, &block)
61
+ protocol = use_ssl? ? "https" : "http"
62
+
63
+ path = request.path
64
+ path = URI.parse(request.path).request_uri if request.path =~ /^http/
65
+
66
+ if request["authorization"] =~ /^Basic /
67
+ userinfo = WebMock::Utility.decode_userinfo_from_header(request["authorization"])
68
+ userinfo = WebMock::Utility.encode_unsafe_chars_in_userinfo(userinfo) + "@"
69
+ else
70
+ userinfo = ""
71
+ end
72
+
73
+ uri = "#{protocol}://#{userinfo}#{self.address}:#{self.port}#{path}"
74
+ method = request.method.downcase.to_sym
75
+
76
+ headers = Hash[*request.to_hash.map {|k,v| [k, v.flatten]}.flatten]
77
+ headers.reject! {|k,v| k =~ /[Aa]ccept/ && v = '*/*'}
78
+
79
+ request_profile = WebMock::RequestProfile.new(method, uri, body, headers)
80
+
81
+ if WebMock.registered_request?(request_profile)
82
+ @socket = Net::HTTP.socket_type.new
83
+ webmock_response = WebMock.response_for_request(request_profile)
84
+ build_net_http_response(webmock_response, &block)
85
+ elsif WebMock.net_connect_allowed?
86
+ WebMock::RequestRegistry.instance.requested.put(request_profile)
87
+ connect_without_webmock
88
+ request_without_webmock(request, body, &block)
89
+ else
90
+ uri = WebMock::Utility.strip_default_port_from_uri(uri)
91
+ message = "Real HTTP connections are disabled. Unregistered request: #{request.method} #{uri}"
92
+ message << " with body '#{body}'" if body
93
+ message << " with headers #{WebMock::Utility.normalize_headers(headers).inspect.gsub("\"","'")}" if
94
+ headers && !headers.empty?
95
+ raise WebMock::NetConnectNotAllowedError, message
96
+ end
97
+ end
98
+ alias_method :request_without_webmock, :request
99
+ alias_method :request, :request_with_webmock
100
+
101
+
102
+ def connect_with_webmock
103
+ unless @@alredy_checked_for_net_http_replacement_libs ||= false
104
+ WebMock::Utility.puts_warning_for_net_http_replacement_libs_if_needed
105
+ @@alredy_checked_for_net_http_replacement_libs = true
106
+ end
107
+ nil
108
+ end
109
+ alias_method :connect_without_webmock, :connect
110
+ alias_method :connect, :connect_with_webmock
111
+
112
+ def build_net_http_response(webmock_response, &block)
113
+ response = Net::HTTPResponse.send(:response_class, webmock_response.status.to_s).new("1.0", webmock_response.status.to_s, "")
114
+ response.instance_variable_set(:@body, webmock_response.body)
115
+ webmock_response.headers.to_a.each { |name, value| response[name] = value }
116
+
117
+ response.instance_variable_set(:@read, true)
118
+
119
+ response.extend StubResponse
120
+
121
+ webmock_response.raise_error_if_any
122
+
123
+ yield response if block_given?
124
+
125
+ response
126
+ end
127
+ end
128
+
129
+ end
@@ -0,0 +1,22 @@
1
+ module WebMock
2
+ class RequestExecutionVerifier
3
+
4
+ attr_accessor :request_profile, :expected_times_executed, :times_executed
5
+
6
+ def initialize(request_profile = nil, expected_times_executed = nil)
7
+ @request_profile = request_profile
8
+ @expected_times_executed = expected_times_executed || 1
9
+ end
10
+
11
+ def verify
12
+ @times_executed =
13
+ RequestRegistry.instance.times_executed(@request_profile)
14
+ @times_executed == @expected_times_executed
15
+ end
16
+
17
+ def failure_message
18
+ %Q(The request #{request_profile.to_s} was expected to execute #{expected_times_executed} time#{ (expected_times_executed == 1) ? '' : 's'} but it executed #{times_executed} time#{ (times_executed == 1) ? '' : 's'})
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,67 @@
1
+ module WebMock
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::URL.normalize_uri(self.uri) unless self.uri.is_a?(URI)
8
+ self.headers = Utility.normalize_headers(self.headers)
9
+ end
10
+
11
+ def with(options)
12
+ self.body = options[:body] if options.has_key?(:body)
13
+ self.headers = Utility.normalize_headers(options[:headers]) if options.has_key?(:headers)
14
+ self
15
+ end
16
+
17
+ #self needs to be a subset of other. Other needs to be more general.
18
+ def match(other)
19
+ match_method(other) &&
20
+ match_body(other) &&
21
+ match_headers(other) &&
22
+ match_url(other)
23
+ end
24
+
25
+ def to_s
26
+ string = "#{self.method.to_s.upcase} #{self.uri}"
27
+ string << " with body '#{body}'" if body
28
+ if headers && !headers.empty?
29
+ string << " with headers #{WebMock::Utility.normalize_headers(headers).inspect.gsub("\"","'")}"
30
+ end
31
+ string
32
+ end
33
+
34
+ private
35
+
36
+ def match_url(other)
37
+ raise "Can't match regexp request profile" if self.uri.is_a?(Regexp)
38
+ @uris_to_check ||= WebMock::URL.variations_of_uri_as_strings(self.uri)
39
+ if other.uri.is_a?(URI)
40
+ @uris_to_check.include?(other.uri.to_s)
41
+ elsif other.uri.is_a?(Regexp)
42
+ @uris_to_check.any? { |u| u.match(other.uri) }
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ def match_headers(other)
49
+ return false if self.headers && !self.headers.empty? && other.headers && other.headers.empty?
50
+ if other.headers && !other.headers.empty?
51
+ other.headers.each do | key, value |
52
+ return false unless (self.headers && self.headers.has_key?(key) && value == self.headers[key])
53
+ end
54
+ end
55
+ return true
56
+ end
57
+
58
+ def match_body(other)
59
+ other.body == self.body || other.body.nil?
60
+ end
61
+
62
+ def match_method(other)
63
+ other.method == self.method || other.method == :any
64
+ end
65
+ end
66
+
67
+ end