mirage-on-thin 3.0.8

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+ require 'mirage/client'
3
+
4
+
5
+ describe Mirage::Template do
6
+
7
+ describe 'get' do
8
+ it 'should load a template given its id' do
9
+ endpoint = "endpoint"
10
+ id = 1
11
+ requests_url = 'request_url'
12
+ body = "Hello"
13
+ default = true
14
+ delay = 1.2
15
+ content_type = "application/json"
16
+ status = 201
17
+ headers = {'header' => 'value'}
18
+
19
+
20
+ required_parameters = {"name" => 'joe'}
21
+ required_body_content = %{content}
22
+ required_headers = {"header" => 'value'}
23
+ http_method = "get"
24
+
25
+ template_json = {
26
+ endpoint: endpoint,
27
+ id: id,
28
+ requests_url: requests_url,
29
+ response:{
30
+ default: default,
31
+ body: Base64.encode64(body),
32
+ delay: delay,
33
+ content_type: content_type,
34
+ status: status,
35
+ headers: headers
36
+ },
37
+ request: {
38
+ parameters: required_parameters,
39
+ body_content: required_body_content,
40
+ headers: required_headers,
41
+ http_method: http_method
42
+ }
43
+ }
44
+ template_json.should_receive(:code).and_return 200
45
+
46
+ template_url = "url"
47
+ Template.should_receive(:backedup_get).with(template_url, :format => :json).and_return(template_json)
48
+
49
+ template = Template.get(template_url)
50
+ template.body.should == body
51
+ template.endpoint.should == endpoint
52
+ template.id.should == id
53
+
54
+ template.default.should == default
55
+ template.delay.should == delay
56
+ template.content_type.should == content_type
57
+ template.status.should == status
58
+ template.headers.should == headers
59
+
60
+ template.required_parameters.should == required_parameters
61
+ template.required_body_content.should == required_body_content
62
+ template.required_headers.should == required_headers
63
+ template.http_method.should == http_method
64
+ template.url.should == template_url
65
+ template.requests_url.should == requests_url
66
+ end
67
+
68
+ it 'should raise an error if the template is not found' do
69
+ template_url = 'url'
70
+ response = double(code: 404)
71
+ Template.should_receive(:backedup_get).with(template_url, :format => :json).and_return response
72
+ expect{Template.get(template_url)}.to raise_error Mirage::TemplateNotFound
73
+ end
74
+ end
75
+
76
+ describe 'initialize' do
77
+ it 'throws and exception if an endpoint is not supplied as the first parameter' do
78
+ expect{Template.new}.to raise_error(ArgumentError)
79
+ end
80
+
81
+ it 'throws and exception if first argument is not a string' do
82
+ expect{Template.new(:endpoint)}.to raise_error(ArgumentError)
83
+ end
84
+ end
85
+
86
+
87
+ describe 'creating' do
88
+ json = "reponse json"
89
+ endpoint = "greeting"
90
+
91
+ it 'should create a template on mirage' do
92
+ template = Template.new(endpoint,json)
93
+
94
+ template.should_receive(:to_json).and_return(json)
95
+ Template.should_receive(:put).with(endpoint, :body => json, :headers => {'content-type' => 'application/json'}).and_return(convert_keys_to_strings({:id => 1}))
96
+ template.create
97
+ template.id.should == 1
98
+ end
99
+
100
+ it 'should have default values set' do
101
+ template = Template.new(endpoint,json)
102
+ template.http_method.should == :get
103
+ template.status.should == 200
104
+ template.content_type.should == "text/plain"
105
+ template.default.should == false
106
+ template.delay.should == 0
107
+ end
108
+ end
109
+
110
+
111
+ describe 'deleting' do
112
+
113
+ it 'should clear a response' do
114
+ id = 1
115
+ template_url = "base_url/templates/#{id}"
116
+ request_url = "base_url/requests/#{id}"
117
+
118
+ template = Template.new("", "")
119
+ template.url template_url
120
+ template.requests_url request_url
121
+
122
+
123
+ template.stub(:id).and_return(id)
124
+
125
+ Template.should_receive(:delete).with(template_url)
126
+
127
+ Mirage::Request.should_receive(:delete).with(request_url)
128
+ template.delete
129
+ end
130
+
131
+ end
132
+
133
+ describe 'method missing' do
134
+ it 'should delagate to the caller if it is set' do
135
+ caller = Object.new
136
+ caller.should_receive(:some_method)
137
+ template = Template.new('endpoint')
138
+ template.caller_binding = caller
139
+ template.some_method
140
+ end
141
+
142
+ it 'should throw a standard method missing error if a caller binding is not set' do
143
+ expect{Template.new('endpoint').some_method}.to raise_error(NameError)
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,197 @@
1
+ require 'spec_helper'
2
+ require 'mirage/client'
3
+
4
+ describe 'templates' do
5
+
6
+
7
+ describe 'deleting' do
8
+ it 'should delete all templates and associated request data' do
9
+ base_url = "base_url"
10
+ requests = double('requests')
11
+ Requests.should_receive(:new).with(base_url).and_return(requests)
12
+
13
+ Templates.should_receive(:delete).with("#{base_url}/templates")
14
+ requests.should_receive(:delete_all)
15
+
16
+ Templates.new(base_url).delete_all
17
+ end
18
+ end
19
+
20
+ describe 'setting default config' do
21
+
22
+ it 'should preset configuration for templates' do
23
+ Template.stub(:put).and_return(convert_keys_to_strings({:id => 1}))
24
+ templates = Templates.new "base_url"
25
+
26
+ http_method = :post
27
+ status = 202
28
+ default = true
29
+ delay = 2
30
+ content_type = "text/xml"
31
+
32
+ templates.default_config do
33
+ http_method http_method
34
+ status status
35
+ default default
36
+ delay delay
37
+ content_type content_type
38
+ end
39
+
40
+ template = templates.put('greeting', 'hello')
41
+
42
+ template.http_method.should == http_method
43
+ template.status.should == status
44
+ template.default.should == default
45
+ template.delay.should == delay
46
+ template.content_type.should == content_type
47
+ end
48
+
49
+ it 'should fall over to methods on the caller if the method does not exist on the configuration object' do
50
+ templates_wrapper = Class.new do
51
+ def initialize
52
+ @templates = Templates.new "base_url"
53
+ @outer_method_called = false
54
+ end
55
+
56
+ def outer_method_call
57
+ @outer_method_called = true
58
+ end
59
+
60
+
61
+ def outer_method_called?
62
+ @outer_method_called
63
+ end
64
+
65
+ def test
66
+ @templates.default_config do
67
+ outer_method_call
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ wrapper = templates_wrapper.new
74
+
75
+ wrapper.test
76
+ wrapper.outer_method_called?.should == true
77
+
78
+ end
79
+ end
80
+
81
+ describe 'putting templates' do
82
+
83
+
84
+ endpoint = "greeting"
85
+ value = "hello"
86
+ let(:base_url) { "base_url" }
87
+ let!(:templates) { Templates.new(base_url) }
88
+ let!(:model_class) do
89
+ Class.new do
90
+ extend Template::Model
91
+ endpoint endpoint
92
+
93
+ def create
94
+ self
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ context 'model as parameter' do
101
+ let!(:endpoint) { 'endpoint' }
102
+
103
+ before :each do
104
+ @base_url = "base_url"
105
+ @templates = Templates.new(@base_url)
106
+ end
107
+ it 'should take a model as a parameter' do
108
+ template = model_class.new
109
+ template = @templates.put template
110
+ template.endpoint.should == "#{@base_url}/templates/#{endpoint}"
111
+ end
112
+
113
+ it 'should prepend base url to the endpoint unless it is set already' do
114
+ original_template = model_class.new
115
+ stored_template = @templates.put original_template
116
+ stored_template.endpoint.should == "#{@base_url}/templates/#{endpoint}"
117
+ stored_template = @templates.put original_template
118
+ stored_template.endpoint.should == "#{@base_url}/templates/#{endpoint}"
119
+ end
120
+
121
+ it 'should fall over to methods on the caller if the method does not exist on the template object' do
122
+ template_wrapper = Class.new do
123
+ def initialize
124
+ @templates = Templates.new "base_url"
125
+ @outer_method_called = false
126
+ end
127
+
128
+ def outer_method_call
129
+ @outer_method_called = true
130
+ end
131
+
132
+ def outer_method_called?
133
+ @outer_method_called
134
+ end
135
+
136
+ def test
137
+ template = Template.new 'endpoint'
138
+ Template.should_receive(:new).and_return template
139
+ template.stub(:create).and_return(template)
140
+ @templates.put('endpoint', 'value') do |response|
141
+ outer_method_call
142
+ end
143
+ end
144
+ end
145
+
146
+ wrapper = template_wrapper.new
147
+
148
+ template = wrapper.test
149
+ wrapper.outer_method_called?.should == true
150
+ template.caller_binding.should == nil
151
+
152
+ end
153
+
154
+
155
+ end
156
+
157
+ context 'endpoint and value as parameters' do
158
+ before :each do
159
+ @base_url = "base_url"
160
+ @templates = Templates.new(@base_url)
161
+
162
+ @template_mock = double('template')
163
+ Template.should_receive(:new).with("#{@base_url}/templates/#{endpoint}", value, @templates.default_config).and_return(@template_mock)
164
+ @template_mock.should_receive(:create)
165
+ end
166
+
167
+ it 'should create a template' do
168
+ @templates.put(endpoint, value)
169
+ end
170
+ end
171
+
172
+ context 'endpoint and model as parameters' do
173
+ it 'should put the given template on the given endpoint' do
174
+ @base_url = "base_url"
175
+ @templates = Templates.new(@base_url)
176
+
177
+ template = model_class.new
178
+ template = @templates.put 'greeting', template
179
+ template.endpoint.should == "#{@base_url}/templates/greeting"
180
+ end
181
+ end
182
+
183
+ describe 'block parameter that can be used for template customisation' do
184
+ it 'it is called in the context of the template' do
185
+ template = Template.new('', '')
186
+ template.stub(:create)
187
+ Template.should_receive(:new).and_return(template)
188
+ templates.put(endpoint, value) do
189
+ status 404
190
+ end
191
+ template.status.should == 404
192
+ end
193
+
194
+ end
195
+
196
+ end
197
+ end
Binary file
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'binary_data_checker'
3
+
4
+
5
+ describe Mirage::BinaryDataChecker do
6
+ include_context :resources
7
+ it 'should find binary data' do
8
+ BinaryDataChecker.contains_binary_data?(File.read("#{resources_dir}/binary.file")).should == true
9
+ end
10
+
11
+ it 'should not find binary data' do
12
+ BinaryDataChecker.contains_binary_data?("string").should == false
13
+ end
14
+
15
+ it 'should clean up the temporary file created when checking string content' do
16
+ tmpfile = Tempfile.new("file")
17
+ Tempfile.should_receive(:new).and_return tmpfile
18
+ FileUtils.should_receive(:rm).with(tmpfile.path)
19
+ BinaryDataChecker.contains_binary_data?("string")
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'helpers/http_headers'
3
+ describe Mirage::Server::Helpers::HttpHeaders do
4
+ describe '#extract_http_headers' do
5
+ it 'returns content-type' do
6
+ helpers = Object.new
7
+ helpers.extend(described_class)
8
+ expected = {'CONTENT_TYPE' => 'application/json'}
9
+ expect(helpers.extract_http_headers(expected)['Content-Type']).to eq('application/json')
10
+ end
11
+
12
+ it 'returns content-length' do
13
+ helpers = Object.new
14
+ helpers.extend(described_class)
15
+ expected = {'CONTENT_LENGTH' => '10'}
16
+ expect(helpers.extract_http_headers(expected)['Content-Length']).to eq('10')
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+ require 'sinatra'
3
+ require 'helpers/template_requirements'
4
+
5
+
6
+ describe "helpers" do
7
+ include_context :resources
8
+
9
+ before :each do
10
+ @helper = Object.new
11
+ @helper.extend(Mirage::Server::Helpers::TemplateRequirements)
12
+ end
13
+
14
+ describe 'converting raw parameter requirements' do
15
+ it 'should split on split on the (:) to derive the required parameter and value' do
16
+ @helper.convert_raw_required_params(%w(name:leon)).should == {'name' => 'leon'}
17
+ end
18
+
19
+ it 'should store regular expression matcher' do
20
+ @helper.convert_raw_required_params(%w(name:%r{.*eon})).should == {'name' => /.*eon/}
21
+ end
22
+ end
23
+
24
+ describe 'converting raw body content requirements' do
25
+ it 'should extract plan text requirements' do
26
+ @helper.convert_raw_required_body_content_requirements(%w(leon)).should == %w(leon)
27
+ end
28
+
29
+ it 'should extract plan requirements in the form of a regexp' do
30
+ @helper.convert_raw_required_body_content_requirements(%w(%r{.*eon})).should == [/.*eon/]
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,577 @@
1
+ require 'spec_helper'
2
+ require 'extensions/object'
3
+ require 'extensions/hash'
4
+ require 'mock_response'
5
+
6
+ describe Mirage::MockResponse do
7
+
8
+ before :each do
9
+ MockResponse.delete_all
10
+ end
11
+
12
+ describe 'initialisation' do
13
+ it 'should find binary data' do
14
+ string="string"
15
+ response_spec = convert_keys_to_strings({:response => {:body => string}})
16
+ BinaryDataChecker.should_receive(:contains_binary_data?).with(string).and_return(true)
17
+ MockResponse.new("greeting", response_spec).binary?.should == true
18
+ end
19
+
20
+ it 'should not find binary data' do
21
+ string="string"
22
+ response_spec = convert_keys_to_strings({:response => {:body => string}})
23
+ BinaryDataChecker.should_receive(:contains_binary_data?).with(string).and_return(false)
24
+ MockResponse.new("greeting", response_spec).binary?.should == false
25
+ end
26
+ end
27
+
28
+ describe 'defaults' do
29
+ describe 'request' do
30
+ it 'should default http_method' do
31
+ MockResponse.new("greeting", {}).request_spec['http_method'].should == "get"
32
+ end
33
+ end
34
+
35
+ describe 'response' do
36
+
37
+ it 'should default content_type' do
38
+ MockResponse.new("greeting", {}).response_spec['content_type'].should == "text/plain"
39
+ end
40
+
41
+ it 'should default status code' do
42
+ MockResponse.new("greeting", {}).response_spec['status'].should == 200
43
+ end
44
+ it 'should default delay' do
45
+ MockResponse.new("greeting", {}).response_spec['delay'].should == 0
46
+ end
47
+
48
+ it 'should default default' do
49
+ MockResponse.new("greeting", {}).response_spec['default'].should == false
50
+ end
51
+ end
52
+ end
53
+
54
+ describe 'saving state' do
55
+ it 'should store the current set of responses' do
56
+ greeting = MockResponse.new("greeting")
57
+ farewell = MockResponse.new("farewell")
58
+
59
+ MockResponse.backup
60
+ MockResponse.new("farewell", "cheerio")
61
+ MockResponse.revert
62
+
63
+ MockResponse.all.should == [greeting, farewell]
64
+ end
65
+ end
66
+
67
+ describe "response values" do
68
+
69
+ it 'should return any headers set' do
70
+ headers = {
71
+ 'header' => 'value'
72
+ }
73
+ response_spec = convert_keys_to_strings({:response => {:headers => headers}})
74
+ MockResponse.new("greeting", response_spec).headers.should == headers
75
+ end
76
+
77
+ it 'should return the response value' do
78
+ response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello")}})
79
+ MockResponse.new("greeting", response_spec).value.should == "hello"
80
+ end
81
+
82
+ it 'should return if the value contains binary data' do
83
+ response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello ${name}")}})
84
+ BinaryDataChecker.should_receive(:contains_binary_data?).and_return(true)
85
+ response = MockResponse.new("greeting", response_spec)
86
+
87
+ response.value("", {"name" => "leon"}).should == "hello ${name}"
88
+ end
89
+
90
+ it 'should replace patterns with values found in request parameters' do
91
+ response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello ${name}")}})
92
+ MockResponse.new("greeting", response_spec).value("", {"name" => "leon"}).should == "hello leon"
93
+ end
94
+
95
+ it 'should base64 decode values' do
96
+ response_spec = convert_keys_to_strings({:response => {:body => "encoded value"}})
97
+ Base64.should_receive(:decode64).and_return("decoded value")
98
+ MockResponse.new("greeting", response_spec).value("")
99
+ end
100
+
101
+ it 'should replace patterns with values found in the body' do
102
+ response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello ${name>(.*?)<}")}})
103
+ MockResponse.new("greeting", response_spec).value("<name>leon</name>").should == "hello leon"
104
+ end
105
+ end
106
+
107
+ describe "Matching http method" do
108
+ it 'should find the response with the correct http method' do
109
+ response_spec = convert_keys_to_strings({:request => {:http_method => "post"}})
110
+ response = MockResponse.new("greeting", response_spec)
111
+
112
+ options = {:body => "", :params => {}, :endpoint => "greeting", :http_method => "post", :headers => {}}
113
+ MockResponse.find(options).should == response
114
+ options[:http_method] = "get"
115
+ expect { MockResponse.find(options) }.to raise_error(ServerResponseNotFound)
116
+ end
117
+ end
118
+
119
+ describe 'Finding by id' do
120
+ it 'should find a response given its id' do
121
+ response1 = MockResponse.new("greeting", "hello")
122
+ MockResponse.new("farewell", "goodbye")
123
+ MockResponse.find_by_id(response1.response_id).should == response1
124
+ end
125
+ end
126
+
127
+ describe 'deleting' do
128
+
129
+ it 'should delete a response given its id' do
130
+ response1 = MockResponse.new("greeting", "hello")
131
+ MockResponse.delete(response1.response_id)
132
+ expect { MockResponse.find_by_id(response1.response_id) }.to raise_error(ServerResponseNotFound)
133
+ end
134
+
135
+ it 'should delete all responses' do
136
+ MockResponse.new("greeting", "hello")
137
+ MockResponse.new("farewell", "goodbye")
138
+ MockResponse.delete_all
139
+ MockResponse.all.size.should == 0
140
+ end
141
+
142
+ end
143
+
144
+ describe 'matching' do
145
+ it 'should convert requirements in to strings before matching' do
146
+ requirement = 1234
147
+ spec = convert_keys_to_strings(
148
+ {
149
+ :request => {
150
+ :parameters => {:number => requirement},
151
+ :body_content => [requirement],
152
+ :headers => {:number => requirement}
153
+ },
154
+ :response => {
155
+ :body => 'response'
156
+ }
157
+
158
+ }
159
+ )
160
+
161
+ MockResponse.new("greeting", spec)
162
+ options = {:headers => {'number' => '1234'},
163
+ :params => {'number' => "1234"},
164
+ :endpoint => "greeting",
165
+ :http_method => "get",
166
+ :body => "1234", }
167
+
168
+ expect { MockResponse.find(options) }.to_not raise_error
169
+ end
170
+
171
+ describe "matching on request parameters" do
172
+ it 'should find the response if all required parameters are present' do
173
+ get_spec = convert_keys_to_strings(
174
+ {
175
+ :request => {
176
+ :http_method => "get",
177
+ :parameters => {
178
+ :firstname => "leon"
179
+ }
180
+ },
181
+ :response => {
182
+ :body => Base64.encode64("get response")
183
+ }
184
+ }
185
+ )
186
+
187
+ post_spec = convert_keys_to_strings(
188
+ {
189
+ :request => {
190
+ :http_method => "post",
191
+ :parameters => {
192
+ :firstname => "leon"
193
+ }
194
+ },
195
+ :response => {
196
+ :body => Base64.encode64("post response")
197
+ }
198
+ }
199
+ )
200
+ get_response = MockResponse.new("greeting", get_spec)
201
+ post_response = MockResponse.new("greeting", post_spec)
202
+
203
+ options = {:body => "", :params => {"firstname" => "leon"}, :endpoint => "greeting", :http_method => "post", :headers => {}}
204
+
205
+ MockResponse.find(options).should == post_response
206
+ MockResponse.find(options.merge(:http_method => "get")).should == get_response
207
+ end
208
+
209
+ it 'should match request parameter values using regexps' do
210
+ response_spec = convert_keys_to_strings(
211
+ {
212
+ :request => {
213
+ :parameters => {:firstname => "%r{leon.*}"}
214
+ },
215
+ :response => {
216
+ :body => 'response'
217
+ }
218
+
219
+ }
220
+ )
221
+ response = MockResponse.new("greeting", response_spec)
222
+
223
+ options = {:body => "", :params => {"firstname" => "leon"}, :endpoint => "greeting", :http_method => "get", :headers => {}}
224
+ MockResponse.find(options).should == response
225
+ MockResponse.find(options.merge(:params => {"firstname" => "leonard"})).should == response
226
+ expect { MockResponse.find(options.merge(:params => {"firstname" => "leo"})) }.to raise_error(ServerResponseNotFound)
227
+ end
228
+ end
229
+
230
+ describe 'matching request uri' do
231
+ it 'should match using wild cards' do
232
+ response_spec = convert_keys_to_strings(
233
+ {
234
+ :response => {
235
+ :body => 'response'
236
+ }
237
+
238
+ }
239
+ )
240
+ response = MockResponse.new('greeting/*/ashley/*', response_spec)
241
+ MockResponse.find(:params => {}, :headers => {}, :http_method => "get", endpoint: 'greeting/leon/ashley/davis').should == response
242
+ end
243
+ end
244
+
245
+ describe 'matching against request http_headers' do
246
+ it 'should match using literals' do
247
+ required_headers = {
248
+ 'HEADER-1' => 'value1',
249
+ 'HEADER-2' => 'value2'
250
+ }
251
+ spec = convert_keys_to_strings(
252
+ {
253
+ :request => {
254
+ :headers => required_headers
255
+ },
256
+ :response => {
257
+ :body => 'response'
258
+ }
259
+
260
+ }
261
+ )
262
+ response = MockResponse.new("greeting", spec)
263
+
264
+ options = {:body => "<name>leon</name>", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => required_headers}
265
+ MockResponse.find(options).should == response
266
+ expect { MockResponse.find(options.merge(:headers => {})) }.to raise_error(ServerResponseNotFound)
267
+
268
+ end
269
+
270
+ it 'should match using regex' do
271
+ required_headers = {
272
+ 'CONTENT-TYPE' => '%r{.*/json}',
273
+ }
274
+ spec = convert_keys_to_strings(
275
+ {
276
+ :request => {
277
+ :headers => required_headers
278
+ },
279
+ :response => {
280
+ :body => 'response'
281
+ }
282
+
283
+ }
284
+ )
285
+ response = MockResponse.new("greeting", spec)
286
+
287
+ options = {:body => "<name>leon</name>", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => {'CONTENT-TYPE' => 'application/json'}}
288
+ MockResponse.find(options).should == response
289
+ expect { MockResponse.find(options.merge(:headers => {'CONTENT-TYPE' => 'text/xml'})) }.to raise_error(ServerResponseNotFound)
290
+
291
+ end
292
+ end
293
+
294
+ describe 'matching against the request body' do
295
+ it 'should match required fragments in the request body' do
296
+
297
+ response_spec = convert_keys_to_strings(
298
+ {
299
+ :request => {
300
+ :body_content => %w(leon)
301
+ },
302
+ :response => {
303
+ :body => 'response'
304
+ }
305
+
306
+ }
307
+ )
308
+
309
+ response = MockResponse.new("greeting", response_spec)
310
+
311
+ options = {:body => "<name>leon</name>", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => {}}
312
+
313
+ MockResponse.find(options).should == response
314
+ expect { MockResponse.find(options.merge(:body => "<name>jeff</name>")) }.to raise_error(ServerResponseNotFound)
315
+ end
316
+
317
+ it 'should use regexs to match required fragements in the request body' do
318
+ response_spec = convert_keys_to_strings(
319
+ {
320
+ :request => {
321
+ :body_content => %w(%r{leon.*})
322
+ },
323
+ :response => {
324
+ :body => 'response'
325
+ }
326
+
327
+ }
328
+ )
329
+
330
+ response = MockResponse.new("greeting", response_spec)
331
+
332
+
333
+ options = {:body => "<name>leon</name>", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => {}}
334
+ MockResponse.find(options).should == response
335
+ MockResponse.find(options.merge(:body => "<name>leonard</name>")).should == response
336
+ expect { MockResponse.find(options.merge(:body => "<name>jeff</name>")) }.to raise_error(ServerResponseNotFound)
337
+ end
338
+ end
339
+ end
340
+
341
+ it 'should be equal to another response that is the same not including the response value' do
342
+
343
+ spec = convert_keys_to_strings({:response => {:body => "hello1",
344
+ :content_type => "text/xml",
345
+ :status => 202,
346
+ :delay => 1.0,
347
+ :default => true,
348
+ :file => false}
349
+
350
+ })
351
+
352
+ response = MockResponse.new("greeting", spec)
353
+ response.should_not == MockResponse.new("greeting", {})
354
+ response.should == MockResponse.new("greeting", spec)
355
+ end
356
+
357
+ describe "scoring to represent the specificity of a response" do
358
+
359
+ it 'should score an exact requirement match at 2' do
360
+ response_spec = convert_keys_to_strings(
361
+ {
362
+ :request => {
363
+ :parameters => {:firstname => "leon"}
364
+ },
365
+ :response => {
366
+ :body => 'response'
367
+ }
368
+
369
+ }
370
+ )
371
+ MockResponse.new("greeting", response_spec).score.should == 2
372
+
373
+ response_spec = convert_keys_to_strings(
374
+ {
375
+ :request => {
376
+ :body_content => %w(login)
377
+ },
378
+ :response => {
379
+ :body => 'response'
380
+ }
381
+
382
+ }
383
+ )
384
+ MockResponse.new("greeting", response_spec).score.should == 2
385
+
386
+ response_spec = convert_keys_to_strings(
387
+ {
388
+ :request => {
389
+ :headers => {'header' => 'header'}
390
+ },
391
+ :response => {
392
+ :body => 'response'
393
+ }
394
+
395
+ }
396
+ )
397
+ MockResponse.new("greeting", response_spec).score.should == 2
398
+ end
399
+
400
+ it 'should score a match found by regexp at 1' do
401
+
402
+ response_spec = convert_keys_to_strings(
403
+ {
404
+ :request => {
405
+ :parameters => {:firstname => "%r{leon.*}"}
406
+ },
407
+ :response => {
408
+ :body => 'response'
409
+ }
410
+
411
+ }
412
+ )
413
+ MockResponse.new("greeting", response_spec).score.should == 1
414
+
415
+ response_spec = convert_keys_to_strings(
416
+ {
417
+ :request => {
418
+ :body_content => %w(%r{input|output})
419
+ },
420
+ :response => {
421
+ :body => 'response'
422
+ }
423
+
424
+ }
425
+ )
426
+ MockResponse.new("greeting", response_spec).score.should == 1
427
+
428
+ response_spec = convert_keys_to_strings(
429
+ {
430
+ :request => {
431
+ :headers => {'header' => '%r{.*blah}'}
432
+ },
433
+ :response => {
434
+ :body => 'response'
435
+ }
436
+
437
+ }
438
+ )
439
+ MockResponse.new("greeting", response_spec).score.should == 1
440
+ end
441
+
442
+ it 'should find the most specific response' do
443
+ default_response_spec = convert_keys_to_strings(
444
+ {
445
+ :request => {
446
+ :body_content => %w(login)
447
+ },
448
+ :response => {
449
+ :body => 'default_response'
450
+ }
451
+
452
+ }
453
+ )
454
+
455
+ specific_response_spec = convert_keys_to_strings(
456
+ {
457
+ :request => {
458
+ :body_content => %w(login),
459
+ :parameters => {
460
+ :name => "leon"
461
+ }
462
+ },
463
+ :response => {
464
+ :body => 'specific response'
465
+ }
466
+
467
+ }
468
+ )
469
+
470
+ MockResponse.new("greeting", default_response_spec)
471
+ expected_response = MockResponse.new("greeting", specific_response_spec)
472
+ options = {:body => "<action>login</action>", :params => {"name" => "leon"}, :endpoint => "greeting", :http_method => "get", :headers => {}}
473
+ MockResponse.find(options).should == expected_response
474
+ end
475
+ end
476
+
477
+
478
+ it 'should all matching to be based on body content, request parameters and http method' do
479
+ response_spec = convert_keys_to_strings({
480
+ :request => {
481
+ :body_content => %w(login),
482
+ :parameters => {
483
+ :name => "leon"
484
+ },
485
+ :http_method => "post"
486
+ },
487
+ :response => {
488
+ :body => "response"
489
+ }
490
+ })
491
+
492
+
493
+ response = MockResponse.new("greeting", response_spec)
494
+ options = {:body => "<action>login</action>", :params => {"name" => "leon"}, :endpoint => "greeting", :http_method => "post", :headers => {}}
495
+ MockResponse.find(options).should == response
496
+
497
+ options[:http_method] = 'get'
498
+ expect { MockResponse.find(options) }.to raise_error(ServerResponseNotFound)
499
+ end
500
+
501
+ it 'should recycle response ids' do
502
+ response_spec = convert_keys_to_strings({
503
+ :request => {
504
+ :body_content => %w(login),
505
+ :parameters => {
506
+ :name => "leon"
507
+ },
508
+ :http_method => "post"
509
+ },
510
+ :response => {
511
+ :body => "response"
512
+ }
513
+ })
514
+ response1 = MockResponse.new("greeting", response_spec)
515
+ response_spec['response']['body'] = 'response2'
516
+ response2 = MockResponse.new("greeting", response_spec)
517
+
518
+ response1.response_id.should_not == nil
519
+ response1.response_id.should == response2.response_id
520
+ end
521
+
522
+ it 'should raise an exception when a response is not found' do
523
+ expect { MockResponse.find(:body => "<action>login</action>", :params => {:name => "leon"}, :endpoint => "greeting", :http_method => "post", :headers => {}) }.to raise_error(ServerResponseNotFound)
524
+ end
525
+
526
+ it 'should return all responses' do
527
+ MockResponse.new("greeting", convert_keys_to_strings({:response => {:body => "hello"}}))
528
+ MockResponse.new("greeting", convert_keys_to_strings({:request => {:body_content => %w(leon)}, :response => {:body => "hello leon"}}))
529
+ MockResponse.new("greeting", convert_keys_to_strings({:request => {:body_content => %w(leon), :http_method => "post"}, :response => {:body => "hello leon"}}))
530
+ MockResponse.new("deposit", convert_keys_to_strings({:request => {:body_content => %w(amount), :http_method => "post"}, :response => {:body => "received"}}))
531
+ MockResponse.all.size.should == 4
532
+ end
533
+
534
+ describe 'finding defaults' do
535
+ it 'most appropriate response under parent resource and same http method' do
536
+ level1_response = MockResponse.new("level1", convert_keys_to_strings({:response => {:body => "level1", :default => true}}))
537
+ MockResponse.new("level1/level2", convert_keys_to_strings({:response => {:body => "level2", :default => true}, :request => {:body_content => %w(body)}}))
538
+ MockResponse.find_default(:body => "", :http_method => "get", :endpoint => "level1/level2/level3", :params => {}, :headers => {}).should == level1_response
539
+ end
540
+ end
541
+
542
+ it 'should generate subdomains' do
543
+ MockResponse.subdomains("1/2/3").should == ["1/2/3", '1/2', '1']
544
+ end
545
+
546
+ it 'should generate a json representation of itself' do
547
+ endpoint = "greeting"
548
+ requests_url = "requests_url"
549
+ response_spec = convert_keys_to_strings({
550
+ :id => 1,
551
+ :endpoint => endpoint,
552
+ :requests_url => requests_url,
553
+ :request => {
554
+ :body_content => %w(login),
555
+ :parameters => {
556
+ :name => "leon"
557
+ },
558
+ :headers => {
559
+ :header => 'header'
560
+ },
561
+ :http_method => "post"
562
+ },
563
+ :response => {
564
+ :body => "response",
565
+ :delay => 0,
566
+ :content_type => 'text/plain',
567
+ :status => 200,
568
+ :default => false
569
+ }
570
+ })
571
+
572
+ mock_response = MockResponse.new(endpoint, response_spec)
573
+ mock_response.requests_url = requests_url
574
+ JSON.parse(mock_response.raw).should == response_spec
575
+ end
576
+
577
+ end