require 'spec_helper' require 'extensions/object' require 'extensions/hash' require 'mock_response' describe Mirage::MockResponse do before :each do MockResponse.delete_all end describe 'initialisation' do it 'should find binary data' do string="string" response_spec = convert_keys_to_strings({:response => {:body => string}}) BinaryDataChecker.should_receive(:contains_binary_data?).with(string).and_return(true) MockResponse.new("greeting", response_spec).binary?.should == true end it 'should not find binary data' do string="string" response_spec = convert_keys_to_strings({:response => {:body => string}}) BinaryDataChecker.should_receive(:contains_binary_data?).with(string).and_return(false) MockResponse.new("greeting", response_spec).binary?.should == false end end describe 'defaults' do describe 'request' do it 'should default http_method' do MockResponse.new("greeting", {}).request_spec['http_method'].should == "get" end end describe 'response' do it 'should default content_type' do MockResponse.new("greeting", {}).response_spec['content_type'].should == "text/plain" end it 'should default status code' do MockResponse.new("greeting", {}).response_spec['status'].should == 200 end it 'should default delay' do MockResponse.new("greeting", {}).response_spec['delay'].should == 0 end it 'should default default' do MockResponse.new("greeting", {}).response_spec['default'].should == false end end end describe 'saving state' do it 'should store the current set of responses' do greeting = MockResponse.new("greeting") farewell = MockResponse.new("farewell") MockResponse.backup MockResponse.new("farewell", "cheerio") MockResponse.revert MockResponse.all.should == [greeting, farewell] end end describe "response values" do it 'should return any headers set' do headers = { 'header' => 'value' } response_spec = convert_keys_to_strings({:response => {:headers => headers}}) MockResponse.new("greeting", response_spec).headers.should == headers end it 'should return the response value' do response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello")}}) MockResponse.new("greeting", response_spec).value.should == "hello" end it 'should return if the value contains binary data' do response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello ${name}")}}) BinaryDataChecker.should_receive(:contains_binary_data?).and_return(true) response = MockResponse.new("greeting", response_spec) response.value("", {"name" => "leon"}).should == "hello ${name}" end it 'should replace patterns with values found in request parameters' do response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello ${name}")}}) MockResponse.new("greeting", response_spec).value("", {"name" => "leon"}).should == "hello leon" end it 'should base64 decode values' do response_spec = convert_keys_to_strings({:response => {:body => "encoded value"}}) Base64.should_receive(:decode64).and_return("decoded value") MockResponse.new("greeting", response_spec).value("") end it 'should replace patterns with values found in the body' do response_spec = convert_keys_to_strings({:response => {:body => Base64.encode64("hello ${name>(.*?)<}")}}) MockResponse.new("greeting", response_spec).value("leon").should == "hello leon" end end describe "Matching http method" do it 'should find the response with the correct http method' do response_spec = convert_keys_to_strings({:request => {:http_method => "post"}}) response = MockResponse.new("greeting", response_spec) options = {:body => "", :params => {}, :endpoint => "greeting", :http_method => "post", :headers => {}} MockResponse.find(options).should == response options[:http_method] = "get" expect { MockResponse.find(options) }.to raise_error(ServerResponseNotFound) end end describe 'Finding by id' do it 'should find a response given its id' do response1 = MockResponse.new("greeting", "hello") MockResponse.new("farewell", "goodbye") MockResponse.find_by_id(response1.response_id).should == response1 end end describe 'deleting' do it 'should delete a response given its id' do response1 = MockResponse.new("greeting", "hello") MockResponse.delete(response1.response_id) expect { MockResponse.find_by_id(response1.response_id) }.to raise_error(ServerResponseNotFound) end it 'should delete all responses' do MockResponse.new("greeting", "hello") MockResponse.new("farewell", "goodbye") MockResponse.delete_all MockResponse.all.size.should == 0 end end describe 'matching' do it 'should convert requirements in to strings before matching' do requirement = 1234 spec = convert_keys_to_strings( { :request => { :parameters => {:number => requirement}, :body_content => [requirement], :headers => {:number => requirement} }, :response => { :body => 'response' } } ) MockResponse.new("greeting", spec) options = {:headers => {'number' => '1234'}, :params => {'number' => "1234"}, :endpoint => "greeting", :http_method => "get", :body => "1234", } expect { MockResponse.find(options) }.to_not raise_error end describe "matching on request parameters" do it 'should find the response if all required parameters are present' do get_spec = convert_keys_to_strings( { :request => { :http_method => "get", :parameters => { :firstname => "leon" } }, :response => { :body => Base64.encode64("get response") } } ) post_spec = convert_keys_to_strings( { :request => { :http_method => "post", :parameters => { :firstname => "leon" } }, :response => { :body => Base64.encode64("post response") } } ) get_response = MockResponse.new("greeting", get_spec) post_response = MockResponse.new("greeting", post_spec) options = {:body => "", :params => {"firstname" => "leon"}, :endpoint => "greeting", :http_method => "post", :headers => {}} MockResponse.find(options).should == post_response MockResponse.find(options.merge(:http_method => "get")).should == get_response end it 'should match request parameter values using regexps' do response_spec = convert_keys_to_strings( { :request => { :parameters => {:firstname => "%r{leon.*}"} }, :response => { :body => 'response' } } ) response = MockResponse.new("greeting", response_spec) options = {:body => "", :params => {"firstname" => "leon"}, :endpoint => "greeting", :http_method => "get", :headers => {}} MockResponse.find(options).should == response MockResponse.find(options.merge(:params => {"firstname" => "leonard"})).should == response expect { MockResponse.find(options.merge(:params => {"firstname" => "leo"})) }.to raise_error(ServerResponseNotFound) end end describe 'matching request uri' do it 'should match using wild cards' do response_spec = convert_keys_to_strings( { :response => { :body => 'response' } } ) response = MockResponse.new('greeting/*/ashley/*', response_spec) MockResponse.find(:params => {}, :headers => {}, :http_method => "get", endpoint: 'greeting/leon/ashley/davis').should == response end end describe 'matching against request http_headers' do it 'should match using literals' do required_headers = { 'HEADER-1' => 'value1', 'HEADER-2' => 'value2' } spec = convert_keys_to_strings( { :request => { :headers => required_headers }, :response => { :body => 'response' } } ) response = MockResponse.new("greeting", spec) options = {:body => "leon", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => required_headers} MockResponse.find(options).should == response expect { MockResponse.find(options.merge(:headers => {})) }.to raise_error(ServerResponseNotFound) end it 'should match using regex' do required_headers = { 'CONTENT-TYPE' => '%r{.*/json}', } spec = convert_keys_to_strings( { :request => { :headers => required_headers }, :response => { :body => 'response' } } ) response = MockResponse.new("greeting", spec) options = {:body => "leon", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => {'CONTENT-TYPE' => 'application/json'}} MockResponse.find(options).should == response expect { MockResponse.find(options.merge(:headers => {'CONTENT-TYPE' => 'text/xml'})) }.to raise_error(ServerResponseNotFound) end end describe 'matching against the request body' do it 'should match required fragments in the request body' do response_spec = convert_keys_to_strings( { :request => { :body_content => %w(leon) }, :response => { :body => 'response' } } ) response = MockResponse.new("greeting", response_spec) options = {:body => "leon", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => {}} MockResponse.find(options).should == response expect { MockResponse.find(options.merge(:body => "jeff")) }.to raise_error(ServerResponseNotFound) end it 'should use regexs to match required fragements in the request body' do response_spec = convert_keys_to_strings( { :request => { :body_content => %w(%r{leon.*}) }, :response => { :body => 'response' } } ) response = MockResponse.new("greeting", response_spec) options = {:body => "leon", :params => {}, :endpoint => "greeting", :http_method => "get", :headers => {}} MockResponse.find(options).should == response MockResponse.find(options.merge(:body => "leonard")).should == response expect { MockResponse.find(options.merge(:body => "jeff")) }.to raise_error(ServerResponseNotFound) end end end it 'should be equal to another response that is the same not including the response value' do spec = convert_keys_to_strings({:response => {:body => "hello1", :content_type => "text/xml", :status => 202, :delay => 1.0, :default => true, :file => false} }) response = MockResponse.new("greeting", spec) response.should_not == MockResponse.new("greeting", {}) response.should == MockResponse.new("greeting", spec) end describe "scoring to represent the specificity of a response" do it 'should score an exact requirement match at 2' do response_spec = convert_keys_to_strings( { :request => { :parameters => {:firstname => "leon"} }, :response => { :body => 'response' } } ) MockResponse.new("greeting", response_spec).score.should == 2 response_spec = convert_keys_to_strings( { :request => { :body_content => %w(login) }, :response => { :body => 'response' } } ) MockResponse.new("greeting", response_spec).score.should == 2 response_spec = convert_keys_to_strings( { :request => { :headers => {'header' => 'header'} }, :response => { :body => 'response' } } ) MockResponse.new("greeting", response_spec).score.should == 2 end it 'should score a match found by regexp at 1' do response_spec = convert_keys_to_strings( { :request => { :parameters => {:firstname => "%r{leon.*}"} }, :response => { :body => 'response' } } ) MockResponse.new("greeting", response_spec).score.should == 1 response_spec = convert_keys_to_strings( { :request => { :body_content => %w(%r{input|output}) }, :response => { :body => 'response' } } ) MockResponse.new("greeting", response_spec).score.should == 1 response_spec = convert_keys_to_strings( { :request => { :headers => {'header' => '%r{.*blah}'} }, :response => { :body => 'response' } } ) MockResponse.new("greeting", response_spec).score.should == 1 end it 'should find the most specific response' do default_response_spec = convert_keys_to_strings( { :request => { :body_content => %w(login) }, :response => { :body => 'default_response' } } ) specific_response_spec = convert_keys_to_strings( { :request => { :body_content => %w(login), :parameters => { :name => "leon" } }, :response => { :body => 'specific response' } } ) MockResponse.new("greeting", default_response_spec) expected_response = MockResponse.new("greeting", specific_response_spec) options = {:body => "login", :params => {"name" => "leon"}, :endpoint => "greeting", :http_method => "get", :headers => {}} MockResponse.find(options).should == expected_response end end it 'should all matching to be based on body content, request parameters and http method' do response_spec = convert_keys_to_strings({ :request => { :body_content => %w(login), :parameters => { :name => "leon" }, :http_method => "post" }, :response => { :body => "response" } }) response = MockResponse.new("greeting", response_spec) options = {:body => "login", :params => {"name" => "leon"}, :endpoint => "greeting", :http_method => "post", :headers => {}} MockResponse.find(options).should == response options[:http_method] = 'get' expect { MockResponse.find(options) }.to raise_error(ServerResponseNotFound) end it 'should recycle response ids' do response_spec = convert_keys_to_strings({ :request => { :body_content => %w(login), :parameters => { :name => "leon" }, :http_method => "post" }, :response => { :body => "response" } }) response1 = MockResponse.new("greeting", response_spec) response_spec['response']['body'] = 'response2' response2 = MockResponse.new("greeting", response_spec) response1.response_id.should_not == nil response1.response_id.should == response2.response_id end it 'should raise an exception when a response is not found' do expect { MockResponse.find(:body => "login", :params => {:name => "leon"}, :endpoint => "greeting", :http_method => "post", :headers => {}) }.to raise_error(ServerResponseNotFound) end it 'should return all responses' do MockResponse.new("greeting", convert_keys_to_strings({:response => {:body => "hello"}})) MockResponse.new("greeting", convert_keys_to_strings({:request => {:body_content => %w(leon)}, :response => {:body => "hello leon"}})) MockResponse.new("greeting", convert_keys_to_strings({:request => {:body_content => %w(leon), :http_method => "post"}, :response => {:body => "hello leon"}})) MockResponse.new("deposit", convert_keys_to_strings({:request => {:body_content => %w(amount), :http_method => "post"}, :response => {:body => "received"}})) MockResponse.all.size.should == 4 end describe 'finding defaults' do it 'most appropriate response under parent resource and same http method' do level1_response = MockResponse.new("level1", convert_keys_to_strings({:response => {:body => "level1", :default => true}})) MockResponse.new("level1/level2", convert_keys_to_strings({:response => {:body => "level2", :default => true}, :request => {:body_content => %w(body)}})) MockResponse.find_default(:body => "", :http_method => "get", :endpoint => "level1/level2/level3", :params => {}, :headers => {}).should == level1_response end end it 'should generate subdomains' do MockResponse.subdomains("1/2/3").should == ["1/2/3", '1/2', '1'] end it 'should generate a json representation of itself' do endpoint = "greeting" requests_url = "requests_url" response_spec = convert_keys_to_strings({ :id => 1, :endpoint => endpoint, :requests_url => requests_url, :request => { :body_content => %w(login), :parameters => { :name => "leon" }, :headers => { :header => 'header' }, :http_method => "post" }, :response => { :body => "response", :delay => 0, :content_type => 'text/plain', :status => 200, :default => false } }) mock_response = MockResponse.new(endpoint, response_spec) mock_response.requests_url = requests_url JSON.parse(mock_response.raw).should == response_spec end end