From 7c77ffd6dbc8148a854ea38c3886e20aaac9b557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raquel=20Guimar=C3=A3es?= Date: Tue, 24 Sep 2013 16:56:11 -0300 Subject: [PATCH 01/25] +mobing contract request signature matching --- lib/pacto/contract.rb | 8 +++++- spec/unit/pacto/contract_spec.rb | 42 ++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/lib/pacto/contract.rb b/lib/pacto/contract.rb index e1934a5..e7e2ec3 100644 --- a/lib/pacto/contract.rb +++ b/lib/pacto/contract.rb @@ -1,18 +1,23 @@ module Pacto class Contract + def initialize(request, response) @request = request @response = response end def stub! - Pacto.configuration.provider.stub!(@request, stub_response) unless @request.nil? + @stub = Pacto.configuration.provider.stub!(@request, stub_response) unless @request.nil? end def validate(response_gotten = provider_response, opt = {}) @response.validate(response_gotten, opt) end + def matches? request_signature + @stub.matches? request_signature unless @stub.nil? + end + private def provider_response @@ -22,5 +27,6 @@ def provider_response def stub_response @response.instantiate end + end end diff --git a/spec/unit/pacto/contract_spec.rb b/spec/unit/pacto/contract_spec.rb index 8c23921..bc658ae 100644 --- a/spec/unit/pacto/contract_spec.rb +++ b/spec/unit/pacto/contract_spec.rb @@ -1,19 +1,25 @@ module Pacto describe Contract do let(:request) { double 'request' } + let(:request_signature) { double 'request_signature' } + let(:request_matcher) do + d = double 'request_matcher' + d.stub(:matches?) do |r| + r == request_signature + end + d + end let(:response) { double 'response' } - let(:contract) { described_class.new request, response } let(:provider) { double 'provider' } + let(:instantiated_response) { double 'instantiated response' } - describe '#stub!' do - before do - response.stub(:instantiate => instantiated_response) - Pacto.configuration.provider = provider - end - - let(:instantiated_response) { double 'instantiated response' } + before do + response.stub(:instantiate => instantiated_response) + Pacto.configuration.provider = provider + end + describe '#stub!' do it 'instantiates the response and registers a stub' do response.should_receive :instantiate provider.should_receive(:stub!).with request, instantiated_response @@ -51,5 +57,25 @@ module Pacto end end end + + describe '#matches?' do + + context 'when the contract is not stubbed' do + it 'should return false' do + expect(contract.matches? request_signature).to be_false + end + end + + context 'when the contract is stubbed' do + it 'should return true if it matches the request' do + provider.should_receive(:stub!).with(request, instantiated_response).and_return(request_matcher) + contract.stub! + expect(contract.matches? request_signature).to be_true + expect(contract.matches? :anything).to be_false + end + end + + end + end end From c892ca1903ca19a180b612a4fbbe6dbb6a6ca454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raquel=20Guimar=C3=A3es?= Date: Tue, 24 Sep 2013 18:33:36 -0300 Subject: [PATCH 02/25] +mob implemented contract_for --- lib/pacto/core/contract_repository.rb | 6 +++ .../pacto/core/contract_repository_spec.rb | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index c5a843e..2464d5c 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -30,5 +30,11 @@ def registered def unregister_all! registered.clear end + + def contract_for(request_signature) + registered.values.inject(Set.new) do |result, contract_set| + result.merge(contract_set.keep_if { |c| c.matches? request_signature }) + end + end end end diff --git a/spec/unit/pacto/core/contract_repository_spec.rb b/spec/unit/pacto/core/contract_repository_spec.rb index 837e4f0..b57445c 100644 --- a/spec/unit/pacto/core/contract_repository_spec.rb +++ b/spec/unit/pacto/core/contract_repository_spec.rb @@ -3,6 +3,7 @@ let(:another_tag) { 'another_tag' } let(:contract) { double('contract') } let(:another_contract) { double('another_contract') } + let(:request_signature) { double('request_signature') } after do described_class.unregister_all! @@ -96,4 +97,42 @@ described_class.registered.should be_empty end end + + describe '.contract_for' do + context 'when no contracts are found for a request' do + it 'should return an empty list' do + expect(described_class.contract_for request_signature).to be_empty + end + end + context 'when contracts are found for a request' do + it 'should return the matching contracts' do + my_contracts = 5.times.inject([]) do |res| + res << create_dummy_contract + end + + described_class.configure do |c| + my_contracts.each do |contract| + c.register_contract contract + end + end + Pacto::Contract.any_instance.stub(:stub!).and_return(double('request_matcher')) + result_bitmap = [false, true, true, false, false] + Pacto::Contract.any_instance.stub(:matches?).and_return do + result_bitmap.shift + end + Pacto.use :default + + expected_contracts = Set.new [my_contracts[1], my_contracts[2]] + + expect(described_class.contract_for request_signature).to eq(expected_contracts) + end + end + end + + def create_dummy_contract + request = double('request') + response = double('response') + Pacto::Contract.new request, response + end + end From 62ef6ef491c94c0e20a97682663a4fa92f1b61dd Mon Sep 17 00:00:00 2001 From: Fernando Junior Date: Wed, 25 Sep 2013 14:14:46 -0300 Subject: [PATCH 03/25] +maxlinc removing multiple rpsec files --- .rspec | 2 -- .rspec_integration | 4 ---- .rspec_unit | 4 ---- Rakefile | 18 +++++++----------- spec/integration/spec_helper.rb | 0 spec/spec_helper.rb | 6 ++++++ spec/unit/spec_helper.rb | 7 ------- 7 files changed, 13 insertions(+), 28 deletions(-) delete mode 100644 .rspec_integration delete mode 100644 .rspec_unit delete mode 100644 spec/integration/spec_helper.rb delete mode 100644 spec/unit/spec_helper.rb diff --git a/.rspec b/.rspec index d632cbc..58e8efe 100644 --- a/.rspec +++ b/.rspec @@ -1,4 +1,2 @@ --colour --require spec_helper ---require integration/spec_helper ---require unit/spec_helper diff --git a/.rspec_integration b/.rspec_integration deleted file mode 100644 index 58bc43e..0000000 --- a/.rspec_integration +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---require spec_helper ---require integration/spec_helper ---pattern spec/integration/**/*_spec.rb diff --git a/.rspec_unit b/.rspec_unit deleted file mode 100644 index 5443833..0000000 --- a/.rspec_unit +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---require spec_helper ---require unit/spec_helper ---pattern spec/unit/**/*_spec.rb diff --git a/Rakefile b/Rakefile index c375d74..9142001 100644 --- a/Rakefile +++ b/Rakefile @@ -18,16 +18,12 @@ Cucumber::Rake::Task.new(:journeys) do |t| t.cucumber_opts = 'features --format pretty' end -if defined?(RSpec) - desc 'Run unit tests' - task :unit do - abort unless system('rspec --option .rspec_unit') - end - - desc 'Run integration tests' - task :integration do - abort unless system('rspec --option .rspec_integration') - end +RSpec::Core::RakeTask.new(:unit) do |t| + t.pattern = 'spec/unit/**/*_spec.rb' +end - task :default => [:unit, :integration, :journeys, :rubocop, 'coveralls:push'] +RSpec::Core::RakeTask.new(:integration) do |t| + t.pattern = 'spec/integration/**/*_spec.rb' end + +task :default => [:unit, :integration, :journeys, :rubocop, 'coveralls:push'] diff --git a/spec/integration/spec_helper.rb b/spec/integration/spec_helper.rb deleted file mode 100644 index e69de29..0000000 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f9f9848..86491b8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,3 +2,9 @@ require 'pacto' require 'pacto/server' require 'stringio' + +RSpec.configure do |config| + config.before(:each) do + Pacto.clear! + end +end diff --git a/spec/unit/spec_helper.rb b/spec/unit/spec_helper.rb deleted file mode 100644 index 12e752a..0000000 --- a/spec/unit/spec_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'coveralls_helper' - -RSpec.configure do |config| - config.before(:each) do - Pacto.clear! - end -end From 0ac52406c5d58e3005a025fe138444308395bf79 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 14:38:53 -0300 Subject: [PATCH 04/25] something in e2e is not leaking data across tests. use :all for now, but hope to find the root cause --- spec/spec_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 86491b8..8a29f4c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,6 +4,7 @@ require 'stringio' RSpec.configure do |config| + # I'd like this to be before :each, but there is an issue with one test config.before(:each) do Pacto.clear! end From a4d3e96796396e04cadab5116e76a8ecfa5b2669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raquel=20Guimar=C3=A3es?= Date: Wed, 25 Sep 2013 15:40:32 -0300 Subject: [PATCH 05/25] +mobing adds callback registration --- lib/pacto.rb | 1 + lib/pacto/core/callback.rb | 4 ++++ lib/pacto/core/configuration.rb | 6 ++++++ lib/pacto/stubs/built_in.rb | 7 +++++-- spec/unit/pacto/core/configuration_spec.rb | 8 ++++++++ 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 lib/pacto/core/callback.rb diff --git a/lib/pacto.rb b/lib/pacto.rb index 0255535..9be5ee2 100644 --- a/lib/pacto.rb +++ b/lib/pacto.rb @@ -12,6 +12,7 @@ require 'pacto/core/contract_repository' require 'pacto/core/configuration' +require 'pacto/core/callback' require 'pacto/logger' require 'pacto/exceptions/invalid_contract.rb' require 'pacto/extensions' diff --git a/lib/pacto/core/callback.rb b/lib/pacto/core/callback.rb new file mode 100644 index 0000000..8fd689d --- /dev/null +++ b/lib/pacto/core/callback.rb @@ -0,0 +1,4 @@ +module Pacto + class Callback < Proc + end +end diff --git a/lib/pacto/core/configuration.rb b/lib/pacto/core/configuration.rb index 7f16cc4..87fc482 100644 --- a/lib/pacto/core/configuration.rb +++ b/lib/pacto/core/configuration.rb @@ -1,6 +1,7 @@ module Pacto class Configuration attr_accessor :preprocessor, :postprocessor, :provider, :strict_matchers, :contracts_path, :logger + attr_reader :callback def initialize @preprocessor = ERBProcessor.new @@ -10,10 +11,15 @@ def initialize @contracts_path = nil @logger = Logger.instance @logger.level = :debug if ENV['PACTO_DEBUG'] + @callback = Pacto::Callback.new { } end def register_contract(contract = nil, *tags) Pacto.register_contract(contract, *tags) end + + def register_callback(&block) + @callback = Pacto::Callback.new(&block) + end end end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 54272f6..7208d8e 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -17,7 +17,7 @@ def stub! request, response }) end - def process(request_signature, response) + def process(contracts, request_signature, response) unless processor.nil? bound_values = {} bound_values.merge!({:req => {'HEADERS' => request_signature.headers}}) if processor.class == ERBProcessor @@ -31,7 +31,10 @@ def process(request_signature, response) def register_callbacks WebMock.after_request do |request_signature, response| - process request_signature, response + contracts = Pacto.contract_for request_signature + + process contracts, request_signature, response + Pacto.configuration.callback.call contracts, request_signature, response end end diff --git a/spec/unit/pacto/core/configuration_spec.rb b/spec/unit/pacto/core/configuration_spec.rb index caf109f..4672069 100644 --- a/spec/unit/pacto/core/configuration_spec.rb +++ b/spec/unit/pacto/core/configuration_spec.rb @@ -16,5 +16,13 @@ end Pacto.configuration.contracts_path.should eql(contracts_path) end + + it 'register a Pacto Callback' do + callback_block = Pacto::Callback.new { } + Pacto.configure do |c| + c.register_callback(&callback_block) + end + Pacto.configuration.callback.should eq(callback_block) + end end end From da5cce89cd5894a839b23bc40859e3ecd47149c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raquel=20Guimar=C3=A3es?= Date: Wed, 25 Sep 2013 17:29:08 -0300 Subject: [PATCH 06/25] added hooks --- lib/pacto.rb | 1 + lib/pacto/contract.rb | 4 ++- lib/pacto/core/configuration.rb | 2 +- lib/pacto/core/contract_repository.rb | 6 ++-- lib/pacto/hooks/erb_hook.rb | 20 +++++++++++ lib/pacto/stubs/built_in.rb | 17 --------- spec/integration/templating_spec.rb | 3 ++ spec/unit/hooks/erb_hook_spec.rb | 51 +++++++++++++++++++++++++++ 8 files changed, 81 insertions(+), 23 deletions(-) create mode 100644 lib/pacto/hooks/erb_hook.rb create mode 100644 spec/unit/hooks/erb_hook_spec.rb diff --git a/lib/pacto.rb b/lib/pacto.rb index 9be5ee2..586c70e 100644 --- a/lib/pacto.rb +++ b/lib/pacto.rb @@ -26,6 +26,7 @@ require 'pacto/hash_merge_processor' require 'pacto/stubs/built_in' require 'pacto/meta_schema' +require 'pacto/hooks/erb_hook' module Pacto class << self diff --git a/lib/pacto/contract.rb b/lib/pacto/contract.rb index e7e2ec3..ffc498b 100644 --- a/lib/pacto/contract.rb +++ b/lib/pacto/contract.rb @@ -1,12 +1,14 @@ module Pacto class Contract + attr_reader :values def initialize(request, response) @request = request @response = response end - def stub! + def stub! values = {} + @values = values @stub = Pacto.configuration.provider.stub!(@request, stub_response) unless @request.nil? end diff --git a/lib/pacto/core/configuration.rb b/lib/pacto/core/configuration.rb index 87fc482..df45044 100644 --- a/lib/pacto/core/configuration.rb +++ b/lib/pacto/core/configuration.rb @@ -11,7 +11,7 @@ def initialize @contracts_path = nil @logger = Logger.instance @logger.level = :debug if ENV['PACTO_DEBUG'] - @callback = Pacto::Callback.new { } + @callback = Pacto::Hooks::ERBHook.new end def register_contract(contract = nil, *tags) diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index 2464d5c..23bc6f1 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -10,15 +10,13 @@ def register_contract(contract = nil, *tags) registered.count - start_count end - def use(tag, values = nil) + def use(tag, values = {}) merged_contracts = registered[:default].merge registered[tag] raise ArgumentError, "contract \"#{tag}\" not found" if merged_contracts.empty? - configuration.provider.values = values - merged_contracts.each do |contract| - contract.stub! + contract.stub! values end merged_contracts.count end diff --git a/lib/pacto/hooks/erb_hook.rb b/lib/pacto/hooks/erb_hook.rb new file mode 100644 index 0000000..9cd41f1 --- /dev/null +++ b/lib/pacto/hooks/erb_hook.rb @@ -0,0 +1,20 @@ +module Pacto + module Hooks + class ERBHook + def initialize + @processor = ERBProcessor.new + end + + def process(contracts, request_signature, response) + bound_values = contracts.empty? ? {} : contracts.first.values + bound_values.merge!({:req => { 'HEADERS' => request_signature.headers}}) + response.body = @processor.process response.body, bound_values + response.body + end + + def call(contracts, request_signature, response) + process contracts, request_signature, response + end + end + end +end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 7208d8e..9a448d7 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -1,7 +1,6 @@ module Pacto module Stubs class BuiltIn - attr_accessor :values def initialize register_callbacks @@ -17,31 +16,15 @@ def stub! request, response }) end - def process(contracts, request_signature, response) - unless processor.nil? - bound_values = {} - bound_values.merge!({:req => {'HEADERS' => request_signature.headers}}) if processor.class == ERBProcessor - bound_values.merge! @values unless @values.nil? - response.body = processor.process response.body, bound_values - end - response.body - end - private def register_callbacks WebMock.after_request do |request_signature, response| contracts = Pacto.contract_for request_signature - - process contracts, request_signature, response Pacto.configuration.callback.call contracts, request_signature, response end end - def processor - Pacto.configuration.postprocessor - end - def format_body(body) if body.is_a?(Hash) || body.is_a?(Array) body.to_json diff --git a/spec/integration/templating_spec.rb b/spec/integration/templating_spec.rb index 693ed10..2594a69 100644 --- a/spec/integration/templating_spec.rb +++ b/spec/integration/templating_spec.rb @@ -30,6 +30,9 @@ c.preprocessor = nil c.postprocessor = nil c.strict_matchers = false + c.register_callback do |contracts, req, res| + res + end end response.keys.should == ['message'] diff --git a/spec/unit/hooks/erb_hook_spec.rb b/spec/unit/hooks/erb_hook_spec.rb new file mode 100644 index 0000000..9a31846 --- /dev/null +++ b/spec/unit/hooks/erb_hook_spec.rb @@ -0,0 +1,51 @@ +describe Pacto::Hooks::ERBHook do + describe '.process' do + let(:req) { + OpenStruct.new({:headers => {'User-Agent' => 'abcd'}}) + } + let(:converted_req) { + {'HEADERS' => {'User-Agent' => 'abcd'}} + } + let(:res) { + OpenStruct.new({:body => 'before'}) + } + + before do + end + + context 'no matching contracts' do + it 'should bind the request' do + contracts = Set.new + mock_erb({ :req => converted_req }) + described_class.new.process contracts, req, res + res.body.should == 'after' + end + end + + context 'one matching contract' do + it 'should bind the request and the contract\'s values' do + contract = OpenStruct.new({:values => {:max => 'test'}}) + contracts = Set.new([contract]) + mock_erb({ :req => converted_req, :max => 'test'}) + described_class.new.process contracts, req, res + res.body.should == 'after' + end + end + + context 'multiple matching contracts' do + it 'should bind the request and the first contract\'s values' do + contract1 = OpenStruct.new({:values => {:max => 'test'}}) + contract2 = OpenStruct.new({:values => {:mob => 'team'}}) + res = OpenStruct.new({:body => 'before'}) + mock_erb({ :req => converted_req, :max => 'test'}) + contracts = Set.new([contract1, contract2]) + described_class.new.process contracts, req, res + res.body.should == 'after' + end + end + end + + def mock_erb(hash) + Pacto::ERBProcessor.any_instance.should_receive(:process).with('before', hash).and_return('after') + end +end From c6286f53d1ee50bc7b6369e4d78951bdd8de8518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Raquel=20Guimar=C3=A3es?= Date: Wed, 25 Sep 2013 18:02:10 -0300 Subject: [PATCH 07/25] max is going crazy --- lib/pacto/core/callback.rb | 9 ++++++++- lib/pacto/core/configuration.rb | 9 +++++++-- lib/pacto/core/contract_repository.rb | 1 + lib/pacto/hooks/erb_hook.rb | 7 ++----- lib/pacto/stubs/built_in.rb | 2 +- spec/integration/e2e_spec.rb | 9 +++------ spec/unit/pacto/core/configuration_spec.rb | 2 +- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/pacto/core/callback.rb b/lib/pacto/core/callback.rb index 8fd689d..8e6ef30 100644 --- a/lib/pacto/core/callback.rb +++ b/lib/pacto/core/callback.rb @@ -1,4 +1,11 @@ module Pacto - class Callback < Proc + class Callback + def initialize(&block) + @callback = block + end + + def process(contracts, request_signature, response) + @callback.call contracts, request_signature, response + end end end diff --git a/lib/pacto/core/configuration.rb b/lib/pacto/core/configuration.rb index df45044..9821206 100644 --- a/lib/pacto/core/configuration.rb +++ b/lib/pacto/core/configuration.rb @@ -18,8 +18,13 @@ def register_contract(contract = nil, *tags) Pacto.register_contract(contract, *tags) end - def register_callback(&block) - @callback = Pacto::Callback.new(&block) + def register_callback(callback = nil, &block) + if block_given? + @callback = Pacto::Callback.new(&block) + else + raise "Expected a Pacto::Callback" unless callback.is_a? Pacto::Callback + @callback = callback + end end end end diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index 23bc6f1..23166ca 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -26,6 +26,7 @@ def registered end def unregister_all! + WebMock.reset! registered.clear end diff --git a/lib/pacto/hooks/erb_hook.rb b/lib/pacto/hooks/erb_hook.rb index 9cd41f1..282dc9c 100644 --- a/lib/pacto/hooks/erb_hook.rb +++ b/lib/pacto/hooks/erb_hook.rb @@ -1,6 +1,6 @@ module Pacto module Hooks - class ERBHook + class ERBHook < Pacto::Callback def initialize @processor = ERBProcessor.new end @@ -11,10 +11,7 @@ def process(contracts, request_signature, response) response.body = @processor.process response.body, bound_values response.body end - - def call(contracts, request_signature, response) - process contracts, request_signature, response - end + end end end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 9a448d7..c7b8806 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -21,7 +21,7 @@ def stub! request, response def register_callbacks WebMock.after_request do |request_signature, response| contracts = Pacto.contract_for request_signature - Pacto.configuration.callback.call contracts, request_signature, response + Pacto.configuration.callback.process contracts, request_signature, response end end diff --git a/spec/integration/e2e_spec.rb b/spec/integration/e2e_spec.rb index 4602a52..0bce7f5 100644 --- a/spec/integration/e2e_spec.rb +++ b/spec/integration/e2e_spec.rb @@ -39,16 +39,13 @@ context 'Journey' do it 'stubs multiple services with a single use' do - - Pacto.configure do |c| - c.postprocessor = Pacto::ERBProcessor.new - c.preprocessor = nil - end - login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') Pacto.configure do |c| + c.postprocessor = Pacto::ERBProcessor.new + c.preprocessor = nil + c.register_callback Pacto::Hooks::ERBHook.new c.register_contract login_contract, :default c.register_contract contract, :devices end diff --git a/spec/unit/pacto/core/configuration_spec.rb b/spec/unit/pacto/core/configuration_spec.rb index 4672069..b39faf5 100644 --- a/spec/unit/pacto/core/configuration_spec.rb +++ b/spec/unit/pacto/core/configuration_spec.rb @@ -20,7 +20,7 @@ it 'register a Pacto Callback' do callback_block = Pacto::Callback.new { } Pacto.configure do |c| - c.register_callback(&callback_block) + c.register_callback(callback_block) end Pacto.configuration.callback.should eq(callback_block) end From fe62447ca80d77214633f7ccfd973bd6cea2c275 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:08:59 -0300 Subject: [PATCH 08/25] store contract file for debugging purposes --- lib/pacto/contract.rb | 3 ++- lib/pacto/contract_factory.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pacto/contract.rb b/lib/pacto/contract.rb index ffc498b..f44d373 100644 --- a/lib/pacto/contract.rb +++ b/lib/pacto/contract.rb @@ -2,9 +2,10 @@ module Pacto class Contract attr_reader :values - def initialize(request, response) + def initialize(request, response, file = nil) @request = request @response = response + @file = file end def stub! values = {} diff --git a/lib/pacto/contract_factory.rb b/lib/pacto/contract_factory.rb index ee825d6..53c9ea2 100644 --- a/lib/pacto/contract_factory.rb +++ b/lib/pacto/contract_factory.rb @@ -9,7 +9,7 @@ def self.build_from_file(contract_path, host, preprocessor) schema.validate definition request = Request.new(host, definition['request']) response = Response.new(definition['response']) - Contract.new(request, response) + Contract.new(request, response, contract_path) end def self.schema From 6f8341d61a129bcc6f2e116e7e6427b9f19807da Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:17:22 -0300 Subject: [PATCH 09/25] fix contract_repo methods that weren't safe with Sets --- lib/pacto/core/contract_repository.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index 23166ca..571ffa7 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -11,7 +11,7 @@ def register_contract(contract = nil, *tags) end def use(tag, values = {}) - merged_contracts = registered[:default].merge registered[tag] + merged_contracts = registered[:default] + registered[tag] raise ArgumentError, "contract \"#{tag}\" not found" if merged_contracts.empty? @@ -26,14 +26,19 @@ def registered end def unregister_all! - WebMock.reset! registered.clear end def contract_for(request_signature) - registered.values.inject(Set.new) do |result, contract_set| - result.merge(contract_set.keep_if { |c| c.matches? request_signature }) + matches = Set.new + registered.values.each do |contract_set| + contract_set.each do |contract| + if contract.matches? request_signature + matches.add contract + end + end end + matches end end end From f4a2bc04e5c4460644bb21a10c60497d9ede4856 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:20:45 -0300 Subject: [PATCH 10/25] fix test configuration --- spec/integration/e2e_spec.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/spec/integration/e2e_spec.rb b/spec/integration/e2e_spec.rb index 0bce7f5..65cb28b 100644 --- a/spec/integration/e2e_spec.rb +++ b/spec/integration/e2e_spec.rb @@ -39,16 +39,20 @@ context 'Journey' do it 'stubs multiple services with a single use' do - login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') - contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') - Pacto.configure do |c| + c.strict_matchers = false c.postprocessor = Pacto::ERBProcessor.new c.preprocessor = nil c.register_callback Pacto::Hooks::ERBHook.new + end + # Preprocessor must be off before building! + login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') + contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') + Pacto.configure do |c| c.register_contract login_contract, :default c.register_contract contract, :devices end + Pacto.use(:devices, {:device_id => 42}) raw_response = HTTParty.get('http://dummyprovider.com/hello', headers: {'Accept' => 'application/json' }) From bacb4a6936c9aa7902e757851ade0a63d4392f59 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:21:53 -0300 Subject: [PATCH 11/25] rubocopped --- lib/pacto/core/configuration.rb | 2 +- spec/unit/hooks/erb_hook_spec.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pacto/core/configuration.rb b/lib/pacto/core/configuration.rb index 9821206..137e12c 100644 --- a/lib/pacto/core/configuration.rb +++ b/lib/pacto/core/configuration.rb @@ -22,7 +22,7 @@ def register_callback(callback = nil, &block) if block_given? @callback = Pacto::Callback.new(&block) else - raise "Expected a Pacto::Callback" unless callback.is_a? Pacto::Callback + raise 'Expected a Pacto::Callback' unless callback.is_a? Pacto::Callback @callback = callback end end diff --git a/spec/unit/hooks/erb_hook_spec.rb b/spec/unit/hooks/erb_hook_spec.rb index 9a31846..46312c5 100644 --- a/spec/unit/hooks/erb_hook_spec.rb +++ b/spec/unit/hooks/erb_hook_spec.rb @@ -9,7 +9,7 @@ let(:res) { OpenStruct.new({:body => 'before'}) } - + before do end @@ -44,8 +44,8 @@ end end end - + def mock_erb(hash) Pacto::ERBProcessor.any_instance.should_receive(:process).with('before', hash).and_return('after') - end + end end From 62baab286d7dd12e1ae0c4512b3b786222a8b414 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:25:10 -0300 Subject: [PATCH 12/25] stub! -> stub_contract! and stub_request! to avoid possible conflict with rspec Object.stub! --- lib/pacto/contract.rb | 4 ++-- lib/pacto/core/contract_repository.rb | 2 +- lib/pacto/stubs/built_in.rb | 2 +- spec/unit/pacto/contract_spec.rb | 10 +++++----- spec/unit/pacto/core/contract_repository_spec.rb | 8 ++++---- spec/unit/pacto/stubs/built_in_spec.rb | 16 ++++++++-------- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/pacto/contract.rb b/lib/pacto/contract.rb index f44d373..f54e722 100644 --- a/lib/pacto/contract.rb +++ b/lib/pacto/contract.rb @@ -8,9 +8,9 @@ def initialize(request, response, file = nil) @file = file end - def stub! values = {} + def stub_contract! values = {} @values = values - @stub = Pacto.configuration.provider.stub!(@request, stub_response) unless @request.nil? + @stub = Pacto.configuration.provider.stub_request!(@request, stub_response) unless @request.nil? end def validate(response_gotten = provider_response, opt = {}) diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index 571ffa7..65d08f7 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -16,7 +16,7 @@ def use(tag, values = {}) raise ArgumentError, "contract \"#{tag}\" not found" if merged_contracts.empty? merged_contracts.each do |contract| - contract.stub! values + contract.stub_contract! values end merged_contracts.count end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index c7b8806..2ca2b86 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -6,7 +6,7 @@ def initialize register_callbacks end - def stub! request, response + def stub_request! request, response stub = WebMock.stub_request(request.method, "#{request.host}#{request.path}") stub = stub.with(request_details(request)) if Pacto.configuration.strict_matchers stub.to_return({ diff --git a/spec/unit/pacto/contract_spec.rb b/spec/unit/pacto/contract_spec.rb index bc658ae..431314f 100644 --- a/spec/unit/pacto/contract_spec.rb +++ b/spec/unit/pacto/contract_spec.rb @@ -19,11 +19,11 @@ module Pacto Pacto.configuration.provider = provider end - describe '#stub!' do + describe '#stub_contract!' do it 'instantiates the response and registers a stub' do response.should_receive :instantiate - provider.should_receive(:stub!).with request, instantiated_response - contract.stub! + provider.should_receive(:stub_request!).with request, instantiated_response + contract.stub_contract! end end @@ -68,8 +68,8 @@ module Pacto context 'when the contract is stubbed' do it 'should return true if it matches the request' do - provider.should_receive(:stub!).with(request, instantiated_response).and_return(request_matcher) - contract.stub! + provider.should_receive(:stub_request!).with(request, instantiated_response).and_return(request_matcher) + contract.stub_contract! expect(contract.matches? request_signature).to be_true expect(contract.matches? :anything).to be_false end diff --git a/spec/unit/pacto/core/contract_repository_spec.rb b/spec/unit/pacto/core/contract_repository_spec.rb index b57445c..d97a4f7 100644 --- a/spec/unit/pacto/core/contract_repository_spec.rb +++ b/spec/unit/pacto/core/contract_repository_spec.rb @@ -71,13 +71,13 @@ let(:response_body) { double('response_body') } it 'should stub a contract with default values' do - contract.should_receive(:stub!) - another_contract.should_receive(:stub!) + contract.should_receive(:stub_contract!) + another_contract.should_receive(:stub_contract!) described_class.use(tag).should == 2 end it 'should stub default contract if unused tag' do - another_contract.should_receive(:stub!) + another_contract.should_receive(:stub_contract!) described_class.use(another_tag).should == 1 end end @@ -115,7 +115,7 @@ c.register_contract contract end end - Pacto::Contract.any_instance.stub(:stub!).and_return(double('request_matcher')) + Pacto::Contract.any_instance.stub(:stub_contract!).and_return(double('request_matcher')) result_bitmap = [false, true, true, false, false] Pacto::Contract.any_instance.stub(:matches?).and_return do result_bitmap.shift diff --git a/spec/unit/pacto/stubs/built_in_spec.rb b/spec/unit/pacto/stubs/built_in_spec.rb index 0241cf1..865d94e 100644 --- a/spec/unit/pacto/stubs/built_in_spec.rb +++ b/spec/unit/pacto/stubs/built_in_spec.rb @@ -38,7 +38,7 @@ module Stubs end end - describe '#stub!' do + describe '#stub_request!' do before do WebMock.should_receive(:stub_request). with(request.method, "#{request.host}#{request.path}"). @@ -65,7 +65,7 @@ module Stubs stubbed_request.stub(:with).and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -83,7 +83,7 @@ module Stubs stubbed_request.stub(:with).and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -99,7 +99,7 @@ module Stubs stubbed_request.stub(:with).and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -110,7 +110,7 @@ module Stubs stubbed_request.should_receive(:with). with({:headers => request.headers, :query => request.params}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -121,7 +121,7 @@ module Stubs stubbed_request.should_receive(:with). with({:headers => request.headers, :body => request.params}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -140,7 +140,7 @@ module Stubs stubbed_request.should_receive(:with). with({:query => request.params}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -159,7 +159,7 @@ module Stubs stubbed_request.should_receive(:with). with({}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end end From cac060f4bb6177474a798901e777b7aa40a4f6e4 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:45:36 -0300 Subject: [PATCH 13/25] reset webmock configuration between tests --- lib/pacto.rb | 1 + lib/pacto/stubs/built_in.rb | 4 ++++ spec/integration/templating_spec.rb | 1 + spec/spec_helper.rb | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/lib/pacto.rb b/lib/pacto.rb index 586c70e..3bfa01d 100644 --- a/lib/pacto.rb +++ b/lib/pacto.rb @@ -36,6 +36,7 @@ def configuration end def clear! + Pacto.configuration.provider.reset! @configuration = nil unregister_all! end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 2ca2b86..1ad5ae8 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -16,6 +16,10 @@ def stub_request! request, response }) end + def reset! + WebMock.reset! + end + private def register_callbacks diff --git a/spec/integration/templating_spec.rb b/spec/integration/templating_spec.rb index 2594a69..5a98de9 100644 --- a/spec/integration/templating_spec.rb +++ b/spec/integration/templating_spec.rb @@ -44,6 +44,7 @@ it 'should process erb on each request' do Pacto.configure do |c| c.preprocessor = nil + c.strict_matchers = false c.postprocessor = Pacto::ERBProcessor.new end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8a29f4c..064f97b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,6 +6,10 @@ RSpec.configure do |config| # I'd like this to be before :each, but there is an issue with one test config.before(:each) do + provider = Pacto.configuration.provider + unless provider.respond_to? :reset! + provider.stub(:reset!) + end Pacto.clear! end end From 2fa8499bb0ef58bad9c0de1ff3e967230fad4e90 Mon Sep 17 00:00:00 2001 From: Jesus Mercado Date: Fri, 27 Sep 2013 00:11:10 -0300 Subject: [PATCH 14/25] Improve the readability of the specs Contract and ContractRepository now are more clean and easy to understand ;). --- spec/unit/pacto/contract_spec.rb | 21 ++++----- .../pacto/core/contract_repository_spec.rb | 43 ++++++++----------- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/spec/unit/pacto/contract_spec.rb b/spec/unit/pacto/contract_spec.rb index bc658ae..a907d56 100644 --- a/spec/unit/pacto/contract_spec.rb +++ b/spec/unit/pacto/contract_spec.rb @@ -2,18 +2,12 @@ module Pacto describe Contract do let(:request) { double 'request' } let(:request_signature) { double 'request_signature' } - let(:request_matcher) do - d = double 'request_matcher' - d.stub(:matches?) do |r| - r == request_signature - end - d - end let(:response) { double 'response' } - let(:contract) { described_class.new request, response } let(:provider) { double 'provider' } let(:instantiated_response) { double 'instantiated response' } + subject(:contract) { described_class.new request, response } + before do response.stub(:instantiate => instantiated_response) Pacto.configuration.provider = provider @@ -59,23 +53,26 @@ module Pacto end describe '#matches?' do + let(:request_matcher) do + double('fake request matcher').tap do |matcher| + matcher.stub(:matches?) { |r| r == request_signature } + end + end context 'when the contract is not stubbed' do - it 'should return false' do + it 'returns false' do expect(contract.matches? request_signature).to be_false end end context 'when the contract is stubbed' do - it 'should return true if it matches the request' do + it 'returns true if it matches the request' do provider.should_receive(:stub!).with(request, instantiated_response).and_return(request_matcher) contract.stub! expect(contract.matches? request_signature).to be_true expect(contract.matches? :anything).to be_false end end - end - end end diff --git a/spec/unit/pacto/core/contract_repository_spec.rb b/spec/unit/pacto/core/contract_repository_spec.rb index b57445c..d4a53d3 100644 --- a/spec/unit/pacto/core/contract_repository_spec.rb +++ b/spec/unit/pacto/core/contract_repository_spec.rb @@ -3,7 +3,6 @@ let(:another_tag) { 'another_tag' } let(:contract) { double('contract') } let(:another_contract) { double('another_contract') } - let(:request_signature) { double('request_signature') } after do described_class.unregister_all! @@ -99,40 +98,36 @@ end describe '.contract_for' do + let(:request_signature) { double('request signature') } + context 'when no contracts are found for a request' do it 'should return an empty list' do expect(described_class.contract_for request_signature).to be_empty end end - context 'when contracts are found for a request' do - it 'should return the matching contracts' do - my_contracts = 5.times.inject([]) do |res| - res << create_dummy_contract - end - described_class.configure do |c| - my_contracts.each do |contract| - c.register_contract contract - end - end - Pacto::Contract.any_instance.stub(:stub!).and_return(double('request_matcher')) - result_bitmap = [false, true, true, false, false] - Pacto::Contract.any_instance.stub(:matches?).and_return do - result_bitmap.shift - end - Pacto.use :default - - expected_contracts = Set.new [my_contracts[1], my_contracts[2]] + context 'when contracts are found for a request' do + let(:contracts_that_match) { create_contracts 2, true } + let(:contracts_that_dont_match) { create_contracts 3, false } + let(:all_contracts) { contracts_that_match + contracts_that_dont_match } - expect(described_class.contract_for request_signature).to eq(expected_contracts) + it 'should return the matching contracts' do + register_and_use all_contracts + expect(described_class.contract_for request_signature).to eq(contracts_that_match) end end end - def create_dummy_contract - request = double('request') - response = double('response') - Pacto::Contract.new request, response + def create_contracts(total, matches) + total.times.map do + double('contract', + :stub! => double('request matcher'), + :matches? => matches) + end.to_set end + def register_and_use contracts + contracts.each { |contract| described_class.register_contract contract } + Pacto.use :default + end end From 5b77660dad34f2762f6ab3a9fdd2e89d64ea3021 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Mon, 30 Sep 2013 00:16:55 -0300 Subject: [PATCH 15/25] README update [ci_skip] --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 730e35e..5bb7b17 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,9 @@ contract = Pacto.build_from_file('/path/to/contract.json', 'http://dummyprovider response = Net::HTTP.get_response(URI.parse('http://dummyprovider.com')).body contract.validate response, body_only: true ``` + +Pacto also has the ability to match a request signature to a contract that is currently in used, via ```Pacto.contract_for request_signature``` + ## Auto-Generated Stubs Pacto provides an API to be used in the consumer's acceptance tests. It uses a custom JSON Schema parser and generator From 79ddb40f83df0b7ccee40327facb1d6bcbff934c Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Mon, 30 Sep 2013 00:37:45 -0300 Subject: [PATCH 16/25] files weren't staged for commit --- spec/unit/pacto/contract_spec.rb | 8 +------- .../pacto/core/contract_repository_spec.rb | 18 +----------------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/spec/unit/pacto/contract_spec.rb b/spec/unit/pacto/contract_spec.rb index a61bc73..0a2c0ab 100644 --- a/spec/unit/pacto/contract_spec.rb +++ b/spec/unit/pacto/contract_spec.rb @@ -66,15 +66,9 @@ module Pacto end context 'when the contract is stubbed' do -<<<<<<< HEAD - it 'should return true if it matches the request' do + it 'returns true if it matches the request' do provider.should_receive(:stub_request!).with(request, instantiated_response).and_return(request_matcher) contract.stub_contract! -======= - it 'returns true if it matches the request' do - provider.should_receive(:stub!).with(request, instantiated_response).and_return(request_matcher) - contract.stub! ->>>>>>> c549be2241c8bd10e25d51d492d113b03a4c0755 expect(contract.matches? request_signature).to be_true expect(contract.matches? :anything).to be_false end diff --git a/spec/unit/pacto/core/contract_repository_spec.rb b/spec/unit/pacto/core/contract_repository_spec.rb index f8e0154..97a18c1 100644 --- a/spec/unit/pacto/core/contract_repository_spec.rb +++ b/spec/unit/pacto/core/contract_repository_spec.rb @@ -106,26 +106,10 @@ end end -<<<<<<< HEAD - described_class.configure do |c| - my_contracts.each do |contract| - c.register_contract contract - end - end - Pacto::Contract.any_instance.stub(:stub_contract!).and_return(double('request_matcher')) - result_bitmap = [false, true, true, false, false] - Pacto::Contract.any_instance.stub(:matches?).and_return do - result_bitmap.shift - end - Pacto.use :default - - expected_contracts = Set.new [my_contracts[1], my_contracts[2]] -======= context 'when contracts are found for a request' do let(:contracts_that_match) { create_contracts 2, true } let(:contracts_that_dont_match) { create_contracts 3, false } let(:all_contracts) { contracts_that_match + contracts_that_dont_match } ->>>>>>> c549be2241c8bd10e25d51d492d113b03a4c0755 it 'should return the matching contracts' do register_and_use all_contracts @@ -137,7 +121,7 @@ def create_contracts(total, matches) total.times.map do double('contract', - :stub! => double('request matcher'), + :stub_contract! => double('request matcher'), :matches? => matches) end.to_set end From 4f1d204d779e0c87288472460f0e7c079a9861f3 Mon Sep 17 00:00:00 2001 From: Fernando Junior Date: Wed, 25 Sep 2013 14:14:46 -0300 Subject: [PATCH 17/25] +maxlinc removing multiple rpsec files --- .rspec | 2 -- .rspec_integration | 4 ---- .rspec_unit | 4 ---- Rakefile | 18 +++++++----------- spec/integration/spec_helper.rb | 0 spec/spec_helper.rb | 6 ++++++ spec/unit/spec_helper.rb | 7 ------- 7 files changed, 13 insertions(+), 28 deletions(-) delete mode 100644 .rspec_integration delete mode 100644 .rspec_unit delete mode 100644 spec/integration/spec_helper.rb delete mode 100644 spec/unit/spec_helper.rb diff --git a/.rspec b/.rspec index d632cbc..58e8efe 100644 --- a/.rspec +++ b/.rspec @@ -1,4 +1,2 @@ --colour --require spec_helper ---require integration/spec_helper ---require unit/spec_helper diff --git a/.rspec_integration b/.rspec_integration deleted file mode 100644 index 58bc43e..0000000 --- a/.rspec_integration +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---require spec_helper ---require integration/spec_helper ---pattern spec/integration/**/*_spec.rb diff --git a/.rspec_unit b/.rspec_unit deleted file mode 100644 index 5443833..0000000 --- a/.rspec_unit +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---require spec_helper ---require unit/spec_helper ---pattern spec/unit/**/*_spec.rb diff --git a/Rakefile b/Rakefile index c375d74..9142001 100644 --- a/Rakefile +++ b/Rakefile @@ -18,16 +18,12 @@ Cucumber::Rake::Task.new(:journeys) do |t| t.cucumber_opts = 'features --format pretty' end -if defined?(RSpec) - desc 'Run unit tests' - task :unit do - abort unless system('rspec --option .rspec_unit') - end - - desc 'Run integration tests' - task :integration do - abort unless system('rspec --option .rspec_integration') - end +RSpec::Core::RakeTask.new(:unit) do |t| + t.pattern = 'spec/unit/**/*_spec.rb' +end - task :default => [:unit, :integration, :journeys, :rubocop, 'coveralls:push'] +RSpec::Core::RakeTask.new(:integration) do |t| + t.pattern = 'spec/integration/**/*_spec.rb' end + +task :default => [:unit, :integration, :journeys, :rubocop, 'coveralls:push'] diff --git a/spec/integration/spec_helper.rb b/spec/integration/spec_helper.rb deleted file mode 100644 index e69de29..0000000 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f9f9848..86491b8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,3 +2,9 @@ require 'pacto' require 'pacto/server' require 'stringio' + +RSpec.configure do |config| + config.before(:each) do + Pacto.clear! + end +end diff --git a/spec/unit/spec_helper.rb b/spec/unit/spec_helper.rb deleted file mode 100644 index 12e752a..0000000 --- a/spec/unit/spec_helper.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'coveralls_helper' - -RSpec.configure do |config| - config.before(:each) do - Pacto.clear! - end -end From 404a4aafa01c8fbad7c06050ea759dd5f8960974 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 14:38:53 -0300 Subject: [PATCH 18/25] something in e2e is not leaking data across tests. use :all for now, but hope to find the root cause --- spec/spec_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 86491b8..8a29f4c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,6 +4,7 @@ require 'stringio' RSpec.configure do |config| + # I'd like this to be before :each, but there is an issue with one test config.before(:each) do Pacto.clear! end From 729f984b191e342ade91b5d99f8ff367224bd980 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:08:59 -0300 Subject: [PATCH 19/25] store contract file for debugging purposes --- lib/pacto/contract.rb | 3 ++- lib/pacto/contract_factory.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pacto/contract.rb b/lib/pacto/contract.rb index e7e2ec3..80883e3 100644 --- a/lib/pacto/contract.rb +++ b/lib/pacto/contract.rb @@ -1,9 +1,10 @@ module Pacto class Contract - def initialize(request, response) + def initialize(request, response, file = nil) @request = request @response = response + @file = file end def stub! diff --git a/lib/pacto/contract_factory.rb b/lib/pacto/contract_factory.rb index ee825d6..53c9ea2 100644 --- a/lib/pacto/contract_factory.rb +++ b/lib/pacto/contract_factory.rb @@ -9,7 +9,7 @@ def self.build_from_file(contract_path, host, preprocessor) schema.validate definition request = Request.new(host, definition['request']) response = Response.new(definition['response']) - Contract.new(request, response) + Contract.new(request, response, contract_path) end def self.schema From 04593d36b4b9b72a36d7865e4f13adf609112a25 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:20:45 -0300 Subject: [PATCH 20/25] fix test configuration Conflicts: spec/integration/e2e_spec.rb --- spec/integration/e2e_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spec/integration/e2e_spec.rb b/spec/integration/e2e_spec.rb index 4602a52..408f59e 100644 --- a/spec/integration/e2e_spec.rb +++ b/spec/integration/e2e_spec.rb @@ -39,19 +39,32 @@ context 'Journey' do it 'stubs multiple services with a single use' do +<<<<<<< HEAD +======= +>>>>>>> f4a2bc0... fix test configuration Pacto.configure do |c| + c.strict_matchers = false c.postprocessor = Pacto::ERBProcessor.new c.preprocessor = nil +<<<<<<< HEAD end login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') +======= + c.register_callback Pacto::Hooks::ERBHook.new + end + # Preprocessor must be off before building! + login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') + contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') +>>>>>>> f4a2bc0... fix test configuration Pacto.configure do |c| c.register_contract login_contract, :default c.register_contract contract, :devices end + Pacto.use(:devices, {:device_id => 42}) raw_response = HTTParty.get('http://dummyprovider.com/hello', headers: {'Accept' => 'application/json' }) From af239df8eb22f85ad8f549281cc39b8c6c60ab27 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:25:10 -0300 Subject: [PATCH 21/25] stub! -> stub_contract! and stub_request! to avoid possible conflict with rspec Object.stub! Conflicts: lib/pacto/contract.rb lib/pacto/core/contract_repository.rb spec/unit/pacto/contract_spec.rb spec/unit/pacto/core/contract_repository_spec.rb --- lib/pacto/contract.rb | 6 ++++-- lib/pacto/core/contract_repository.rb | 6 +++--- lib/pacto/stubs/built_in.rb | 2 +- spec/unit/pacto/contract_spec.rb | 12 +++++++++--- spec/unit/pacto/core/contract_repository_spec.rb | 6 +++--- spec/unit/pacto/stubs/built_in_spec.rb | 16 ++++++++-------- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/lib/pacto/contract.rb b/lib/pacto/contract.rb index 80883e3..f54e722 100644 --- a/lib/pacto/contract.rb +++ b/lib/pacto/contract.rb @@ -1,5 +1,6 @@ module Pacto class Contract + attr_reader :values def initialize(request, response, file = nil) @request = request @@ -7,8 +8,9 @@ def initialize(request, response, file = nil) @file = file end - def stub! - @stub = Pacto.configuration.provider.stub!(@request, stub_response) unless @request.nil? + def stub_contract! values = {} + @values = values + @stub = Pacto.configuration.provider.stub_request!(@request, stub_response) unless @request.nil? end def validate(response_gotten = provider_response, opt = {}) diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index 2464d5c..b2fe9d2 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -10,15 +10,15 @@ def register_contract(contract = nil, *tags) registered.count - start_count end - def use(tag, values = nil) - merged_contracts = registered[:default].merge registered[tag] + def use(tag, values = {}) + merged_contracts = registered[:default] + registered[tag] raise ArgumentError, "contract \"#{tag}\" not found" if merged_contracts.empty? configuration.provider.values = values merged_contracts.each do |contract| - contract.stub! + contract.stub_contract! values end merged_contracts.count end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 54272f6..9acc6ac 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -7,7 +7,7 @@ def initialize register_callbacks end - def stub! request, response + def stub_request! request, response stub = WebMock.stub_request(request.method, "#{request.host}#{request.path}") stub = stub.with(request_details(request)) if Pacto.configuration.strict_matchers stub.to_return({ diff --git a/spec/unit/pacto/contract_spec.rb b/spec/unit/pacto/contract_spec.rb index a907d56..4800ccd 100644 --- a/spec/unit/pacto/contract_spec.rb +++ b/spec/unit/pacto/contract_spec.rb @@ -13,11 +13,11 @@ module Pacto Pacto.configuration.provider = provider end - describe '#stub!' do + describe '#stub_contract!' do it 'instantiates the response and registers a stub' do response.should_receive :instantiate - provider.should_receive(:stub!).with request, instantiated_response - contract.stub! + provider.should_receive(:stub_request!).with request, instantiated_response + contract.stub_contract! end end @@ -66,9 +66,15 @@ module Pacto end context 'when the contract is stubbed' do +<<<<<<< HEAD it 'returns true if it matches the request' do provider.should_receive(:stub!).with(request, instantiated_response).and_return(request_matcher) contract.stub! +======= + it 'should return true if it matches the request' do + provider.should_receive(:stub_request!).with(request, instantiated_response).and_return(request_matcher) + contract.stub_contract! +>>>>>>> 62baab2... stub! -> stub_contract! and stub_request! to avoid possible conflict expect(contract.matches? request_signature).to be_true expect(contract.matches? :anything).to be_false end diff --git a/spec/unit/pacto/core/contract_repository_spec.rb b/spec/unit/pacto/core/contract_repository_spec.rb index d4a53d3..84c6073 100644 --- a/spec/unit/pacto/core/contract_repository_spec.rb +++ b/spec/unit/pacto/core/contract_repository_spec.rb @@ -70,13 +70,13 @@ let(:response_body) { double('response_body') } it 'should stub a contract with default values' do - contract.should_receive(:stub!) - another_contract.should_receive(:stub!) + contract.should_receive(:stub_contract!) + another_contract.should_receive(:stub_contract!) described_class.use(tag).should == 2 end it 'should stub default contract if unused tag' do - another_contract.should_receive(:stub!) + another_contract.should_receive(:stub_contract!) described_class.use(another_tag).should == 1 end end diff --git a/spec/unit/pacto/stubs/built_in_spec.rb b/spec/unit/pacto/stubs/built_in_spec.rb index 0241cf1..865d94e 100644 --- a/spec/unit/pacto/stubs/built_in_spec.rb +++ b/spec/unit/pacto/stubs/built_in_spec.rb @@ -38,7 +38,7 @@ module Stubs end end - describe '#stub!' do + describe '#stub_request!' do before do WebMock.should_receive(:stub_request). with(request.method, "#{request.host}#{request.path}"). @@ -65,7 +65,7 @@ module Stubs stubbed_request.stub(:with).and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -83,7 +83,7 @@ module Stubs stubbed_request.stub(:with).and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -99,7 +99,7 @@ module Stubs stubbed_request.stub(:with).and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -110,7 +110,7 @@ module Stubs stubbed_request.should_receive(:with). with({:headers => request.headers, :query => request.params}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -121,7 +121,7 @@ module Stubs stubbed_request.should_receive(:with). with({:headers => request.headers, :body => request.params}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -140,7 +140,7 @@ module Stubs stubbed_request.should_receive(:with). with({:query => request.params}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end @@ -159,7 +159,7 @@ module Stubs stubbed_request.should_receive(:with). with({}). and_return(stubbed_request) - described_class.new.stub! request, response + described_class.new.stub_request! request, response end end end From b1692a548da374a535b36566cdfe6b63a1bd78b0 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:45:36 -0300 Subject: [PATCH 22/25] reset webmock configuration between tests Conflicts: lib/pacto/stubs/built_in.rb --- lib/pacto.rb | 1 + lib/pacto/stubs/built_in.rb | 4 ++++ spec/integration/e2e_spec.rb | 13 +------------ spec/integration/templating_spec.rb | 1 + spec/spec_helper.rb | 4 ++++ spec/unit/pacto/contract_spec.rb | 6 ------ spec/unit/pacto/core/contract_repository_spec.rb | 2 +- 7 files changed, 12 insertions(+), 19 deletions(-) diff --git a/lib/pacto.rb b/lib/pacto.rb index 0255535..806097b 100644 --- a/lib/pacto.rb +++ b/lib/pacto.rb @@ -34,6 +34,7 @@ def configuration end def clear! + Pacto.configuration.provider.reset! @configuration = nil unregister_all! end diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 9acc6ac..ee592b4 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -17,6 +17,10 @@ def stub_request! request, response }) end + def reset! + WebMock.reset! + end + def process(request_signature, response) unless processor.nil? bound_values = {} diff --git a/spec/integration/e2e_spec.rb b/spec/integration/e2e_spec.rb index 408f59e..b3550dd 100644 --- a/spec/integration/e2e_spec.rb +++ b/spec/integration/e2e_spec.rb @@ -39,27 +39,16 @@ context 'Journey' do it 'stubs multiple services with a single use' do -<<<<<<< HEAD - -======= ->>>>>>> f4a2bc0... fix test configuration + Pacto.clear! Pacto.configure do |c| c.strict_matchers = false c.postprocessor = Pacto::ERBProcessor.new c.preprocessor = nil -<<<<<<< HEAD end - login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') - contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') - -======= - c.register_callback Pacto::Hooks::ERBHook.new - end # Preprocessor must be off before building! login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com') contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com') ->>>>>>> f4a2bc0... fix test configuration Pacto.configure do |c| c.register_contract login_contract, :default c.register_contract contract, :devices diff --git a/spec/integration/templating_spec.rb b/spec/integration/templating_spec.rb index 693ed10..2e76ce6 100644 --- a/spec/integration/templating_spec.rb +++ b/spec/integration/templating_spec.rb @@ -41,6 +41,7 @@ it 'should process erb on each request' do Pacto.configure do |c| c.preprocessor = nil + c.strict_matchers = false c.postprocessor = Pacto::ERBProcessor.new end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 8a29f4c..064f97b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -6,6 +6,10 @@ RSpec.configure do |config| # I'd like this to be before :each, but there is an issue with one test config.before(:each) do + provider = Pacto.configuration.provider + unless provider.respond_to? :reset! + provider.stub(:reset!) + end Pacto.clear! end end diff --git a/spec/unit/pacto/contract_spec.rb b/spec/unit/pacto/contract_spec.rb index 4800ccd..0a2c0ab 100644 --- a/spec/unit/pacto/contract_spec.rb +++ b/spec/unit/pacto/contract_spec.rb @@ -66,15 +66,9 @@ module Pacto end context 'when the contract is stubbed' do -<<<<<<< HEAD it 'returns true if it matches the request' do - provider.should_receive(:stub!).with(request, instantiated_response).and_return(request_matcher) - contract.stub! -======= - it 'should return true if it matches the request' do provider.should_receive(:stub_request!).with(request, instantiated_response).and_return(request_matcher) contract.stub_contract! ->>>>>>> 62baab2... stub! -> stub_contract! and stub_request! to avoid possible conflict expect(contract.matches? request_signature).to be_true expect(contract.matches? :anything).to be_false end diff --git a/spec/unit/pacto/core/contract_repository_spec.rb b/spec/unit/pacto/core/contract_repository_spec.rb index 84c6073..97a18c1 100644 --- a/spec/unit/pacto/core/contract_repository_spec.rb +++ b/spec/unit/pacto/core/contract_repository_spec.rb @@ -121,7 +121,7 @@ def create_contracts(total, matches) total.times.map do double('contract', - :stub! => double('request matcher'), + :stub_contract! => double('request matcher'), :matches? => matches) end.to_set end From f8c938060190bb6307742d8215aca046372bc2ea Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Wed, 25 Sep 2013 21:17:22 -0300 Subject: [PATCH 23/25] fix contract_repo methods that weren't safe with Sets --- lib/pacto/core/contract_repository.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/pacto/core/contract_repository.rb b/lib/pacto/core/contract_repository.rb index b2fe9d2..0f0c037 100644 --- a/lib/pacto/core/contract_repository.rb +++ b/lib/pacto/core/contract_repository.rb @@ -32,9 +32,15 @@ def unregister_all! end def contract_for(request_signature) - registered.values.inject(Set.new) do |result, contract_set| - result.merge(contract_set.keep_if { |c| c.matches? request_signature }) + matches = Set.new + registered.values.each do |contract_set| + contract_set.each do |contract| + if contract.matches? request_signature + matches.add contract + end + end end + matches end end end From e8105440c6ae27c62356979d56720e01a455e279 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Mon, 30 Sep 2013 01:55:13 -0300 Subject: [PATCH 24/25] WebMock.reset! does not reset callback --- lib/pacto/stubs/built_in.rb | 1 + spec/integration/e2e_spec.rb | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index ee592b4..c979c67 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -19,6 +19,7 @@ def stub_request! request, response def reset! WebMock.reset! + WebMock.reset_callbacks end def process(request_signature, response) diff --git a/spec/integration/e2e_spec.rb b/spec/integration/e2e_spec.rb index b3550dd..0094634 100644 --- a/spec/integration/e2e_spec.rb +++ b/spec/integration/e2e_spec.rb @@ -39,7 +39,6 @@ context 'Journey' do it 'stubs multiple services with a single use' do - Pacto.clear! Pacto.configure do |c| c.strict_matchers = false c.postprocessor = Pacto::ERBProcessor.new From 927cdb902e3acf78bfdef19de8ac1a946fa4c0d8 Mon Sep 17 00:00:00 2001 From: Max Lincoln Date: Mon, 30 Sep 2013 01:55:13 -0300 Subject: [PATCH 25/25] WebMock.reset! does not reset callback --- lib/pacto/stubs/built_in.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pacto/stubs/built_in.rb b/lib/pacto/stubs/built_in.rb index 1ad5ae8..ecc18af 100644 --- a/lib/pacto/stubs/built_in.rb +++ b/lib/pacto/stubs/built_in.rb @@ -18,6 +18,7 @@ def stub_request! request, response def reset! WebMock.reset! + WebMock.reset_callbacks end private