webstub 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .repl_history
2
+ build
3
+ resources/*.nib
4
+ resources/*.momd
5
+ resources/*.storyboardc
data/.rvmrc ADDED
@@ -0,0 +1,5 @@
1
+ rvm ruby-1.9.3-p194@rubymotion --create
2
+
3
+ [[ -s "config/rvm_env.sh" ]] && . "config/rvm_env.sh"
4
+ [[ -s ".rvm_env" ]] && . ".rvm_env"
5
+
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ gem 'rake'
4
+
5
+ gem 'listen', :git => 'git://github.com/guard/listen.git'
6
+ gem 'guard', :git => 'git://github.com/guard/guard.git'
7
+ gem 'guard-motion'
8
+ gem 'rb-fsevent', '~> 0.9.1'
9
+ gem 'coolline'
10
+ gem 'terminal-notifier-guard'
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
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'motion', :env => {:output => 'test_unit'}, :keep_failed => false do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+
7
+ watch(%r{^lib/[^/]+/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8
+ end
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
+
@@ -0,0 +1,5 @@
1
+ class SpecDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ true
4
+ end
5
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ # HACK: need define_method to be legal
2
+ class Bacon
3
+ class Context
4
+ include WebStub::API
5
+ end
6
+ end
7
+
@@ -0,0 +1,10 @@
1
+ module WebStub
2
+ module JSON
3
+ def self.generate(hash)
4
+ error = Pointer.new(:object)
5
+ result = NSJSONSerialization.dataWithJSONObject(hash, options:0, error:error)
6
+
7
+ NSString.alloc.initWithData(result, encoding:NSUTF8StringEncoding)
8
+ end
9
+ end
10
+ end
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module WebStub
2
+ VERSION = "0.3.0"
3
+ end
data/lib/webstub.rb ADDED
@@ -0,0 +1,8 @@
1
+ gem_name = File.basename(__FILE__).gsub(/\.rb$/, "")
2
+
3
+ Motion::Project::App.setup do |app|
4
+ app.development do
5
+ gem_files = Dir.glob(File.join(File.dirname(__FILE__), gem_name, "**/*.rb"))
6
+ app.files = gem_files + app.files
7
+ end
8
+ end
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: