mirage-on-thin 3.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +6 -0
- data/.travis.yml +3 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +151 -0
- data/HISTORY +22 -0
- data/README.md +156 -0
- data/Rakefile +10 -0
- data/VERSION +1 -0
- data/bin/mirage +14 -0
- data/features/.nav +29 -0
- data/features/client/clear.feature +78 -0
- data/features/client/configure.feature +72 -0
- data/features/client/model.feature +95 -0
- data/features/client/preview_responses.feature +33 -0
- data/features/client/prime.feature +32 -0
- data/features/client/put.feature +111 -0
- data/features/client/readme.md +3 -0
- data/features/client/requests.feature +20 -0
- data/features/client/running.feature +51 -0
- data/features/client/save_and_revert.feature +39 -0
- data/features/client/start.feature +46 -0
- data/features/client/stop.feature +53 -0
- data/features/commandline_interface/help.feature +17 -0
- data/features/commandline_interface/readme.md +1 -0
- data/features/commandline_interface/start.feature +18 -0
- data/features/commandline_interface/stop.feature +42 -0
- data/features/logging.feature +6 -0
- data/features/prime.feature +35 -0
- data/features/readme.md +7 -0
- data/features/requests/delete.feature +48 -0
- data/features/requests/get.feature +36 -0
- data/features/save_and_revert.feature +35 -0
- data/features/step_definitions/my_steps.rb +98 -0
- data/features/step_definitions/observation_steps.rb +103 -0
- data/features/support/command_line.rb +33 -0
- data/features/support/env.rb +22 -0
- data/features/support/hooks.rb +26 -0
- data/features/support/mirage.rb +12 -0
- data/features/support/web.rb +20 -0
- data/features/templates/delete.feature +45 -0
- data/features/templates/get.feature +54 -0
- data/features/templates/path_wildcards.feature +10 -0
- data/features/templates/preview.feature +18 -0
- data/features/templates/put.feature +77 -0
- data/features/templates/put_with_substitutions.feature +22 -0
- data/features/templates/readme.md +4 -0
- data/features/templates/required_content.feature +113 -0
- data/features/web_user_interface.feature +44 -0
- data/full_build.sh +100 -0
- data/lib/mirage/client.rb +10 -0
- data/lib/mirage/client/cli_bridge.rb +30 -0
- data/lib/mirage/client/client.rb +73 -0
- data/lib/mirage/client/error.rb +22 -0
- data/lib/mirage/client/helpers/method_builder.rb +19 -0
- data/lib/mirage/client/request.rb +26 -0
- data/lib/mirage/client/requests.rb +13 -0
- data/lib/mirage/client/runner.rb +103 -0
- data/lib/mirage/client/template.rb +56 -0
- data/lib/mirage/client/template/configuration.rb +44 -0
- data/lib/mirage/client/template/model.rb +48 -0
- data/lib/mirage/client/template/model/common_methods.rb +24 -0
- data/lib/mirage/client/template/model/instance_methods.rb +95 -0
- data/lib/mirage/client/templates.rb +50 -0
- data/mirage-on-thin.gemspec +175 -0
- data/mirage_server.rb +35 -0
- data/server/app.rb +4 -0
- data/server/binary_data_checker.rb +15 -0
- data/server/extensions/hash.rb +10 -0
- data/server/extensions/object.rb +5 -0
- data/server/helpers.rb +3 -0
- data/server/helpers/http_headers.rb +31 -0
- data/server/helpers/template_requirements.rb +33 -0
- data/server/mock_response.rb +242 -0
- data/server/server.rb +184 -0
- data/spec/client/cli_bridge_spec.rb +63 -0
- data/spec/client/client_spec.rb +179 -0
- data/spec/client/helpers/method_builder_spec.rb +40 -0
- data/spec/client/request_spec.rb +39 -0
- data/spec/client/requests_spec.rb +9 -0
- data/spec/client/runner_spec.rb +138 -0
- data/spec/client/template/configuration_spec.rb +32 -0
- data/spec/client/template/model/common_methods_spec.rb +25 -0
- data/spec/client/template/model/instance_methods_spec.rb +169 -0
- data/spec/client/template/model_spec.rb +119 -0
- data/spec/client/template_spec.rb +146 -0
- data/spec/client/templates_spec.rb +197 -0
- data/spec/resources/binary.file +0 -0
- data/spec/server/binary_data_checker_spec.rb +21 -0
- data/spec/server/helpers/http_headers_spec.rb +20 -0
- data/spec/server/helpers/template_requirements_spec.rb +34 -0
- data/spec/server/mock_response_spec.rb +577 -0
- data/spec/server/server_spec.rb +156 -0
- data/spec/spec_helper.rb +85 -0
- data/tasks/application.rake +7 -0
- data/tasks/packaging.rake +28 -0
- data/tasks/tests.rake +25 -0
- data/views/index.haml +16 -0
- data/views/response.haml +46 -0
- 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
|