rack-stubs 0.0.1
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.
- data/Gemfile +7 -0
- data/README.rdoc +7 -0
- data/features/step_definitions/steps.rb +21 -0
- data/features/stub_responses.feature +69 -0
- data/features/support/env.rb +47 -0
- data/features/support/web_server.rb +15 -0
- data/lib/rack-stubs.rb +1 -0
- data/lib/rack_stubs/client.rb +38 -0
- data/lib/rack_stubs/middleware.rb +57 -0
- data/lib/rack_stubs.rb +9 -0
- data/rack-stubs.gemspec +23 -0
- data/spec/rack_stubs/client_spec.rb +71 -0
- data/spec/rack_stubs/middleware_spec.rb +21 -0
- data/spec/spec_helper.rb +6 -0
- metadata +133 -0
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Given /^(GET|POST) ([^\s]+) returns (\d\d\d) with the body "([^"]*)"$/ do |verb, path, status, body|
|
2
|
+
Then %|#{verb} #{path} should return #{status} with the body "#{body}"|
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I (GET|POST) "([^"]+)" to (\/[^\s]*) with the body:$/ do |verb, mime, path, body|
|
6
|
+
RestClient.send(verb.downcase, url(path), body, { "Content-Type" => mime })
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^(GET|POST) (\/[^\s]*) should return (\d\d\d) with the body "([^"]*)"$/ do |verb, path, status, body|
|
10
|
+
RestClient.send(verb.downcase, url(path), {}) do |response, request, result, &block|
|
11
|
+
response.code.should == status.to_i
|
12
|
+
response.body.should == body
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Then /^(GET|POST) (\/[^\s]*) should return (\d\d\d) with the body:$/ do |verb, path, status, body|
|
17
|
+
RestClient.send(verb.downcase, url(path), {}) do |response, request, result, &block|
|
18
|
+
response.code.should == status.to_i
|
19
|
+
response.body.should == body
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
Feature: Stub Responses
|
2
|
+
In order to simulate behaviour of third-party web services
|
3
|
+
As a test for my application
|
4
|
+
I want to simulate http service behaviour
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given GET /foo returns 404 with the body "Not Found"
|
8
|
+
And GET /bar returns 404 with the body "Not Found"
|
9
|
+
And POST /foo returns 404 with the body "Not Found"
|
10
|
+
And POST /bar returns 404 with the body "Not Found"
|
11
|
+
|
12
|
+
Scenario: Stub GET response
|
13
|
+
When I POST "application/json+rack-stub" to /foo with the body:
|
14
|
+
"""
|
15
|
+
{
|
16
|
+
"GET" : [200, { "header": "value" }, ["jazz"]]
|
17
|
+
}
|
18
|
+
"""
|
19
|
+
Then GET /foo should return 200 with the body "jazz"
|
20
|
+
And POST /foo should return 404 with the body "Not Found"
|
21
|
+
|
22
|
+
Scenario: Stub POST response
|
23
|
+
When I POST "application/json+rack-stub" to /bar with the body:
|
24
|
+
"""
|
25
|
+
{
|
26
|
+
"POST" : [200, { "header": "value" }, ["funk"]]
|
27
|
+
}
|
28
|
+
"""
|
29
|
+
Then POST /bar should return 200 with the body "funk"
|
30
|
+
And GET /foo should return 404 with the body "Not Found"
|
31
|
+
|
32
|
+
Scenario: Clear all stub responses
|
33
|
+
When I POST "application/json+rack-stub" to /foo with the body:
|
34
|
+
"""
|
35
|
+
{
|
36
|
+
"GET" : [200, { "header": "value" }, ["soul"]]
|
37
|
+
}
|
38
|
+
"""
|
39
|
+
And I POST "application/json+rack-stub" to /bar with the body:
|
40
|
+
"""
|
41
|
+
{
|
42
|
+
"POST" : [200, { "header": "value" }, ["brother"]]
|
43
|
+
}
|
44
|
+
"""
|
45
|
+
When I POST "application/json+rack-stub" to /rack_stubs/clear with the body:
|
46
|
+
"""
|
47
|
+
"""
|
48
|
+
Then GET /foo should return 404 with the body "Not Found"
|
49
|
+
And POST /bar should return 404 with the body "Not Found"
|
50
|
+
|
51
|
+
Scenario: List all stub responses
|
52
|
+
Then GET /rack_stubs/list should return 200 with the body "{}"
|
53
|
+
When I POST "application/json+rack-stub" to /foo with the body:
|
54
|
+
"""
|
55
|
+
{
|
56
|
+
"GET" : [200, { "header": "value" }, ["salsa"]]
|
57
|
+
}
|
58
|
+
"""
|
59
|
+
And I POST "application/json+rack-stub" to /bar with the body:
|
60
|
+
"""
|
61
|
+
{
|
62
|
+
"POST" : [200, { "header": "value" }, ["chicken"]]
|
63
|
+
}
|
64
|
+
"""
|
65
|
+
Then GET /rack_stubs/list should return 200 with the body:
|
66
|
+
"""
|
67
|
+
{"/foo":{"GET":[200,{"header":"value"},["salsa"]]},"/bar":{"POST":[200,{"header":"value"},["chicken"]]}}
|
68
|
+
"""
|
69
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'mongrel'
|
2
|
+
require 'restclient'
|
3
|
+
|
4
|
+
$:.unshift(File.dirname(__FILE__) + '/../../lib')
|
5
|
+
require 'rack_stubs'
|
6
|
+
|
7
|
+
module RackStubs::World
|
8
|
+
def host
|
9
|
+
"localhost"
|
10
|
+
end
|
11
|
+
|
12
|
+
def port
|
13
|
+
6663
|
14
|
+
end
|
15
|
+
|
16
|
+
def options
|
17
|
+
{ :Host => host, :Port => port }
|
18
|
+
end
|
19
|
+
|
20
|
+
def start_server
|
21
|
+
@@server ||= begin
|
22
|
+
server = WebServer.new
|
23
|
+
server.start(app, options)
|
24
|
+
server
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def url(path)
|
29
|
+
"http://#{host}:#{port}#{path}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def app
|
33
|
+
@app ||= Rack::Builder.app do
|
34
|
+
use RackStubs::Middleware
|
35
|
+
run lambda { |e|
|
36
|
+
[404, {"Content-Type" => "text/plain"}, ["Not Found"]]
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
World(RackStubs::World)
|
43
|
+
|
44
|
+
Before do
|
45
|
+
start_server
|
46
|
+
RestClient.post url("/rack_stubs/clear"), {}
|
47
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class WebServer
|
2
|
+
def start(app, options)
|
3
|
+
rack_server = nil
|
4
|
+
rack_thread = Thread.new do
|
5
|
+
::Rack::Handler::Mongrel.run(app, options) do |server|
|
6
|
+
rack_server = server
|
7
|
+
end
|
8
|
+
end
|
9
|
+
at_exit do
|
10
|
+
rack_server.stop
|
11
|
+
rack_thread.kill
|
12
|
+
end
|
13
|
+
sleep 0.05 while rack_server.nil?
|
14
|
+
end
|
15
|
+
end
|
data/lib/rack-stubs.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/rack_stubs'
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'restclient'
|
3
|
+
|
4
|
+
module RackStubs
|
5
|
+
class Client
|
6
|
+
def initialize(service, rest_client = RestClient)
|
7
|
+
@service = service
|
8
|
+
@rest_client = rest_client
|
9
|
+
end
|
10
|
+
|
11
|
+
def service_url(path)
|
12
|
+
@service.gsub(/\/+$/, '') + '/' + path.gsub(/^\/+/, '')
|
13
|
+
end
|
14
|
+
|
15
|
+
def get(path)
|
16
|
+
PathSpecification.new(service_url(path), 'GET', @rest_client)
|
17
|
+
end
|
18
|
+
|
19
|
+
def post(path)
|
20
|
+
PathSpecification.new(service_url(path), 'POST', @rest_client)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class PathSpecification
|
25
|
+
def initialize(path, http_verb, rest_client)
|
26
|
+
@path = path
|
27
|
+
@http_verb = http_verb
|
28
|
+
@rest_client = rest_client
|
29
|
+
end
|
30
|
+
|
31
|
+
def returns(status_code, response_headers, response_body)
|
32
|
+
@rest_client.post(@path,
|
33
|
+
{ @http_verb => [status_code, response_headers, response_body] }.to_json,
|
34
|
+
{"Content-Type" => "application/json+rack-stub"}
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module RackStubs
|
5
|
+
class Middleware
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
@stubs = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
request = Rack::Request.new(env)
|
13
|
+
if request.path =~ /\/rack_stubs\/clear$/
|
14
|
+
@stubs = {}
|
15
|
+
ok
|
16
|
+
elsif request.path =~ /\/rack_stubs\/list$/
|
17
|
+
[200, {"Content-Type" => "text/plain"}, [@stubs.to_json]]
|
18
|
+
elsif request.content_type == "application/json+rack-stub"
|
19
|
+
setup_stub(request.path, JSON.parse(request.body.read.to_s))
|
20
|
+
ok
|
21
|
+
elsif @stubs.include?(request.path) &&
|
22
|
+
@stubs[request.path].include?(request.request_method)
|
23
|
+
@stubs[request.path][request.request_method]
|
24
|
+
else
|
25
|
+
@app.call(env)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup_stub(path, http_verb_behaviours_hash)
|
30
|
+
@stubs[path] = http_verb_behaviours_hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(path)
|
34
|
+
PathSpecification.new(path, "GET", self)
|
35
|
+
end
|
36
|
+
|
37
|
+
def post(path)
|
38
|
+
PathSpecification.new(path, "POST", self)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
class PathSpecification
|
44
|
+
def initialize(path, http_verb, middleware)
|
45
|
+
@path, @http_verb, @middleware = path, http_verb, middleware
|
46
|
+
end
|
47
|
+
|
48
|
+
def returns(status, headers, body)
|
49
|
+
@middleware.setup_stub(@path, { @http_verb => [status, headers, body] })
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def ok
|
54
|
+
[200, {"Content-Type" => "text/plain"}, ["OK"]]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/rack_stubs.rb
ADDED
data/rack-stubs.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
3
|
+
require "rack_stubs"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'rack-stubs'
|
7
|
+
s.version = RackStubs::VERSION
|
8
|
+
s.authors = ['Josh Chisholm']
|
9
|
+
s.description = 'Makes rack apps deliver stub responses'
|
10
|
+
s.summary = "rack-stubs-#{s.version}"
|
11
|
+
s.email = 'joshuachisholm@gmail.com'
|
12
|
+
s.homepage = 'http://github.com/joshski/rack-stubs'
|
13
|
+
|
14
|
+
s.add_dependency 'json', '~> 1.4.6'
|
15
|
+
s.add_dependency 'rack', '~> 1.2.1'
|
16
|
+
s.add_dependency 'rest-client', '~> 1.4.2'
|
17
|
+
|
18
|
+
s.rubygems_version = "1.3.7"
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- {features,spec}/*`.split("\n")
|
21
|
+
s.extra_rdoc_files = ["README.rdoc"]
|
22
|
+
s.require_path = "lib"
|
23
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RackStubs
|
4
|
+
describe Client do
|
5
|
+
|
6
|
+
def rest_client_should_stub(path, responses)
|
7
|
+
@rest_client.should_receive(:post).with(path, responses.to_json, {"Content-Type" => "application/json+rack-stub"})
|
8
|
+
end
|
9
|
+
|
10
|
+
before do
|
11
|
+
@rest_client = mock("rest_client")
|
12
|
+
@client = Client.new("http://path/to/service", @rest_client)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "stubs GETs to return 404" do
|
16
|
+
rest_client_should_stub("http://path/to/service/resource", { 'GET' => [404, {}, ""] })
|
17
|
+
@client.get("/resource").returns(404, {}, "")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "stubs POSTs to return 404" do
|
21
|
+
rest_client_should_stub("http://path/to/service/resource", { 'POST' => [404, {}, ""] })
|
22
|
+
@client.post("/resource").returns(404, {}, "")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "stubs GETs to return 200" do
|
26
|
+
rest_client_should_stub("http://path/to/service/resource", { 'GET' => [200, {}, ""] })
|
27
|
+
@client.get("/resource").returns(200, {}, "")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "stubs POSTs to return 200" do
|
31
|
+
rest_client_should_stub("http://path/to/service/resource", { 'POST' => [200, {}, ""] })
|
32
|
+
@client.post("/resource").returns(200, {}, "")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "stubs GETs to return the correct body" do
|
36
|
+
rest_client_should_stub("http://path/to/service/resource", { 'GET' => [200, {}, "Success"] })
|
37
|
+
@client.get("/resource").returns(200, {}, "Success")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "stubs POSTs to return the correct body" do
|
41
|
+
rest_client_should_stub("http://path/to/service/resource", { 'POST' => [200, {}, "Success"] })
|
42
|
+
@client.post("/resource").returns(200, {}, "Success")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "stubs GETs to return the correct http headers" do
|
46
|
+
rest_client_should_stub("http://path/to/service/resource", { 'GET' => [200, { "header" => "information" }, ""] })
|
47
|
+
@client.get("/resource").returns(200, { "header" => "information" }, "")
|
48
|
+
end
|
49
|
+
|
50
|
+
it "stubs POSTs to return the correct http headers" do
|
51
|
+
rest_client_should_stub("http://path/to/service/resource", { 'POST' => [200, { "header" => "information" }, ""] })
|
52
|
+
@client.post("/resource").returns(200, { "header" => "information" }, "")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "stubs GETs with the correct path" do
|
56
|
+
rest_client_should_stub("http://path/to/service/nothing", { 'GET' => [200, {}, ""] })
|
57
|
+
@client.get("/nothing").returns(200, { }, "")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "isn't fussy about leading slashes in paths" do
|
61
|
+
rest_client_should_stub("http://path/to/service/something", { 'GET' => [200, {}, ""] })
|
62
|
+
@client.get("something").returns(200, { }, "")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "isn't fussy about trailing slashes in paths" do
|
66
|
+
rest_client_should_stub("http://path/with/a/trailing/slash/anything", { 'GET' => [200, {}, ""] })
|
67
|
+
Client.new("http://path/with/a/trailing/slash/", @rest_client).get("anything").returns(200, { }, "")
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RackStubs
|
2
|
+
describe Middleware do
|
3
|
+
it "allows GET behaviour to be specified directly, using the client interface" do
|
4
|
+
app = mock("app")
|
5
|
+
env = Rack::MockRequest.env_for("/foo")
|
6
|
+
env["REQUEST_METHOD"] = "GET"
|
7
|
+
middleware = Middleware.new(app)
|
8
|
+
middleware.get("/foo").returns(200, {}, "found!")
|
9
|
+
middleware.call(env).should == [200, {}, "found!"]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "allows POST behaviour to be specified directly, using the client interface" do
|
13
|
+
app = mock("app")
|
14
|
+
env = Rack::MockRequest.env_for("/bar")
|
15
|
+
env["REQUEST_METHOD"] = "POST"
|
16
|
+
middleware = Middleware.new(app)
|
17
|
+
middleware.post("/bar").returns(200, {}, "OK!")
|
18
|
+
middleware.call(env).should == [200, {}, "OK!"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-stubs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Josh Chisholm
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-10 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: json
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 11
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 4
|
33
|
+
- 6
|
34
|
+
version: 1.4.6
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rack
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 29
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 2
|
49
|
+
- 1
|
50
|
+
version: 1.2.1
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rest-client
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 3
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 4
|
65
|
+
- 2
|
66
|
+
version: 1.4.2
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
description: Makes rack apps deliver stub responses
|
70
|
+
email: joshuachisholm@gmail.com
|
71
|
+
executables: []
|
72
|
+
|
73
|
+
extensions: []
|
74
|
+
|
75
|
+
extra_rdoc_files:
|
76
|
+
- README.rdoc
|
77
|
+
files:
|
78
|
+
- Gemfile
|
79
|
+
- README.rdoc
|
80
|
+
- features/step_definitions/steps.rb
|
81
|
+
- features/stub_responses.feature
|
82
|
+
- features/support/env.rb
|
83
|
+
- features/support/web_server.rb
|
84
|
+
- lib/rack-stubs.rb
|
85
|
+
- lib/rack_stubs.rb
|
86
|
+
- lib/rack_stubs/client.rb
|
87
|
+
- lib/rack_stubs/middleware.rb
|
88
|
+
- rack-stubs.gemspec
|
89
|
+
- spec/rack_stubs/client_spec.rb
|
90
|
+
- spec/rack_stubs/middleware_spec.rb
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://github.com/joshski/rack-stubs
|
94
|
+
licenses: []
|
95
|
+
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
hash: 3
|
107
|
+
segments:
|
108
|
+
- 0
|
109
|
+
version: "0"
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
hash: 3
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
version: "0"
|
119
|
+
requirements: []
|
120
|
+
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 1.4.1
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: rack-stubs-0.0.1
|
126
|
+
test_files:
|
127
|
+
- features/step_definitions/steps.rb
|
128
|
+
- features/stub_responses.feature
|
129
|
+
- features/support/env.rb
|
130
|
+
- features/support/web_server.rb
|
131
|
+
- spec/rack_stubs/client_spec.rb
|
132
|
+
- spec/rack_stubs/middleware_spec.rb
|
133
|
+
- spec/spec_helper.rb
|