mirage 2.4.2 → 3.0.0.alpha.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/.simplecov +6 -0
- data/Gemfile +11 -3
- data/Gemfile.lock +41 -14
- data/VERSION +1 -1
- data/features/client/clear.feature +41 -50
- data/features/client/configure.feature +2 -2
- data/features/client/put.feature +17 -6
- data/features/client/requests.feature +5 -9
- data/features/client/start.feature +19 -11
- data/features/client/stop.feature +10 -44
- data/features/server/commandline_interface/start.feature +2 -14
- data/features/server/commandline_interface/stop.feature +6 -4
- data/features/server/logging.feature +2 -2
- data/features/server/prime.feature +11 -66
- data/features/server/requests/delete.feature +34 -33
- data/features/server/requests/get.feature +21 -18
- data/features/server/save_and_revert.feature +24 -11
- data/features/server/templates/delete.feature +29 -32
- data/features/server/templates/get.feature +44 -25
- data/features/server/templates/put/put.feature +55 -78
- data/features/server/templates/put/put_with_substitutions.feature +12 -32
- data/features/server/templates/put/required_content.feature +118 -0
- data/features/step_definitions/my_steps.rb +51 -6
- data/features/support/env.rb +1 -1
- data/features/support/hooks.rb +2 -5
- data/{lib/mirage/client → features/support}/web.rb +14 -3
- data/lib/mirage/client.rb +5 -2
- data/lib/mirage/client/client.rb +22 -129
- data/lib/mirage/client/request.rb +25 -0
- data/lib/mirage/client/requests.rb +13 -0
- data/lib/mirage/client/runner.rb +4 -4
- data/lib/mirage/client/template.rb +108 -0
- data/lib/mirage/client/template_configuration.rb +22 -0
- data/lib/mirage/client/templates.rb +26 -0
- data/mirage.gemspec +42 -22
- data/mirage_server.rb +1 -135
- data/rakefile +22 -7
- data/server/app.rb +4 -0
- data/server/binary_data_checker.rb +15 -0
- data/server/helpers.rb +28 -0
- data/server/mock_response.rb +140 -58
- data/server/server.rb +167 -0
- data/spec/{cli_bridge_spec.rb → client/cli_bridge_spec.rb} +15 -11
- data/spec/client/client_spec.rb +139 -0
- data/spec/client/request_spec.rb +52 -0
- data/spec/client/requests_spec.rb +10 -0
- data/spec/{runner_spec.rb → client/runner_spec.rb} +3 -3
- data/spec/client/template_configuration_spec.rb +32 -0
- data/spec/client/template_spec.rb +241 -0
- data/spec/client/templates_spec.rb +79 -0
- data/spec/resources/binary.file +0 -0
- data/spec/server/binary_data_checker_spec.rb +22 -0
- data/spec/server/helpers_spec.rb +34 -0
- data/spec/server/mock_response_spec.rb +526 -0
- data/spec/server/server_spec.rb +132 -0
- data/spec/spec_helper.rb +61 -2
- data/test.html +12 -0
- data/test.rb +20 -17
- data/todo.lst +2 -0
- data/views/index.haml +22 -0
- data/views/response.haml +24 -0
- metadata +134 -49
- data/features/server/templates/put/put_as_default.feature +0 -42
- data/features/server/templates/put/put_with_delay.feature +0 -8
- data/features/server/templates/put/put_with_pattern.feature +0 -80
- data/lib/mirage/client/response.rb +0 -29
- data/spec/client_spec.rb +0 -38
- data/views/index.erb +0 -28
data/server/server.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'helpers'
|
3
|
+
require 'base64'
|
4
|
+
module Mirage
|
5
|
+
|
6
|
+
class Server < Sinatra::Base
|
7
|
+
|
8
|
+
REQUESTS = {}
|
9
|
+
|
10
|
+
|
11
|
+
helpers Mirage::Server::Helpers
|
12
|
+
|
13
|
+
put '/mirage/templates/*' do |name|
|
14
|
+
content_type :json
|
15
|
+
mock_response = MockResponse.new(name, JSON.parse(request.body.read))
|
16
|
+
mock_response.requests_url = request.url.gsub("/mirage/templates/#{name}", "/mirage/requests/#{mock_response.response_id}")
|
17
|
+
{:id => mock_response.response_id}.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
%w(get post delete put).each do |http_method|
|
21
|
+
send(http_method, '/mirage/responses/*') do |name|
|
22
|
+
body, query_string = Rack::Utils.unescape(request.body.read.to_s), request.query_string
|
23
|
+
|
24
|
+
options = {:body => body,
|
25
|
+
:http_method => http_method,
|
26
|
+
:endpoint => name,
|
27
|
+
:params => request.params,
|
28
|
+
:headers => extract_http_headers(env)}
|
29
|
+
begin
|
30
|
+
record = MockResponse.find(options)
|
31
|
+
rescue ServerResponseNotFound
|
32
|
+
record = MockResponse.find_default(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
REQUESTS[record.response_id] = request.dup
|
36
|
+
|
37
|
+
send_response(record, body, request, query_string)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
delete '/mirage/templates/:id' do
|
42
|
+
MockResponse.delete(response_id)
|
43
|
+
REQUESTS.delete(response_id)
|
44
|
+
200
|
45
|
+
end
|
46
|
+
|
47
|
+
delete '/mirage/requests' do
|
48
|
+
REQUESTS.clear
|
49
|
+
200
|
50
|
+
end
|
51
|
+
|
52
|
+
delete '/mirage/requests/:id' do
|
53
|
+
REQUESTS.delete(response_id)
|
54
|
+
200
|
55
|
+
end
|
56
|
+
|
57
|
+
delete '/mirage/templates' do
|
58
|
+
REQUESTS.clear
|
59
|
+
MockResponse.delete_all
|
60
|
+
200
|
61
|
+
end
|
62
|
+
|
63
|
+
get '/mirage/templates/:id' do
|
64
|
+
MockResponse.find_by_id(response_id).raw
|
65
|
+
end
|
66
|
+
|
67
|
+
get '/mirage/requests/:id' do
|
68
|
+
content_type :json
|
69
|
+
tracked_request = REQUESTS[response_id]
|
70
|
+
if tracked_request
|
71
|
+
|
72
|
+
tracked_request.body.rewind
|
73
|
+
body = tracked_request.body.read
|
74
|
+
|
75
|
+
parameters = tracked_request.params.dup.select{|key, value| key != body}
|
76
|
+
|
77
|
+
{ request_url: request.url,
|
78
|
+
headers: extract_http_headers(tracked_request.env),
|
79
|
+
parameters: parameters,
|
80
|
+
body: body}.to_json
|
81
|
+
|
82
|
+
else
|
83
|
+
404
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
get '/mirage' do
|
88
|
+
haml :index
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
put '/mirage/defaults' do
|
93
|
+
MockResponse.delete_all
|
94
|
+
if File.directory?(settings.defaults.to_s)
|
95
|
+
Dir["#{settings.defaults}/**/*.rb"].each do |default|
|
96
|
+
begin
|
97
|
+
eval File.read(default)
|
98
|
+
rescue Exception => e
|
99
|
+
raise "Unable to load default responses from: #{default}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
200
|
104
|
+
end
|
105
|
+
#
|
106
|
+
put '/mirage/backup' do
|
107
|
+
MockResponse.backup
|
108
|
+
200
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
put '/mirage' do
|
113
|
+
MockResponse.revert
|
114
|
+
200
|
115
|
+
end
|
116
|
+
|
117
|
+
get '/mirage/pid' do
|
118
|
+
"#{$$}"
|
119
|
+
end
|
120
|
+
|
121
|
+
error ServerResponseNotFound do
|
122
|
+
404
|
123
|
+
end
|
124
|
+
|
125
|
+
error do
|
126
|
+
erb request.env['sinatra.error'].message
|
127
|
+
end
|
128
|
+
|
129
|
+
helpers do
|
130
|
+
|
131
|
+
def response_id
|
132
|
+
params[:id].to_i
|
133
|
+
end
|
134
|
+
|
135
|
+
def prime &block
|
136
|
+
block.call Mirage::Client.new "http://localhost:#{settings.port}/mirage"
|
137
|
+
end
|
138
|
+
|
139
|
+
def send_response(response, body='', request={}, query_string='')
|
140
|
+
sleep response.response_spec['delay']
|
141
|
+
content_type(response.response_spec['content_type'])
|
142
|
+
status response.response_spec['status']
|
143
|
+
response.value(body, request, query_string)
|
144
|
+
end
|
145
|
+
|
146
|
+
def extract_http_headers(env)
|
147
|
+
headers = env.reject do |k, v|
|
148
|
+
!(/^HTTP_[A-Z_]+$/ === k) || v.nil?
|
149
|
+
end.map do |k, v|
|
150
|
+
[reconstruct_header_name(k), v]
|
151
|
+
end.inject(Rack::Utils::HeaderHash.new) do |hash, k_v|
|
152
|
+
k, v = k_v
|
153
|
+
hash[k] = v
|
154
|
+
hash
|
155
|
+
end
|
156
|
+
|
157
|
+
x_forwarded_for = (headers["X-Forwarded-For"].to_s.split(/, +/) << env["REMOTE_ADDR"]).join(", ")
|
158
|
+
|
159
|
+
headers.merge!("X-Forwarded-For" => x_forwarded_for)
|
160
|
+
end
|
161
|
+
|
162
|
+
def reconstruct_header_name(name)
|
163
|
+
name.sub(/^HTTP_/, "").gsub("_", "-")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -3,7 +3,11 @@ require 'mirage/client'
|
|
3
3
|
|
4
4
|
describe Mirage::CLIBridge do
|
5
5
|
|
6
|
-
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@bridge = Object.new
|
9
|
+
@bridge.extend(Mirage::CLIBridge)
|
10
|
+
end
|
7
11
|
|
8
12
|
describe 'Windows' do
|
9
13
|
|
@@ -15,8 +19,8 @@ describe Mirage::CLIBridge do
|
|
15
19
|
#{process_string_for_mirage(7002, 18904)}
|
16
20
|
#{process_string_for_mirage(7003, 18905)}"
|
17
21
|
|
18
|
-
|
19
|
-
mirage_process_ids([7001, 7002]).should == {"7001" => "18903", "7002" => "18904"}
|
22
|
+
@bridge.should_receive(:`).with(/tasklist.*/).any_number_of_times.and_return(tasklist_output)
|
23
|
+
@bridge.mirage_process_ids([7001, 7002]).should == {"7001" => "18903", "7002" => "18904"}
|
20
24
|
end
|
21
25
|
|
22
26
|
it 'should find the pids of mirage instances for all ports' do
|
@@ -24,13 +28,13 @@ describe Mirage::CLIBridge do
|
|
24
28
|
#{process_string_for_mirage(7002, 18904)}
|
25
29
|
#{process_string_for_mirage(7003, 18905)}"
|
26
30
|
|
27
|
-
|
28
|
-
mirage_process_ids([:all]).should == {"7001" => "18903", "7002" => "18904", "7003" => "18905"}
|
31
|
+
@bridge.should_receive(:`).with(/tasklist.*/).any_number_of_times.and_return(tasklist_output)
|
32
|
+
@bridge.mirage_process_ids([:all]).should == {"7001" => "18903", "7002" => "18904", "7003" => "18905"}
|
29
33
|
end
|
30
34
|
|
31
35
|
it 'should kill the given process id' do
|
32
|
-
|
33
|
-
kill(18903)
|
36
|
+
@bridge.should_receive(:`).with(/taskkill \/F \/T \/PID 18903/)
|
37
|
+
@bridge.kill(18903)
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
@@ -44,7 +48,7 @@ describe Mirage::CLIBridge do
|
|
44
48
|
#{process_string_for_mirage(7003, 18905)}"
|
45
49
|
|
46
50
|
IO.should_receive(:popen).with(/ps aux.*/).any_number_of_times.and_return(ps_aux_output)
|
47
|
-
mirage_process_ids([7001, 7002]).should == {"7001" => "18903", "7002" => "18904"}
|
51
|
+
@bridge.mirage_process_ids([7001, 7002]).should == {"7001" => "18903", "7002" => "18904"}
|
48
52
|
end
|
49
53
|
|
50
54
|
it 'should find the pids of mirage instances for all ports' do
|
@@ -53,12 +57,12 @@ describe Mirage::CLIBridge do
|
|
53
57
|
#{process_string_for_mirage(7003, 18905)}"
|
54
58
|
|
55
59
|
IO.should_receive(:popen).with(/ps aux.*/).any_number_of_times.and_return(ps_aux_output)
|
56
|
-
mirage_process_ids([:all]).should == {"7001" => "18903", "7002" => "18904", "7003" => "18905"}
|
60
|
+
@bridge.mirage_process_ids([:all]).should == {"7001" => "18903", "7002" => "18904", "7003" => "18905"}
|
57
61
|
end
|
58
62
|
|
59
63
|
it 'should kill the given process id' do
|
60
|
-
|
61
|
-
kill(18903)
|
64
|
+
@bridge.should_receive(:`).with(/kill -9 18903/)
|
65
|
+
@bridge.kill(18903)
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mirage/client'
|
3
|
+
|
4
|
+
describe Mirage::Client do
|
5
|
+
Client = Mirage::Client
|
6
|
+
Templates = Mirage::Templates
|
7
|
+
Template = Mirage::Template
|
8
|
+
Requests = Mirage::Requests
|
9
|
+
Request = Mirage::Request
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
@response = mock('response').as_null_object
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'configuration' do
|
16
|
+
it 'is configured to connect to local host port 7001 by default' do
|
17
|
+
Client.new.url.should == "http://localhost:7001/mirage"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can be configured with a url pointing to Mirage' do
|
21
|
+
mirage_url = "http://url.for.mirage"
|
22
|
+
Client.new(mirage_url).url.should == mirage_url
|
23
|
+
|
24
|
+
Client.new(:url => mirage_url).url.should == mirage_url
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'can be configured with a port refering to which port Mirage is running on on localhost' do
|
28
|
+
port = 9001
|
29
|
+
Client.new(:port => port).url.should == "http://localhost:#{port}/mirage"
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'raises an error if neither a port or url specified in the argument' do
|
33
|
+
expect { Client.new({}) }.to raise_error()
|
34
|
+
expect { Client.new("rubbish") }.to raise_error()
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should clear mirage' do
|
39
|
+
templates_mock = mock('templates')
|
40
|
+
Templates.should_receive(:new).and_return(templates_mock)
|
41
|
+
templates_mock.should_receive(:delete_all)
|
42
|
+
Client.new.clear
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
it 'should prime mirage' do
|
49
|
+
Client.should_receive(:put) do |url|
|
50
|
+
url.should == "http://localhost:7001/mirage/defaults"
|
51
|
+
end
|
52
|
+
Client.new.prime
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'templates' do
|
56
|
+
it 'should give access to templates' do
|
57
|
+
mirage = Client.new
|
58
|
+
mirage.templates.instance_of?(Templates).should == true
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should find a template' do
|
62
|
+
id = 1
|
63
|
+
mirage = Client.new
|
64
|
+
mock_template = mock('template')
|
65
|
+
Template.should_receive(:get).with("#{mirage.url}/templates/#{id}").and_return(mock_template)
|
66
|
+
mirage.templates(1).should == mock_template
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should put a response on mirage' do
|
70
|
+
endpoint, value, block = 'greeting', 'hello', Proc.new{}
|
71
|
+
|
72
|
+
templates_mock = mock('templates')
|
73
|
+
Templates.should_receive(:new).and_return(templates_mock)
|
74
|
+
|
75
|
+
templates_mock.should_receive(:put).with(endpoint, value, &block)
|
76
|
+
|
77
|
+
mirage = Client.new
|
78
|
+
mirage.put endpoint, value, &block
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'requests' do
|
83
|
+
it 'should give access to requests' do
|
84
|
+
mirage = Client.new
|
85
|
+
mirage.requests.instance_of?(Requests).should == true
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should find a request' do
|
89
|
+
id = 1
|
90
|
+
mirage = Client.new
|
91
|
+
Request.should_receive(:get).with("#{mirage.url}/requests/#{id}")
|
92
|
+
mirage.requests(id)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
#describe 'stop' do
|
97
|
+
#
|
98
|
+
#end
|
99
|
+
|
100
|
+
describe 'save' do
|
101
|
+
it 'should save the current template setup of mirage' do
|
102
|
+
mirage = Client.new
|
103
|
+
Client.should_receive(:put).with("#{mirage.url}/backup", :body => "")
|
104
|
+
mirage.save
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'revert' do
|
109
|
+
it 'should revert the current template set' do
|
110
|
+
mirage = Client.new
|
111
|
+
Client.should_receive(:put).with(mirage.url, :body => "")
|
112
|
+
mirage.revert
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
describe 'interface to mirage' do
|
118
|
+
|
119
|
+
after :each do
|
120
|
+
Mirage.stop
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should set a response' do
|
124
|
+
client = Mirage.start
|
125
|
+
response = client.templates.put("greeting", "hello")
|
126
|
+
response.id.should == 1
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should find mirage running' do
|
130
|
+
Mirage.start
|
131
|
+
Mirage.running?.should == true
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'should not find mirage running' do
|
135
|
+
Mirage.running?.should == false
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mirage/client'
|
3
|
+
|
4
|
+
|
5
|
+
describe Mirage::Request do
|
6
|
+
Request = Mirage::Request
|
7
|
+
|
8
|
+
it 'delete a request' do
|
9
|
+
request_url = "url"
|
10
|
+
Request.should_receive(:delete).with(request_url)
|
11
|
+
request = Request.new
|
12
|
+
request.request_url = request_url
|
13
|
+
request.delete
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should load request data' do
|
17
|
+
request_url = "url"
|
18
|
+
trigger_url = "trigger url"
|
19
|
+
|
20
|
+
body = "body"
|
21
|
+
parameters = {"name" => "joe"}
|
22
|
+
headers = {"header" => "value"}
|
23
|
+
|
24
|
+
request_json = {
|
25
|
+
body: body,
|
26
|
+
headers: headers,
|
27
|
+
parameters: parameters,
|
28
|
+
request_url: trigger_url
|
29
|
+
}
|
30
|
+
|
31
|
+
Request.should_receive(:backedup_get).with(request_url,format: :json).and_return(request_json)
|
32
|
+
|
33
|
+
request = Request.get(request_url)
|
34
|
+
request.headers.should == headers
|
35
|
+
request.body.should == body
|
36
|
+
request.request_url.should == trigger_url
|
37
|
+
request.parameters.should == parameters
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should contain parameters' do
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should contain the request body' do
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should contain the triggering url' do
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mirage/client'
|
3
|
+
|
4
|
+
describe 'Requests' do
|
5
|
+
it 'should delete all request data' do
|
6
|
+
base_url = "base_url"
|
7
|
+
Mirage::Requests.should_receive(:delete).with("#{base_url}/requests")
|
8
|
+
Mirage::Requests.new(base_url).delete_all
|
9
|
+
end
|
10
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'mirage/client'
|
3
3
|
|
4
|
-
include Mirage
|
5
4
|
|
6
5
|
describe Mirage do
|
6
|
+
Runner = Mirage::Runner
|
7
7
|
|
8
8
|
describe 'starting' do
|
9
9
|
before(:each) do
|
@@ -72,7 +72,7 @@ describe Mirage do
|
|
72
72
|
runner.should_not_receive(:kill)
|
73
73
|
Mirage::Runner.should_receive(:new).and_return(runner)
|
74
74
|
|
75
|
-
|
75
|
+
expect { runner.invoke(:stop, [], options) }.to raise_error(Mirage::ClientError)
|
76
76
|
end
|
77
77
|
|
78
78
|
|
@@ -131,7 +131,7 @@ describe Mirage do
|
|
131
131
|
runner.should_receive(:mirage_process_ids).with([7001]).any_number_of_times.and_return({})
|
132
132
|
|
133
133
|
Mirage::Runner.should_receive(:new).and_return(runner)
|
134
|
-
|
134
|
+
expect { runner.invoke(:stop, [], options) }.to_not raise_error(Mirage::ClientError)
|
135
135
|
end
|
136
136
|
|
137
137
|
end
|