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 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