mirage-on-thin 3.0.8

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.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/.simplecov +6 -0
  5. data/.travis.yml +3 -0
  6. data/Gemfile +29 -0
  7. data/Gemfile.lock +151 -0
  8. data/HISTORY +22 -0
  9. data/README.md +156 -0
  10. data/Rakefile +10 -0
  11. data/VERSION +1 -0
  12. data/bin/mirage +14 -0
  13. data/features/.nav +29 -0
  14. data/features/client/clear.feature +78 -0
  15. data/features/client/configure.feature +72 -0
  16. data/features/client/model.feature +95 -0
  17. data/features/client/preview_responses.feature +33 -0
  18. data/features/client/prime.feature +32 -0
  19. data/features/client/put.feature +111 -0
  20. data/features/client/readme.md +3 -0
  21. data/features/client/requests.feature +20 -0
  22. data/features/client/running.feature +51 -0
  23. data/features/client/save_and_revert.feature +39 -0
  24. data/features/client/start.feature +46 -0
  25. data/features/client/stop.feature +53 -0
  26. data/features/commandline_interface/help.feature +17 -0
  27. data/features/commandline_interface/readme.md +1 -0
  28. data/features/commandline_interface/start.feature +18 -0
  29. data/features/commandline_interface/stop.feature +42 -0
  30. data/features/logging.feature +6 -0
  31. data/features/prime.feature +35 -0
  32. data/features/readme.md +7 -0
  33. data/features/requests/delete.feature +48 -0
  34. data/features/requests/get.feature +36 -0
  35. data/features/save_and_revert.feature +35 -0
  36. data/features/step_definitions/my_steps.rb +98 -0
  37. data/features/step_definitions/observation_steps.rb +103 -0
  38. data/features/support/command_line.rb +33 -0
  39. data/features/support/env.rb +22 -0
  40. data/features/support/hooks.rb +26 -0
  41. data/features/support/mirage.rb +12 -0
  42. data/features/support/web.rb +20 -0
  43. data/features/templates/delete.feature +45 -0
  44. data/features/templates/get.feature +54 -0
  45. data/features/templates/path_wildcards.feature +10 -0
  46. data/features/templates/preview.feature +18 -0
  47. data/features/templates/put.feature +77 -0
  48. data/features/templates/put_with_substitutions.feature +22 -0
  49. data/features/templates/readme.md +4 -0
  50. data/features/templates/required_content.feature +113 -0
  51. data/features/web_user_interface.feature +44 -0
  52. data/full_build.sh +100 -0
  53. data/lib/mirage/client.rb +10 -0
  54. data/lib/mirage/client/cli_bridge.rb +30 -0
  55. data/lib/mirage/client/client.rb +73 -0
  56. data/lib/mirage/client/error.rb +22 -0
  57. data/lib/mirage/client/helpers/method_builder.rb +19 -0
  58. data/lib/mirage/client/request.rb +26 -0
  59. data/lib/mirage/client/requests.rb +13 -0
  60. data/lib/mirage/client/runner.rb +103 -0
  61. data/lib/mirage/client/template.rb +56 -0
  62. data/lib/mirage/client/template/configuration.rb +44 -0
  63. data/lib/mirage/client/template/model.rb +48 -0
  64. data/lib/mirage/client/template/model/common_methods.rb +24 -0
  65. data/lib/mirage/client/template/model/instance_methods.rb +95 -0
  66. data/lib/mirage/client/templates.rb +50 -0
  67. data/mirage-on-thin.gemspec +175 -0
  68. data/mirage_server.rb +35 -0
  69. data/server/app.rb +4 -0
  70. data/server/binary_data_checker.rb +15 -0
  71. data/server/extensions/hash.rb +10 -0
  72. data/server/extensions/object.rb +5 -0
  73. data/server/helpers.rb +3 -0
  74. data/server/helpers/http_headers.rb +31 -0
  75. data/server/helpers/template_requirements.rb +33 -0
  76. data/server/mock_response.rb +242 -0
  77. data/server/server.rb +184 -0
  78. data/spec/client/cli_bridge_spec.rb +63 -0
  79. data/spec/client/client_spec.rb +179 -0
  80. data/spec/client/helpers/method_builder_spec.rb +40 -0
  81. data/spec/client/request_spec.rb +39 -0
  82. data/spec/client/requests_spec.rb +9 -0
  83. data/spec/client/runner_spec.rb +138 -0
  84. data/spec/client/template/configuration_spec.rb +32 -0
  85. data/spec/client/template/model/common_methods_spec.rb +25 -0
  86. data/spec/client/template/model/instance_methods_spec.rb +169 -0
  87. data/spec/client/template/model_spec.rb +119 -0
  88. data/spec/client/template_spec.rb +146 -0
  89. data/spec/client/templates_spec.rb +197 -0
  90. data/spec/resources/binary.file +0 -0
  91. data/spec/server/binary_data_checker_spec.rb +21 -0
  92. data/spec/server/helpers/http_headers_spec.rb +20 -0
  93. data/spec/server/helpers/template_requirements_spec.rb +34 -0
  94. data/spec/server/mock_response_spec.rb +577 -0
  95. data/spec/server/server_spec.rb +156 -0
  96. data/spec/spec_helper.rb +85 -0
  97. data/tasks/application.rake +7 -0
  98. data/tasks/packaging.rake +28 -0
  99. data/tasks/tests.rake +25 -0
  100. data/views/index.haml +16 -0
  101. data/views/response.haml +46 -0
  102. metadata +337 -0
data/server/server.rb ADDED
@@ -0,0 +1,184 @@
1
+ require 'sinatra'
2
+ require 'helpers'
3
+ require 'base64'
4
+ module Mirage
5
+
6
+ class Server < Sinatra::Base
7
+
8
+ REQUESTS = {}
9
+
10
+ helpers Helpers::TemplateRequirements, Helpers::HttpHeaders
11
+
12
+ put '/templates/*' do |name|
13
+ content_type :json
14
+ mock_response = synchronize do
15
+ MockResponse.new(name, JSON.parse(request.body.read))
16
+ end
17
+
18
+ mock_response.requests_url = request.url.gsub("/templates/#{name}", "/requests/#{mock_response.response_id}")
19
+ {:id => mock_response.response_id}.to_json
20
+ end
21
+
22
+ %w(get post delete put).each do |http_method|
23
+ send(http_method, '/responses/*') do |name|
24
+ body, query_string = Rack::Utils.unescape(request.body.read.to_s), request.query_string
25
+
26
+ options = {:body => body,
27
+ :http_method => http_method,
28
+ :endpoint => name,
29
+ :params => request.params,
30
+ :headers => extract_http_headers(env)}
31
+ begin
32
+ record = MockResponse.find(options)
33
+ rescue ServerResponseNotFound
34
+ record = MockResponse.find_default(options)
35
+ end
36
+
37
+ synchronize do
38
+ REQUESTS[record.response_id] = request.dup
39
+ end
40
+
41
+
42
+ send_response(record, body, request, query_string)
43
+ end
44
+ end
45
+
46
+ get '/templates/:id/preview' do
47
+ send_response(MockResponse.find_by_id(response_id), '', {}, '')
48
+ end
49
+
50
+ delete '/templates/:id' do
51
+ synchronize do
52
+ MockResponse.delete(response_id)
53
+ REQUESTS.delete(response_id)
54
+ end
55
+
56
+ 200
57
+ end
58
+
59
+ delete '/requests' do
60
+ synchronize do
61
+ REQUESTS.clear
62
+ end
63
+
64
+ 200
65
+ end
66
+
67
+ delete '/requests/:id' do
68
+ synchronize do
69
+ REQUESTS.delete(response_id)
70
+ end
71
+
72
+ 200
73
+ end
74
+
75
+ delete '/templates' do
76
+ synchronize do
77
+ REQUESTS.clear
78
+ MockResponse.delete_all
79
+ end
80
+
81
+ 200
82
+ end
83
+
84
+ get '/templates/:id' do
85
+ MockResponse.find_by_id(response_id).raw
86
+ end
87
+
88
+ get '/requests/:id' do
89
+ content_type :json
90
+ tracked_request = REQUESTS[response_id]
91
+ if tracked_request
92
+
93
+ tracked_request.body.rewind
94
+ body = tracked_request.body.read
95
+
96
+ parameters = tracked_request.params.dup.select { |key, value| key != body }
97
+
98
+ {id: request.url,
99
+ request_url: tracked_request.url,
100
+ headers: extract_http_headers(tracked_request.env),
101
+ parameters: parameters,
102
+ body: body}.to_json
103
+
104
+ else
105
+ 404
106
+ end
107
+ end
108
+
109
+ get '/' do
110
+ haml :index
111
+ end
112
+
113
+
114
+ put '/defaults' do
115
+ synchronize do
116
+ MockResponse.delete_all
117
+ if File.directory?(settings.defaults.to_s)
118
+ Dir["#{settings.defaults}/**/*.rb"].each do |default|
119
+ begin
120
+ eval File.read(default)
121
+ rescue Exception => e
122
+ raise "Unable to load default responses from: #{default}"
123
+ end
124
+ end
125
+ end
126
+ end
127
+ 200
128
+ end
129
+ #
130
+ put '/backup' do
131
+ synchronize do
132
+ MockResponse.backup
133
+ end
134
+
135
+ 200
136
+ end
137
+
138
+
139
+ put '/' do
140
+ synchronize do
141
+ MockResponse.revert
142
+ end
143
+
144
+ 200
145
+ end
146
+
147
+ get '/pid' do
148
+ "#{$$}"
149
+ end
150
+
151
+ error ServerResponseNotFound do
152
+ 404
153
+ end
154
+
155
+ error do
156
+ erb request.env['sinatra.error'].message
157
+ end
158
+
159
+ helpers do
160
+
161
+ def synchronize &block
162
+ Mutex.new.synchronize &block
163
+ end
164
+
165
+ def response_id
166
+ params[:id].to_i
167
+ end
168
+
169
+ def prime &block
170
+ block.call Mirage::Client.new "http://localhost:#{settings.port}"
171
+ end
172
+
173
+ def send_response(mock_response, body='', request={}, query_string='')
174
+ sleep mock_response.response_spec['delay']
175
+ content_type(mock_response.response_spec['content_type'])
176
+ status mock_response.response_spec['status']
177
+ headers mock_response.headers
178
+ mock_response.value(body, request, query_string)
179
+ end
180
+
181
+
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'mirage/client'
3
+
4
+ describe CLIBridge do
5
+ def mapping port
6
+ {port.to_s => port_pid_mappings[port.to_s]}
7
+ end
8
+
9
+ let(:port_pid_mappings) do
10
+ {"7001" => "18903", "7002" => "18904", "7003" => "18905"}
11
+ end
12
+
13
+ let(:operating_system) do
14
+ Hashie::Mash.new({
15
+ :windows => {
16
+ :kill_string => "taskkill /F /T /PID %d",
17
+ :set_ps_cmd_expectation => proc{bridge.stub(:`).with(/tasklist.*/).and_return(tasklist_output)}
18
+ },
19
+ :linux => {
20
+ :kill_string => "kill -9 %d",
21
+ :set_ps_cmd_expectation => proc{IO.stub(:popen).with(/ps aux.*/).and_return(tasklist_output)}
22
+ }
23
+ })
24
+ end
25
+
26
+ [:linux,:windows].each do |os_name|
27
+
28
+ describe os_name do
29
+ let(:os){operating_system[os_name]}
30
+ let!(:bridge) do
31
+ bridge = Object.new
32
+ bridge.extend(CLIBridge)
33
+ end
34
+
35
+ include_context os_name do
36
+
37
+ let(:tasklist_output) do
38
+ output = []
39
+ port_pid_mappings.each do |port, pid|
40
+ output << process_string_for_mirage(port, pid)
41
+ end
42
+ output.join("\n")
43
+ end
44
+
45
+ it 'should find the pids of mirage instances for given ports' do
46
+ os.set_ps_cmd_expectation.call
47
+ bridge.mirage_process_ids([7001, 7002]).should == mapping(7001).merge(mapping(7002))
48
+ end
49
+
50
+ it 'should find the pids of mirage instances for all ports' do
51
+ os.set_ps_cmd_expectation.call
52
+ bridge.mirage_process_ids([:all]).should == port_pid_mappings
53
+ end
54
+
55
+ it 'should kill the given process id' do
56
+ bridge.should_receive(:`).with(os.kill_string % 18903)
57
+ bridge.kill(18903)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+ require 'mirage/client'
3
+
4
+ describe Mirage::Client do
5
+
6
+
7
+ before :each do
8
+ @response = double('response').as_null_object
9
+ end
10
+
11
+ describe 'configuration' do
12
+ it 'is configured to connect to local host port 7001 by default' do
13
+ Client.new.url.should == "http://localhost:7001"
14
+ end
15
+
16
+ it 'can be configured with a url pointing to Mirage' do
17
+ mirage_url = "http://url.for.mirage"
18
+ Client.new(mirage_url).url.should == mirage_url
19
+
20
+ Client.new(:url => mirage_url).url.should == mirage_url
21
+ end
22
+
23
+ it 'can be configured with a port refering to which port Mirage is running on on localhost' do
24
+ port = 9001
25
+ Client.new(:port => port).url.should == "http://localhost:#{port}"
26
+ end
27
+
28
+ it 'raises an error if neither a port or url specified in the argument' do
29
+ expect { Client.new({}) }.to raise_error()
30
+ expect { Client.new("rubbish") }.to raise_error()
31
+ end
32
+
33
+
34
+ describe 'defaults' do
35
+ it 'can be configured with template defaults on initialize' do
36
+ templates, config = Templates.new("url"), proc {}
37
+ Templates.should_receive(:new).and_return(templates)
38
+ templates.should_receive(:default_config) do |&block|
39
+ block.should == config
40
+ end
41
+ Client.new &config
42
+ end
43
+
44
+ it 'can be configured with template defaults on after initalize' do
45
+ templates, config = Templates.new("url"), proc {}
46
+ Templates.should_receive(:new).and_return(templates)
47
+ templates.should_receive(:default_config) do |&block|
48
+ block.should == config
49
+ end
50
+ Client.new.configure &config
51
+ end
52
+
53
+ it 'can be reset' do
54
+ client = Client.new do
55
+ http_method :post
56
+ end
57
+
58
+ client.reset
59
+ client.templates.default_config.should == Template::Configuration.new
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ it 'should clear mirage' do
66
+ templates_mock = double('templates')
67
+ Templates.should_receive(:new).and_return(templates_mock)
68
+ templates_mock.should_receive(:delete_all)
69
+ Client.new.clear
70
+ end
71
+
72
+
73
+
74
+
75
+ it 'should prime mirage' do
76
+ Client.should_receive(:put) do |url|
77
+ url.should == "http://localhost:7001/defaults"
78
+ end
79
+ Client.new.prime
80
+ end
81
+
82
+ describe 'templates' do
83
+ it 'should give access to templates' do
84
+ mirage = Client.new
85
+ mirage.templates.instance_of?(Templates).should == true
86
+ end
87
+
88
+ it 'The templates instance should be the one created on construction otherwise the defaults passed in will get lost' do
89
+ mirage = Client.new
90
+ mirage.templates.should == mirage.templates
91
+ end
92
+
93
+ it 'should find a template' do
94
+ id = 1
95
+ mirage = Client.new
96
+ mock_template = double('template')
97
+ Template.should_receive(:get).with("#{mirage.url}/templates/#{id}").and_return(mock_template)
98
+ mirage.templates(1).should == mock_template
99
+ end
100
+
101
+
102
+ describe 'put' do
103
+ it "should put a response on mirage by passing args on to template's put method " do
104
+ endpoint, value, block = 'greeting', 'hello', Proc.new{}
105
+
106
+ templates_mock = double('templates')
107
+ Templates.should_receive(:new).and_return(templates_mock)
108
+
109
+ templates_mock.should_receive(:put).with(endpoint, value, &block)
110
+
111
+ mirage = Client.new
112
+ mirage.put endpoint, value, &block
113
+ end
114
+ end
115
+ end
116
+
117
+ describe 'requests' do
118
+ it 'should give access to requests' do
119
+ mirage = Client.new
120
+ mirage.requests.instance_of?(Requests).should == true
121
+ end
122
+
123
+ it 'should find a request' do
124
+ id = 1
125
+ mirage = Client.new
126
+ Request.should_receive(:get).with("#{mirage.url}/requests/#{id}")
127
+ mirage.requests(id)
128
+ end
129
+ end
130
+
131
+ describe 'save' do
132
+ it 'should save the current template setup of mirage' do
133
+ mirage = Client.new
134
+ Client.should_receive(:put).with("#{mirage.url}/backup", :body => "")
135
+ mirage.save
136
+ end
137
+ end
138
+
139
+ describe 'revert' do
140
+ it 'should revert the current template set' do
141
+ mirage = Client.new
142
+ Client.should_receive(:put).with(mirage.url, :body => "")
143
+ mirage.revert
144
+ end
145
+ end
146
+
147
+ describe 'running?' do
148
+ it 'should check if mirage is runing' do
149
+ url = 'http://some_url'
150
+
151
+ Mirage.should_receive(:running?).with url
152
+ Client.new(url).running?
153
+ end
154
+ end
155
+
156
+
157
+ describe 'interface to mirage' do
158
+
159
+ after :each do
160
+ Mirage.stop
161
+ end
162
+
163
+ it 'should set a response' do
164
+ client = Mirage.start
165
+ response = client.templates.put("greeting", "hello")
166
+ response.id.should == 1
167
+ end
168
+
169
+ it 'should find mirage running' do
170
+ Mirage.start
171
+ Mirage.running?.should == true
172
+ end
173
+
174
+ it 'should not find mirage running' do
175
+ Mirage.running?.should == false
176
+ end
177
+
178
+ end
179
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Helpers::MethodBuilder do
4
+
5
+ describe 'a builder method' do
6
+ let :model do
7
+ model_class = Class.new do
8
+ extend Helpers::MethodBuilder
9
+
10
+ builder_method :name
11
+ end
12
+ model_class.new
13
+ end
14
+
15
+ it 'should set a value' do
16
+ model.name(:joe)
17
+ model.name.should == :joe
18
+ end
19
+
20
+ it 'should chain' do
21
+ model.name(:joe).should == model
22
+ end
23
+
24
+ it 'should work with booleans' do
25
+ model.name(false)
26
+ model.name.should == false
27
+ end
28
+ end
29
+
30
+
31
+ it 'should let you define more than one builder method at a time' do
32
+ model_class = Class.new do
33
+ extend Helpers::MethodBuilder
34
+ builder_methods :foo, :bar
35
+ end
36
+ model = model_class.new
37
+ model.respond_to?(:foo).should be_true
38
+ model.respond_to?(:bar).should be_true
39
+ end
40
+ end