rack-stubs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem 'bundler', '~> 1.0.7'
5
+ end
6
+
7
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = Rack Stubs
2
+
3
+ Rack middleware for specifying behaviour of HTTP resources by POSTing stub representations.
4
+
5
+ == Usage
6
+
7
+ See the features :)
@@ -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
@@ -0,0 +1,9 @@
1
+ lib = File.dirname(__FILE__)
2
+ $:.unshift(lib) unless $:.include?(lib) || $:.include?(File.expand_path(lib))
3
+
4
+ module RackStubs
5
+ VERSION = '0.0.1'
6
+ end
7
+
8
+ require 'rack_stubs/middleware'
9
+ require 'rack_stubs/client'
@@ -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
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require 'rubygems'
4
+ require 'rspec'
5
+
6
+ require File.dirname(__FILE__) + '/../lib/rack_stubs'
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