webstub 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/.rvmrc +5 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +37 -0
- data/Guardfile +8 -0
- data/LICENSE +7 -0
- data/Rakefile +21 -0
- data/lib/spec/spec_delegate.rb +5 -0
- data/lib/webstub/api.rb +21 -0
- data/lib/webstub/bacon.rb +7 -0
- data/lib/webstub/json.rb +10 -0
- data/lib/webstub/protocol.rb +96 -0
- data/lib/webstub/registry.rb +32 -0
- data/lib/webstub/stub.rb +80 -0
- data/lib/webstub/uri.rb +16 -0
- data/lib/webstub/version.rb +3 -0
- data/lib/webstub.rb +8 -0
- data/spec/api_spec.rb +139 -0
- data/spec/helpers/request_helper.rb +46 -0
- data/spec/json_spec.rb +21 -0
- data/spec/protocol_spec.rb +83 -0
- data/spec/registry_spec.rb +24 -0
- data/spec/stub_spec.rb +99 -0
- data/spec/uri_spec.rb +16 -0
- data/webstub.gemspec +16 -0
- metadata +78 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/guard/guard.git
|
3
|
+
revision: 863fa1247e07a0659edebfede61cf16096496c36
|
4
|
+
specs:
|
5
|
+
guard (1.3.2)
|
6
|
+
listen (>= 0.4.2)
|
7
|
+
thor (>= 0.14.6)
|
8
|
+
|
9
|
+
GIT
|
10
|
+
remote: git://github.com/guard/listen.git
|
11
|
+
revision: edff3eb1dfca5e7864460ece2322e85097fb0209
|
12
|
+
specs:
|
13
|
+
listen (0.5.0)
|
14
|
+
|
15
|
+
GEM
|
16
|
+
remote: http://rubygems.org/
|
17
|
+
specs:
|
18
|
+
coolline (0.3.0)
|
19
|
+
guard-motion (0.1.0)
|
20
|
+
guard (>= 1.1.0)
|
21
|
+
rake (>= 0.9)
|
22
|
+
rake (0.9.2.2)
|
23
|
+
rb-fsevent (0.9.1)
|
24
|
+
terminal-notifier-guard (1.5.3)
|
25
|
+
thor (0.16.0)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
coolline
|
32
|
+
guard!
|
33
|
+
guard-motion
|
34
|
+
listen!
|
35
|
+
rake
|
36
|
+
rb-fsevent (~> 0.9.1)
|
37
|
+
terminal-notifier-guard
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2012 Matt Green
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$:.unshift("/Library/RubyMotion/lib")
|
2
|
+
require 'motion/project'
|
3
|
+
|
4
|
+
require 'bundler'
|
5
|
+
Bundler.setup
|
6
|
+
Bundler.require
|
7
|
+
|
8
|
+
Motion::Project::App.setup do |app|
|
9
|
+
gemspec = Dir.glob(File.join(File.dirname(__FILE__), "*.gemspec")).first
|
10
|
+
gem_name = File.basename(gemspec).gsub("\.gemspec", "")
|
11
|
+
|
12
|
+
app.development do
|
13
|
+
app.files += Dir.glob(File.join(File.dirname(__FILE__), "lib/#{gem_name}/**/*.rb"))
|
14
|
+
|
15
|
+
app.files << File.join(File.dirname(__FILE__), "lib/spec/spec_delegate.rb")
|
16
|
+
app.delegate_class = "SpecDelegate"
|
17
|
+
end
|
18
|
+
|
19
|
+
app.name = gem_name
|
20
|
+
end
|
21
|
+
|
data/lib/webstub/api.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module WebStub
|
2
|
+
module API
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def disable_network_access!
|
6
|
+
Protocol.disable_network_access!
|
7
|
+
end
|
8
|
+
|
9
|
+
def enable_network_access!
|
10
|
+
Protocol.enable_network_access!
|
11
|
+
end
|
12
|
+
|
13
|
+
def stub_request(method, path)
|
14
|
+
Protocol.add_stub(method, path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset_stubs
|
18
|
+
Protocol.reset_stubs
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/webstub/json.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module WebStub
|
2
|
+
class Protocol < NSURLProtocol
|
3
|
+
def self.add_stub(*args)
|
4
|
+
registry.add_stub(*args)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.canInitWithRequest(request)
|
8
|
+
if stub_for(request)
|
9
|
+
return true
|
10
|
+
end
|
11
|
+
|
12
|
+
! network_access_allowed?
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.canonicalRequestForRequest(request)
|
16
|
+
request
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.disable_network_access!
|
20
|
+
@network_access = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.enable_network_access!
|
24
|
+
@network_access = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.network_access_allowed?
|
28
|
+
@network_access.nil? ? true : @network_access
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.reset_stubs
|
32
|
+
registry.reset
|
33
|
+
end
|
34
|
+
|
35
|
+
def startLoading
|
36
|
+
request = self.request
|
37
|
+
client = self.client
|
38
|
+
|
39
|
+
unless stub = self.class.stub_for(request)
|
40
|
+
error = NSError.errorWithDomain("WebStub", code:0, userInfo:{ NSLocalizedDescriptionKey: "network access is not permitted!"})
|
41
|
+
client.URLProtocol(self, didFailWithError:error)
|
42
|
+
|
43
|
+
return
|
44
|
+
end
|
45
|
+
|
46
|
+
response = NSHTTPURLResponse.alloc.initWithURL(request.URL,
|
47
|
+
statusCode:200,
|
48
|
+
HTTPVersion:"HTTP/1.1",
|
49
|
+
headerFields:stub.response_headers)
|
50
|
+
|
51
|
+
client.URLProtocol(self, didReceiveResponse:response, cacheStoragePolicy:NSURLCacheStorageNotAllowed)
|
52
|
+
client.URLProtocol(self, didLoadData:stub.response_body.dataUsingEncoding(NSUTF8StringEncoding))
|
53
|
+
client.URLProtocolDidFinishLoading(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def stopLoading
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def self.registry
|
62
|
+
@registry ||= Registry.new()
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.stub_for(request)
|
66
|
+
options = {}
|
67
|
+
if request.HTTPBody
|
68
|
+
options[:body] = parse_body(request)
|
69
|
+
end
|
70
|
+
|
71
|
+
registry.stub_matching(request.HTTPMethod, request.URL.absoluteString, options)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.parse_body(request)
|
75
|
+
content_type = nil
|
76
|
+
|
77
|
+
request.allHTTPHeaderFields.each do |key, value|
|
78
|
+
if key.downcase == "content-type"
|
79
|
+
content_type = value
|
80
|
+
break
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
body = NSString.alloc.initWithData(request.HTTPBody, encoding:NSUTF8StringEncoding)
|
85
|
+
|
86
|
+
case content_type
|
87
|
+
when /application\/x-www-form-urlencoded/
|
88
|
+
URI.decode_www_form(body)
|
89
|
+
else
|
90
|
+
body
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
NSURLProtocol.registerClass(WebStub::Protocol)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module WebStub
|
2
|
+
class Registry
|
3
|
+
def initialize()
|
4
|
+
@stubs = []
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_stub(method, path)
|
8
|
+
stub = Stub.new(method, path)
|
9
|
+
@stubs << stub
|
10
|
+
|
11
|
+
stub
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
@stubs = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def size
|
19
|
+
@stubs.size
|
20
|
+
end
|
21
|
+
|
22
|
+
def stub_matching(method, url, options={})
|
23
|
+
@stubs.each do |stub|
|
24
|
+
if stub.matches?(method, url, options)
|
25
|
+
return stub
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/webstub/stub.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module WebStub
|
2
|
+
class Stub
|
3
|
+
METHODS = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].freeze
|
4
|
+
|
5
|
+
def initialize(method, url)
|
6
|
+
@request_method = canonicalize_method(method)
|
7
|
+
raise ArgumentError, "invalid method name" unless METHODS.include? @request_method
|
8
|
+
|
9
|
+
@request_url = canonicalize_url(url)
|
10
|
+
@request_headers = nil
|
11
|
+
@request_body = nil
|
12
|
+
|
13
|
+
@response_body = ""
|
14
|
+
@response_headers = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def matches?(method, url, options={})
|
18
|
+
if @request_url != canonicalize_url(url)
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
if @request_method != canonicalize_method(method)
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
if @request_body
|
27
|
+
if @request_body != options[:body]
|
28
|
+
return false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :response_body
|
36
|
+
attr_reader :response_headers
|
37
|
+
|
38
|
+
def to_return(options)
|
39
|
+
if json = options[:json]
|
40
|
+
@response_body = json
|
41
|
+
@response_headers["Content-Type"] = "application/json"
|
42
|
+
|
43
|
+
if @response_body.is_a? Hash
|
44
|
+
@response_body = JSON.generate(@response_body)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
@response_body = options[:body] || ""
|
48
|
+
@response_headers = options[:headers] || {}
|
49
|
+
|
50
|
+
if content_type = options[:content_type]
|
51
|
+
@response_headers["Content-Type"] = content_type
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def with(options)
|
59
|
+
if body = options[:body]
|
60
|
+
@request_body = body
|
61
|
+
|
62
|
+
if @request_body.is_a?(Hash)
|
63
|
+
@request_body = @request_body.inject({}) { |h, (k,v)| h[k.to_s] = v; h }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def canonicalize_method(method)
|
73
|
+
method.to_s.upcase
|
74
|
+
end
|
75
|
+
|
76
|
+
def canonicalize_url(url)
|
77
|
+
url
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/webstub/uri.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module WebStub
|
2
|
+
module URI
|
3
|
+
def self.decode_www_form(str)
|
4
|
+
str.split("&").inject({}) do |hash, component|
|
5
|
+
key, value = component.split("=", 2)
|
6
|
+
hash[decode_www_form_component(key)] = decode_www_form_component(value)
|
7
|
+
|
8
|
+
hash
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.decode_www_form_component(str)
|
13
|
+
str.gsub("+", " ").stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/webstub.rb
ADDED
data/spec/api_spec.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
describe WebStub::API do
|
2
|
+
before do
|
3
|
+
WebStub::API.reset_stubs
|
4
|
+
|
5
|
+
@url = "http://www.google.com/search"
|
6
|
+
@request = NSURLRequest.requestWithURL(NSURL.URLWithString(@url))
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".stub_request" do
|
10
|
+
it "returns the newly added stub" do
|
11
|
+
WebStub::API.stub_request(:get, @url).should.not.be.nil
|
12
|
+
end
|
13
|
+
|
14
|
+
before { WebStub::API.disable_network_access! }
|
15
|
+
after { WebStub::API.enable_network_access! }
|
16
|
+
|
17
|
+
describe "when a request does not match any previously set stubs" do
|
18
|
+
describe "when no body is set" do
|
19
|
+
before do
|
20
|
+
@response = get @url
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns a nil body" do
|
24
|
+
@response.body.should.be.nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns an error with a description of the problem" do
|
28
|
+
@response.error.localizedDescription.should.not.be.empty
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when a body is set" do
|
33
|
+
before do
|
34
|
+
WebStub::API.stub_request(:post, @url).
|
35
|
+
with(body: { :q => "hi" })
|
36
|
+
|
37
|
+
@response = post @url, :q => "hello"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "requires the request body to match" do
|
41
|
+
@response.body.should.be.nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "when a request matches a stub" do
|
47
|
+
describe "and the request does include a body" do
|
48
|
+
before do
|
49
|
+
WebStub::API.stub_request(:get, @url).to_return(body:"hello", headers: {"Content-Type" => "text/plain"})
|
50
|
+
|
51
|
+
@response = get @url
|
52
|
+
end
|
53
|
+
|
54
|
+
it "has the content-type header" do
|
55
|
+
@response.headers["Content-Type"].should == "text/plain"
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns a non-nil body" do
|
59
|
+
@response.body.length.should.be == 5
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns a nil error" do
|
63
|
+
@response.error.should.be.nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "and the request includes a body" do
|
68
|
+
describe "of form data" do
|
69
|
+
before do
|
70
|
+
WebStub::API.stub_request(:post, @url).
|
71
|
+
with(body: { q: "search" }).
|
72
|
+
to_return(json: { results: ["result 1", "result 2"] })
|
73
|
+
|
74
|
+
@response = post @url, :q => "search"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "returns the correct body" do
|
78
|
+
@response.body.should == '{"results":["result 1","result 2"]}'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "with raw data" do
|
84
|
+
before do
|
85
|
+
WebStub::API.stub_request(:post, @url).
|
86
|
+
with(body: "raw body").
|
87
|
+
to_return(json: { results: ["result 1", "result 2"] })
|
88
|
+
|
89
|
+
@response = post @url, "raw body"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "returns the correct body" do
|
93
|
+
@response.body.should == '{"results":["result 1","result 2"]}'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe ".reset_stubs" do
|
100
|
+
before do
|
101
|
+
WebStub::API.stub_request(:get, @url)
|
102
|
+
WebStub::API.reset_stubs
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "when network access is disabled" do
|
106
|
+
before do
|
107
|
+
WebStub::API.disable_network_access!
|
108
|
+
|
109
|
+
@response = get @url
|
110
|
+
end
|
111
|
+
|
112
|
+
after do
|
113
|
+
WebStub::API.enable_network_access!
|
114
|
+
end
|
115
|
+
|
116
|
+
it "returns a nil body" do
|
117
|
+
@response.body.should.be.nil
|
118
|
+
end
|
119
|
+
|
120
|
+
it "returns an error with a description of the problem" do
|
121
|
+
@response.error.localizedDescription.should.not.be.empty
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "when network access is enabled" do
|
126
|
+
before do
|
127
|
+
@response = get @url
|
128
|
+
end
|
129
|
+
|
130
|
+
it "returns a non-nil body" do
|
131
|
+
@response.body.length.should.be > 100
|
132
|
+
end
|
133
|
+
|
134
|
+
it "returns a nil error" do
|
135
|
+
@response.error.should.be.nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Response
|
2
|
+
def initialize(body, response, error)
|
3
|
+
@body = body ? NSString.alloc.initWithData(body, encoding:NSUTF8StringEncoding) : nil
|
4
|
+
@headers = response ? response.allHeaderFields : nil
|
5
|
+
@error = error
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :body
|
9
|
+
attr_reader :headers
|
10
|
+
attr_reader :error
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(url)
|
14
|
+
request = NSURLRequest.requestWithURL(NSURL.URLWithString(url))
|
15
|
+
|
16
|
+
response = Pointer.new(:object)
|
17
|
+
error = Pointer.new(:object)
|
18
|
+
body = NSURLConnection.sendSynchronousRequest(request, returningResponse:response, error:error)
|
19
|
+
|
20
|
+
Response.new(body, response[0], error[0])
|
21
|
+
end
|
22
|
+
|
23
|
+
def post(url, body)
|
24
|
+
request = NSMutableURLRequest.alloc.initWithURL(NSURL.URLWithString(url))
|
25
|
+
request.HTTPMethod = "POST"
|
26
|
+
|
27
|
+
if body.is_a?(Hash)
|
28
|
+
body = body.map do |key, value|
|
29
|
+
key = key.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
|
30
|
+
value = value.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
|
31
|
+
|
32
|
+
"#{key}=#{value}"
|
33
|
+
end.join("&")
|
34
|
+
|
35
|
+
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")
|
36
|
+
end
|
37
|
+
|
38
|
+
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
|
39
|
+
|
40
|
+
response = Pointer.new(:object)
|
41
|
+
error = Pointer.new(:object)
|
42
|
+
body = NSURLConnection.sendSynchronousRequest(request, returningResponse:response, error:error)
|
43
|
+
|
44
|
+
Response.new(body, response[0], error[0])
|
45
|
+
end
|
46
|
+
|
data/spec/json_spec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
describe WebStub::JSON do
|
2
|
+
describe ".generate" do
|
3
|
+
it "encodes an empty Array as JSON" do
|
4
|
+
WebStub::JSON.generate([]).should == "[]"
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'encodes an empty Hash as JSON' do
|
8
|
+
WebStub::JSON.generate({}).should == "{}"
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'encodes a Hash as JSON' do
|
12
|
+
WebStub::JSON.generate({
|
13
|
+
int: 42,
|
14
|
+
string: "hello",
|
15
|
+
array: [1,2,3],
|
16
|
+
hash: {
|
17
|
+
title: "the title"
|
18
|
+
}}).should == "{\"int\":42,\"string\":\"hello\",\"array\":[1,2,3],\"hash\":{\"title\":\"the title\"}}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
describe WebStub::Protocol do
|
2
|
+
before do
|
3
|
+
WebStub::Protocol.reset_stubs
|
4
|
+
|
5
|
+
@request = NSURLRequest.requestWithURL(NSURL.URLWithString("http://www.google.com/"))
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".canInitWithRequest" do
|
9
|
+
describe "when network access is allowed" do
|
10
|
+
it "returns false for unstubbed requests" do
|
11
|
+
WebStub::Protocol.canInitWithRequest(@request).should.be.false
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns true for stubbed requests" do
|
15
|
+
WebStub::Protocol.add_stub(:get, "http://www.google.com/")
|
16
|
+
WebStub::Protocol.canInitWithRequest(@request).should.be.true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "when network access is disabled" do
|
21
|
+
before { WebStub::Protocol.disable_network_access! }
|
22
|
+
after { WebStub::Protocol.enable_network_access! }
|
23
|
+
|
24
|
+
it "handles all requests" do
|
25
|
+
WebStub::Protocol.canInitWithRequest(@request).should.be.true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe ".disable_network_access!" do
|
31
|
+
before { WebStub::Protocol.disable_network_access! }
|
32
|
+
after { WebStub::Protocol.enable_network_access! }
|
33
|
+
|
34
|
+
it "disables network access" do
|
35
|
+
WebStub::Protocol.network_access_allowed?.should.be.false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe ".enable_network_access!" do
|
40
|
+
before do
|
41
|
+
WebStub::Protocol.disable_network_access!
|
42
|
+
WebStub::Protocol.enable_network_access!
|
43
|
+
end
|
44
|
+
|
45
|
+
it "enables network access" do
|
46
|
+
WebStub::Protocol.network_access_allowed?.should.be.true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".isNetworkAccessAllowed" do
|
51
|
+
describe "by default" do
|
52
|
+
it "returns true" do
|
53
|
+
WebStub::Protocol.network_access_allowed?.should.be.true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "when network access has been disabled" do
|
58
|
+
before { WebStub::Protocol.disable_network_access! }
|
59
|
+
after { WebStub::Protocol.enable_network_access! }
|
60
|
+
|
61
|
+
it "returns false" do
|
62
|
+
WebStub::Protocol.network_access_allowed?.should.be.false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "when network access has been disabled, then enabled" do
|
67
|
+
before do
|
68
|
+
WebStub::Protocol.disable_network_access!
|
69
|
+
WebStub::Protocol.enable_network_access!
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns true" do
|
73
|
+
WebStub::Protocol.network_access_allowed?.should.be.true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".registry" do
|
79
|
+
it "stores the stub registry as a singleton" do
|
80
|
+
WebStub::Protocol.registry.object_id.should == WebStub::Protocol.registry.object_id
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
describe WebStub::Registry do
|
2
|
+
before do
|
3
|
+
@registry = WebStub::Registry.new()
|
4
|
+
end
|
5
|
+
|
6
|
+
it "has no requests initially" do
|
7
|
+
@registry.size.should == 0
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#add_stub" do
|
11
|
+
it "inserts a stub" do
|
12
|
+
@registry.add_stub(:get, "http://www.yahoo.com/")
|
13
|
+
@registry.size.should == 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#reset" do
|
18
|
+
it "removes all previously set stubs" do
|
19
|
+
@registry.add_stub(:get, "http://www.yahoo.com")
|
20
|
+
@registry.reset
|
21
|
+
@registry.size.should == 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/stub_spec.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
describe WebStub::Stub do
|
2
|
+
before do
|
3
|
+
@stub = WebStub::Stub.new(:get, "http://www.yahoo.com/")
|
4
|
+
end
|
5
|
+
|
6
|
+
it "holds the method and the path" do
|
7
|
+
@stub.should.not.be.nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it "allows all valid HTTP methods" do
|
11
|
+
WebStub::Stub::METHODS.each do |method|
|
12
|
+
lambda { WebStub::Stub.new(method, "http://www.yahoo.com/") }.should.not.raise(ArgumentError)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "does not allow invalid HTTP methods" do
|
17
|
+
lambda { WebStub::Stub.new("invalid", "http://www.yahoo.com/") }.should.raise(ArgumentError)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#matches?" do
|
21
|
+
it "returns true when provided an identical stub" do
|
22
|
+
@stub.matches?(:get, "http://www.yahoo.com/").should.be.true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns false when the URL differs" do
|
26
|
+
@stub.matches?(:get, "http://www.google.com/").should.be.false
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns false when the method differs" do
|
30
|
+
@stub.matches?(:post, "http://www.yahoo.com/").should.be.false
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "body" do
|
34
|
+
describe "with a dictionary" do
|
35
|
+
before do
|
36
|
+
@stub = WebStub::Stub.new(:post, "http://www.yahoo.com/search").
|
37
|
+
with(body: { :q => "query"})
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns false when the body does not match" do
|
41
|
+
@stub.matches?(:post, "http://www.yahoo.com/search", { :body => {}}).should.be.false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns true when the body matches (with string keys)" do
|
45
|
+
@stub.matches?(:post, "http://www.yahoo.com/search", { :body => { "q" => "query" }}).should.be.true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "with a string" do
|
50
|
+
before do
|
51
|
+
@stub = WebStub::Stub.new(:post, "http://www.yahoo.com/search").
|
52
|
+
with(body: "raw body")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns true when an identical body is provided" do
|
56
|
+
@stub.matches?(:post, "http://www.yahoo.com/search", { :body => "raw body" }).should.be.true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns false when a dictionary is provided" do
|
60
|
+
@stub.matches?(:post, "http://www.yahoo.com/search", { :body => { "q" => "query" }}).should.be.false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns false without a body" do
|
64
|
+
@stub.matches?(:post, "http://www.yahoo.com/search").should.be.false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#response_body" do
|
71
|
+
it "returns the response body" do
|
72
|
+
@stub.response_body.should == ""
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#to_return" do
|
77
|
+
it "sets the response body" do
|
78
|
+
@stub.to_return(body: "hello")
|
79
|
+
@stub.response_body.should.be == "hello"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "allows JSON results by passing :json with a string" do
|
83
|
+
@stub.to_return(json: '{"value":42}')
|
84
|
+
@stub.response_headers["Content-Type"].should == "application/json"
|
85
|
+
@stub.response_body.should == '{"value":42}'
|
86
|
+
end
|
87
|
+
|
88
|
+
it "allows JSON results by passing :json with a hash" do
|
89
|
+
@stub.to_return(json: {:value => 42})
|
90
|
+
@stub.response_headers["Content-Type"].should == "application/json"
|
91
|
+
@stub.response_body.should == '{"value":42}'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "sets response headers" do
|
95
|
+
@stub.to_return(body: "{}", headers: { "Content-Type" => "application/json" })
|
96
|
+
@stub.response_headers.should.be == { "Content-Type" => "application/json" }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/uri_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
describe WebStub::URI do
|
2
|
+
describe ".decode_www_form" do
|
3
|
+
it "decodes a simple form into a Hash" do
|
4
|
+
WebStub::URI.decode_www_form("a=42&b=hello").should == { "a" => "42", "b" => "hello" }
|
5
|
+
end
|
6
|
+
|
7
|
+
it "unescapes reserved characters properly" do
|
8
|
+
WebStub::URI.decode_www_form("comment=hello%2C+my+name+is+%21%40%23%24%25%5E%5E%26*%28%29_-%2B%3D").should ==
|
9
|
+
{ "comment" => 'hello, my name is !@#$%^^&*()_-+=' }
|
10
|
+
end
|
11
|
+
|
12
|
+
it "produces the same Hash, regardless of how components were ordered" do
|
13
|
+
WebStub::URI.decode_www_form("a=42&b=hello").should == WebStub::URI.decode_www_form("b=hello&a=42")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/webstub.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), "lib/webstub/version")
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Matt Green"]
|
6
|
+
gem.email = ["mattgreenrocks@gmail.com"]
|
7
|
+
gem.description = "Easily stub out HTTP responses in RubyMotion specs"
|
8
|
+
gem.summary = "Easily stub out HTTP responses in RubyMotion specs"
|
9
|
+
gem.homepage = "https://github.com/mattgreen/webstub"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
|
+
gem.name = "webstub"
|
14
|
+
gem.require_paths = ["lib"]
|
15
|
+
gem.version = WebStub::VERSION
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webstub
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matt Green
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-18 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Easily stub out HTTP responses in RubyMotion specs
|
15
|
+
email:
|
16
|
+
- mattgreenrocks@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- .rvmrc
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- Guardfile
|
26
|
+
- LICENSE
|
27
|
+
- Rakefile
|
28
|
+
- lib/spec/spec_delegate.rb
|
29
|
+
- lib/webstub.rb
|
30
|
+
- lib/webstub/api.rb
|
31
|
+
- lib/webstub/bacon.rb
|
32
|
+
- lib/webstub/json.rb
|
33
|
+
- lib/webstub/protocol.rb
|
34
|
+
- lib/webstub/registry.rb
|
35
|
+
- lib/webstub/stub.rb
|
36
|
+
- lib/webstub/uri.rb
|
37
|
+
- lib/webstub/version.rb
|
38
|
+
- spec/api_spec.rb
|
39
|
+
- spec/helpers/request_helper.rb
|
40
|
+
- spec/json_spec.rb
|
41
|
+
- spec/protocol_spec.rb
|
42
|
+
- spec/registry_spec.rb
|
43
|
+
- spec/stub_spec.rb
|
44
|
+
- spec/uri_spec.rb
|
45
|
+
- webstub.gemspec
|
46
|
+
homepage: https://github.com/mattgreen/webstub
|
47
|
+
licenses: []
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.8.24
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Easily stub out HTTP responses in RubyMotion specs
|
70
|
+
test_files:
|
71
|
+
- spec/api_spec.rb
|
72
|
+
- spec/helpers/request_helper.rb
|
73
|
+
- spec/json_spec.rb
|
74
|
+
- spec/protocol_spec.rb
|
75
|
+
- spec/registry_spec.rb
|
76
|
+
- spec/stub_spec.rb
|
77
|
+
- spec/uri_spec.rb
|
78
|
+
has_rdoc:
|