From b26cc792d224ec8ce631c255c9d116aefdf3c5f3 Mon Sep 17 00:00:00 2001 From: Fernando Freire Date: Mon, 15 Sep 2014 17:13:21 +0200 Subject: [PATCH 1/6] allows example body to be a hash instead of string --- lib/pacto/consumer/faraday_driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pacto/consumer/faraday_driver.rb b/lib/pacto/consumer/faraday_driver.rb index 2d5b06d..e62d86e 100644 --- a/lib/pacto/consumer/faraday_driver.rb +++ b/lib/pacto/consumer/faraday_driver.rb @@ -11,7 +11,7 @@ def execute(req) response = conn.send(req.method) do |faraday_request| # faraday_request.url = req.uri faraday_request.headers = req.headers - faraday_request.body = req.body + faraday_request.body = (req.body.is_a?(String) ? req.body : req.body.to_json) end faraday_to_pacto_response response From f80710812ab5700044e5c39be1c6f509787d9f9c Mon Sep 17 00:00:00 2001 From: Faris Mohammed Date: Wed, 17 Sep 2014 12:22:36 +0200 Subject: [PATCH 2/6] Supporting ruby evaluation in json file -- erb format --- .gitignore | 2 + lib/pacto/native_contract_factory.rb | 5 +++ spec/fixtures/contracts/contract.json.erb | 38 +++++++++++++++++++ .../pacto/native_contract_factory_spec.rb | 18 +++++++++ 4 files changed, 63 insertions(+) create mode 100644 spec/fixtures/contracts/contract.json.erb diff --git a/.gitignore b/.gitignore index faf42af..c3011d3 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ tmp tags pacto.log .polytrix/ +.ruby-gemset +.ruby-version diff --git a/lib/pacto/native_contract_factory.rb b/lib/pacto/native_contract_factory.rb index f23d6a5..45dae0c 100644 --- a/lib/pacto/native_contract_factory.rb +++ b/lib/pacto/native_contract_factory.rb @@ -1,3 +1,5 @@ +require 'erb' + module Pacto # Builds {Pacto::Contract} instances from Pacto's native Contract format. class NativeContractFactory @@ -9,6 +11,9 @@ def initialize(options = {}) def build_from_file(contract_path, host) contract_definition = File.read(contract_path) + if contract_path.to_s.end_with? '.erb' + contract_definition = ERB.new(contract_definition).result + end definition = JSON.parse(contract_definition) schema.validate definition definition['request'].merge!('host' => host) diff --git a/spec/fixtures/contracts/contract.json.erb b/spec/fixtures/contracts/contract.json.erb new file mode 100644 index 0000000..d54ce73 --- /dev/null +++ b/spec/fixtures/contracts/contract.json.erb @@ -0,0 +1,38 @@ +{ + "request": { + "http_method": "GET", + "path": "/hello_world", + "headers": { + "Accept": "application/json" + }, + "params": {} + }, + + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "schema": { + "description": "A simple response", + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + } + }, + + "examples": { + "default": { + "request": {}, + "response": { + "body": { + "message": "<%= "foo#{2+2}" %>", + "count": <%= 2+2 %> + } + } + } + } +} diff --git a/spec/unit/pacto/native_contract_factory_spec.rb b/spec/unit/pacto/native_contract_factory_spec.rb index ed7be9b..f2cef4c 100644 --- a/spec/unit/pacto/native_contract_factory_spec.rb +++ b/spec/unit/pacto/native_contract_factory_spec.rb @@ -13,6 +13,24 @@ module Pacto expect(contract).to be_a(Contract) end + context 'contract template ends with .erb' do + let(:contract_path) { File.join(contracts_path, "#{contract_name}.json.erb") } + + it 'builds the contract' do + contract = contract_factory.build_from_file(contract_path, host) + expect(contract).to be_a(Contract) + end + end + + context 'contract template does not end with .erb' do + let(:contract_name) { 'templating_contract' } + + it 'builds the contract' do + contract = contract_factory.build_from_file(contract_path, host) + expect(contract).to be_a(Contract) + end + end + context 'deprecated contracts' do let(:contracts_path) { %w(spec fixtures deprecated_contracts) } let(:contract_name) { 'deprecated_contract' } From f3bd809ce86aa632d8eaef9244b2a789e6de2200 Mon Sep 17 00:00:00 2001 From: Mariana Date: Tue, 11 Nov 2014 10:44:58 -0200 Subject: [PATCH 3/6] WebMock 1.20.4 does not like #with to be called with empty hash: .../webmock-1.20.4/lib/webmock/request_pattern.rb:23:in `with': #with method invoked with no arguments. Either options hash or block must be specified. (ArgumentError) --- lib/pacto/stubs/webmock_adapter.rb | 4 +++- spec/unit/pacto/stubs/webmock_adapter_spec.rb | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pacto/stubs/webmock_adapter.rb b/lib/pacto/stubs/webmock_adapter.rb index e2547d8..375ee11 100644 --- a/lib/pacto/stubs/webmock_adapter.rb +++ b/lib/pacto/stubs/webmock_adapter.rb @@ -54,7 +54,9 @@ def stub_request!(contract) uri_pattern = UriPattern.for(request_clause) stub = WebMock.stub_request(request_clause.http_method, uri_pattern) - stub.request_pattern.with(strict_details(request_clause)) if Pacto.configuration.strict_matchers + if Pacto.configuration.strict_matchers && strict_details(request_clause).any? + stub.request_pattern.with(strict_details(request_clause)) + end stub.to_return do |request| pacto_request = Pacto::Adapters::WebMock::PactoRequest.new request diff --git a/spec/unit/pacto/stubs/webmock_adapter_spec.rb b/spec/unit/pacto/stubs/webmock_adapter_spec.rb index e5a1ae7..9e1d158 100644 --- a/spec/unit/pacto/stubs/webmock_adapter_spec.rb +++ b/spec/unit/pacto/stubs/webmock_adapter_spec.rb @@ -142,9 +142,7 @@ module Stubs end it 'uses WebMock to stub the request' do - expect(request_pattern).to receive(:with). - with({}). - and_return(stubbed_request) + expect(request_pattern).to_not receive(:with) adapter.stub_request! contract end end From 1c40447cf201ee27a59e7365e7a9cfabfa7f319e Mon Sep 17 00:00:00 2001 From: Mariana Date: Wed, 12 Nov 2014 10:51:21 -0200 Subject: [PATCH 4/6] Allowing factory to match files ending in .json.erb --- lib/pacto/native_contract_factory.rb | 2 +- spec/unit/pacto/native_contract_factory_spec.rb | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/pacto/native_contract_factory.rb b/lib/pacto/native_contract_factory.rb index 45dae0c..f80611b 100644 --- a/lib/pacto/native_contract_factory.rb +++ b/lib/pacto/native_contract_factory.rb @@ -29,7 +29,7 @@ def files_for(contracts_dir) full_path = Pathname.new(contracts_dir).realpath if full_path.directory? - all_json_files = "#{full_path}/**/*.json" + all_json_files = "#{full_path}/**/*{.json,.json.erb}" Dir.glob(all_json_files).map do |f| Pathname.new(f) end diff --git a/spec/unit/pacto/native_contract_factory_spec.rb b/spec/unit/pacto/native_contract_factory_spec.rb index f2cef4c..da07469 100644 --- a/spec/unit/pacto/native_contract_factory_spec.rb +++ b/spec/unit/pacto/native_contract_factory_spec.rb @@ -39,5 +39,21 @@ module Pacto expect(contract).to be_a(Contract) end end + + describe '#files_for' do + context 'given directory' do + let(:contract_path) { File.join(contracts_path) } + + it 'includes .json files' do + files = contract_factory.files_for(contract_path).collect { |f| f.basename.to_s } + expect(files).to include('contract.json') + end + + it 'includes .json.erb files' do + files = contract_factory.files_for(contract_path).collect { |f| f.basename.to_s } + expect(files).to include('contract.json.erb') + end + end + end end end From 3bfae48cc289c081a2153faa20bdba781a4229c9 Mon Sep 17 00:00:00 2001 From: Mariana Date: Wed, 12 Nov 2014 11:12:31 -0200 Subject: [PATCH 5/6] Removing rubocop offenses --- lib/pacto/native_contract_factory.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/pacto/native_contract_factory.rb b/lib/pacto/native_contract_factory.rb index f80611b..f2204a9 100644 --- a/lib/pacto/native_contract_factory.rb +++ b/lib/pacto/native_contract_factory.rb @@ -10,17 +10,14 @@ def initialize(options = {}) end def build_from_file(contract_path, host) - contract_definition = File.read(contract_path) - if contract_path.to_s.end_with? '.erb' - contract_definition = ERB.new(contract_definition).result - end - definition = JSON.parse(contract_definition) + definition = parse_json(contract_path) schema.validate definition - definition['request'].merge!('host' => host) + body_to_schema(definition, 'request', contract_path) body_to_schema(definition, 'response', contract_path) method_to_http_method(definition, contract_path) - request = RequestClause.new(definition['request']) + + request = RequestClause.new(definition['request'].merge('host' => host)) response = ResponseClause.new(definition['response']) Contract.new(request: request, response: response, file: contract_path, name: definition['name'], examples: definition['examples']) end @@ -40,6 +37,12 @@ def files_for(contracts_dir) private + def parse_json(path) + contents = File.read(path) + contents = ERB.new(contents).result if path.extname == '.erb' + JSON.parse(contents) + end + def body_to_schema(definition, section, file) schema = definition[section].delete 'body' return nil unless schema From 954e0376abaac9a0816513febc7dab1a94494ab7 Mon Sep 17 00:00:00 2001 From: Mariana Date: Wed, 12 Nov 2014 11:15:48 -0200 Subject: [PATCH 6/6] Fixing unit tests - we don't always have a Pathname --- lib/pacto/native_contract_factory.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pacto/native_contract_factory.rb b/lib/pacto/native_contract_factory.rb index f2204a9..96095af 100644 --- a/lib/pacto/native_contract_factory.rb +++ b/lib/pacto/native_contract_factory.rb @@ -39,7 +39,7 @@ def files_for(contracts_dir) def parse_json(path) contents = File.read(path) - contents = ERB.new(contents).result if path.extname == '.erb' + contents = ERB.new(contents).result if path.to_s.end_with? '.erb' JSON.parse(contents) end