http_stub 0.1.4 → 0.2.0

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.
@@ -7,7 +7,11 @@ require 'immutable_struct'
7
7
  require 'net/http'
8
8
  require 'json'
9
9
 
10
- require File.expand_path('../http_stub/stub', __FILE__)
11
- require File.expand_path('../http_stub/registry', __FILE__)
10
+ require File.expand_path('../http_stub/response', __FILE__)
11
+ require File.expand_path('../http_stub/models/stub', __FILE__)
12
+ require File.expand_path('../http_stub/models/alias', __FILE__)
13
+ require File.expand_path('../http_stub/models/registry', __FILE__)
14
+ require File.expand_path('../http_stub/controllers/stub_controller', __FILE__)
15
+ require File.expand_path('../http_stub/controllers/alias_controller', __FILE__)
12
16
  require File.expand_path('../http_stub/server', __FILE__)
13
- require File.expand_path('../http_stub/client', __FILE__)
17
+ require File.expand_path('../http_stub/configurer', __FILE__)
@@ -0,0 +1,75 @@
1
+ module HttpStub
2
+
3
+ module Configurer
4
+
5
+ def self.included(mod)
6
+ mod.extend(HttpStub::Configurer::ClassMethods)
7
+ mod.send(:include, HttpStub::Configurer::InstanceMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def host(host)
13
+ @host = host
14
+ end
15
+
16
+ def port(port)
17
+ @port = port
18
+ end
19
+
20
+ def stub_alias(alias_uri, stub_uri, options)
21
+ response_options = options[:response]
22
+ request = Net::HTTP::Post.new("/stubs/aliases")
23
+ request.content_type = "application/json"
24
+ request.body = {
25
+ "alias_uri" => alias_uri,
26
+ "uri" => stub_uri,
27
+ "method" => options[:method],
28
+ "parameters" => options[:parameters] || {},
29
+ "response" => {
30
+ "status" => response_options[:status] || "200",
31
+ "body" => response_options[:body]
32
+ }
33
+ }.to_json
34
+ response = submit(request)
35
+ raise "Unable to establish stub alias: #{response.message}" unless response.code == "200"
36
+ end
37
+
38
+ def submit(request)
39
+ Net::HTTP.new(@host, @port).start { |http| http.request(request) }
40
+ end
41
+
42
+ end
43
+
44
+ module InstanceMethods
45
+
46
+ def stub!(uri, options)
47
+ response_options = options[:response]
48
+ request = Net::HTTP::Post.new("/stubs")
49
+ request.content_type = "application/json"
50
+ request.body = {
51
+ "uri" => uri,
52
+ "method" => options[:method],
53
+ "parameters" => options[:parameters] || {},
54
+ "response" => {
55
+ "status" => response_options[:status] || "200",
56
+ "body" => response_options[:body]
57
+ }
58
+ }.to_json
59
+ response = self.class.submit(request)
60
+ raise "Unable to establish stub: #{response.message}" unless response.code == "200"
61
+ end
62
+
63
+ alias_method :stub_response!, :stub!
64
+
65
+ def clear!
66
+ request = Net::HTTP::Delete.new("/stubs")
67
+ response = self.class.submit(request)
68
+ raise "Unable to clear stubs: #{response.message}" unless response.code == "200"
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,29 @@
1
+ module HttpStub
2
+ module Controllers
3
+
4
+ class AliasController
5
+
6
+ def initialize(alias_registry, stub_registry)
7
+ @alias_registry = alias_registry
8
+ @stub_registry = stub_registry
9
+ end
10
+
11
+ def register(request)
12
+ @alias_registry.add(HttpStub::Models::Alias.new(request.body.read), request)
13
+ HttpStub::Response::SUCCESS
14
+ end
15
+
16
+ def activate(request)
17
+ the_alias = @alias_registry.find_for(request)
18
+ if the_alias
19
+ @stub_registry.add(the_alias.the_stub, request)
20
+ HttpStub::Response::SUCCESS
21
+ else
22
+ HttpStub::Response::EMPTY
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module HttpStub
2
+ module Controllers
3
+
4
+ class StubController
5
+
6
+ def initialize(registry)
7
+ @registry = registry
8
+ end
9
+
10
+ def register(request)
11
+ @registry.add(HttpStub::Models::Stub.new(request.body.read), request)
12
+ HttpStub::Response::SUCCESS
13
+ end
14
+
15
+ def replay(request)
16
+ stub = @registry.find_for(request)
17
+ stub ? stub.response : HttpStub::Response::EMPTY
18
+ end
19
+
20
+ def clear(request)
21
+ @registry.clear(request)
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module HttpStub
2
+ module Models
3
+
4
+ class Alias
5
+
6
+ def initialize(request_body)
7
+ @data = JSON.parse(request_body)
8
+ @stub = HttpStub::Models::Stub.new(request_body)
9
+ end
10
+
11
+ def satisfies?(request)
12
+ @data["alias_uri"] == request.path_info
13
+ end
14
+
15
+ def the_stub
16
+ @stub
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ module HttpStub
2
+ module Models
3
+
4
+ class Registry
5
+
6
+ def initialize(model_name)
7
+ @model_name = model_name
8
+ @models = []
9
+ end
10
+
11
+ def add(model, request)
12
+ @models.unshift(model)
13
+ request.logger.info "Registered #{@model_name}: #{model}"
14
+ end
15
+
16
+ def find_for(request)
17
+ request.logger.info "Finding #{@model_name} satisfying: #{request.inspect}"
18
+ @models.find { |model| model.satisfies?(request) }
19
+ end
20
+
21
+ def clear(request)
22
+ request.logger.info "Clearing #{@model_name} registry"
23
+ @models.clear
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ module HttpStub
2
+ module Models
3
+
4
+ class Stub
5
+
6
+ attr_reader :response
7
+
8
+ def initialize(request_body)
9
+ @data = JSON.parse(request_body)
10
+ @response = HttpStub::Response.new(status: @data["response"]["status"], body: @data["response"]["body"])
11
+ end
12
+
13
+ def satisfies?(request)
14
+ @data["uri"] == request.path_info &&
15
+ @data["method"].downcase == request.request_method.downcase &&
16
+ parameters_match?(request)
17
+ end
18
+
19
+ def to_s
20
+ @data.to_s
21
+ end
22
+
23
+ private
24
+
25
+ def parameters_match?(request)
26
+ parameters = @data["parameters"]
27
+ parameters.nil? || parameters.reduce(true) do |result, parameter|
28
+ result && (request.params[parameter[0]] == parameter[1])
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module HttpStub
2
+
3
+ class Response < ImmutableStruct.new(:status, :body)
4
+ SUCCESS = HttpStub::Response.new(status: 200, body: "")
5
+ ERROR = HttpStub::Response.new(status: 404, body: "")
6
+ EMPTY = HttpStub::Response.new()
7
+
8
+ def empty?
9
+ self == HttpStub::Response::EMPTY
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -6,7 +6,10 @@ module HttpStub
6
6
 
7
7
  def initialize
8
8
  super()
9
- @registry = HttpStub::Registry.new
9
+ @stub_registry = HttpStub::Models::Registry.new("stub")
10
+ @alias_registry = HttpStub::Models::Registry.new("alias")
11
+ @stub_controller = HttpStub::Controllers::StubController.new(@stub_registry)
12
+ @alias_controller = HttpStub::Controllers::AliasController.new(@alias_registry, @stub_registry)
10
13
  end
11
14
 
12
15
  private
@@ -32,23 +35,35 @@ module HttpStub
32
35
  # "body": "Hello World"
33
36
  # }
34
37
  # }
35
- post "/stub" do
36
- @registry.add(HttpStub::Stub.new(request), request)
37
- halt 200
38
+ post "/stubs" do
39
+ response = @stub_controller.register(request)
40
+ halt(response.status, response.body)
41
+ end
42
+
43
+ # Sample request body:
44
+ # {
45
+ # "alias_uri": "/some/path",
46
+ # ... see /stub ...
47
+ # }
48
+ post "/stubs/aliases" do
49
+ response = @alias_controller.register(request)
50
+ halt(response.status, response.body)
38
51
  end
39
52
 
40
53
  delete "/stubs" do
41
- @registry.clear(request)
54
+ @stub_controller.clear(request)
42
55
  halt 200
43
56
  end
44
57
 
45
- any_request_type(//) { handle_stub_request }
58
+ any_request_type(//) { handle_request }
46
59
 
47
60
  private
48
61
 
49
- def handle_stub_request
50
- stub = @registry.find_for(request)
51
- stub ? halt(stub.response.status, stub.response.body) : halt(404)
62
+ def handle_request
63
+ response = @stub_controller.replay(request)
64
+ response = @alias_controller.activate(request) if response.empty?
65
+ response = HttpStub::Response::ERROR if response.empty?
66
+ halt(response.status, response.body)
52
67
  end
53
68
 
54
69
  end
@@ -1,5 +1,5 @@
1
1
  require File.expand_path('../../http_stub', __FILE__)
2
- require 'rake/tasklib' unless defined?(::Rake::TaskLib)
2
+ require 'rake/tasklib' unless defined? (::Rake::TaskLib)
3
3
 
4
4
  module HttpStub
5
5
 
@@ -1,3 +1,3 @@
1
1
  module HttpStub
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,119 @@
1
+ describe HttpStub::Configurer do
2
+ include_context "server integration"
3
+
4
+ before(:all) do
5
+ class TestConfigurer
6
+ include HttpStub::Configurer
7
+
8
+ host "localhost"
9
+ port 8001
10
+
11
+ stub_alias "/an_alias", "/path1", method: :get, response: { status: 200, body: "Stub alias body" }
12
+ end
13
+ end
14
+
15
+ let(:configurer) { TestConfigurer.new }
16
+
17
+ after(:each) { configurer.clear! }
18
+
19
+ describe "when a stub alias is activated" do
20
+
21
+ before(:each) { Net::HTTP.get_response("localhost", "/an_alias", 8001) }
22
+
23
+ describe "and the stub request is made" do
24
+
25
+ let(:response) { Net::HTTP.get_response("localhost", "/path1", 8001) }
26
+
27
+ it "should replay the stubbed response" do
28
+ response.code.should eql("200")
29
+ response.body.should eql("Stub alias body")
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ describe "when a stub alias is not activated" do
37
+
38
+ describe "and the stub request is made" do
39
+
40
+ let(:response) { Net::HTTP.get_response("localhost", "/path1", 8001) }
41
+
42
+ it "should respond with a 404 status code" do
43
+ response.code.should eql("404")
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ describe "when a response for a request is stubbed" do
51
+
52
+ describe "that contains no parameters" do
53
+
54
+ before(:each) do
55
+ configurer.stub_response!("/path2", method: :get, response: { status: 201, body: "Stub body" })
56
+ end
57
+
58
+ describe "and that request is made" do
59
+
60
+ let(:response) { Net::HTTP.get_response("localhost", "/path2", 8001) }
61
+
62
+ it "should replay the stubbed response" do
63
+ response.code.should eql("201")
64
+ response.body.should eql("Stub body")
65
+ end
66
+
67
+ end
68
+
69
+ describe "and the stub is cleared" do
70
+
71
+ before(:each) { configurer.clear! }
72
+
73
+ describe "and the original request is made" do
74
+
75
+ let(:response) { Net::HTTP.get_response("localhost", "/path2", 8001) }
76
+
77
+ it "should respond with a 404 status code" do
78
+ response.code.should eql("404")
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ describe "that contains parameters" do
88
+
89
+ before(:each) do
90
+ configurer.stub_response!("/path3", method: :get, parameters: { key: "value" },
91
+ response: { status: 202, body: "Another stub body" })
92
+ end
93
+
94
+ describe "and that request is made" do
95
+
96
+ let(:response) { Net::HTTP.get_response("localhost", "/path3?key=value", 8001) }
97
+
98
+ it "should replay the stubbed response" do
99
+ response.code.should eql("202")
100
+ response.body.should eql("Another stub body")
101
+ end
102
+
103
+ end
104
+
105
+ describe "and a request with different parameters is made" do
106
+
107
+ let(:response) { Net::HTTP.get_response("localhost", "/path3?key=another_value", 8001) }
108
+
109
+ it "should respond with a 404 status code" do
110
+ response.code.should eql("404")
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+
119
+ end
@@ -0,0 +1,75 @@
1
+ describe HttpStub::Controllers::AliasController do
2
+
3
+ let(:request_body) { "Some request body" }
4
+ let(:request) { double("HttpRequest", body: double("RequestBody", read: request_body)) }
5
+ let(:the_stub) { double(HttpStub::Models::Stub) }
6
+ let(:stub_alias) { double(HttpStub::Models::Alias, the_stub: the_stub) }
7
+ let(:alias_registry) { double("HttpStub::Models::AliasRegistry").as_null_object }
8
+ let(:stub_registry) { double("HttpStub::Models::StubRegistry").as_null_object }
9
+ let(:controller) { HttpStub::Controllers::AliasController.new(alias_registry, stub_registry) }
10
+
11
+ describe "#register" do
12
+
13
+ before(:each) do
14
+ HttpStub::Models::Alias.stub!(:new).and_return(stub_alias)
15
+ end
16
+
17
+ it "should create an alias from the request body" do
18
+ HttpStub::Models::Alias.should_receive(:new).with(request_body).and_return(stub_alias)
19
+
20
+ controller.register(request)
21
+ end
22
+
23
+ it "should add the created alias to the alias registry" do
24
+ alias_registry.should_receive(:add).with(stub_alias, request)
25
+
26
+ controller.register(request)
27
+ end
28
+
29
+ it "should return a success response" do
30
+ controller.register(request).should eql(HttpStub::Response::SUCCESS)
31
+ end
32
+
33
+ end
34
+
35
+ describe "#activate" do
36
+
37
+ describe "when an alias has been registered that is activated by the request" do
38
+
39
+ before(:each) do
40
+ alias_registry.stub!(:find_for).with(request).and_return(stub_alias)
41
+ end
42
+
43
+ it "should add the aliases stub to the stub registry" do
44
+ stub_registry.should_receive(:add).with(the_stub, request)
45
+
46
+ controller.activate(request)
47
+ end
48
+
49
+ it "should return a success response" do
50
+ controller.activate(request).should eql(HttpStub::Response::SUCCESS)
51
+ end
52
+
53
+ end
54
+
55
+ describe "when no alias is activated by the request" do
56
+
57
+ before(:each) do
58
+ alias_registry.stub!(:find_for).with(request).and_return(nil)
59
+ end
60
+
61
+ it "should not add a stub to the registry" do
62
+ stub_registry.should_not_receive(:add)
63
+
64
+ controller.activate(request)
65
+ end
66
+
67
+ it "should return an empty response" do
68
+ controller.activate(request).should eql(HttpStub::Response::EMPTY)
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end