Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/provider params #171

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/pact/consumer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
require 'pact/consumer/consumer_contract_builders'
require 'pact/consumer/interaction_builder'
require 'pact/term'
require 'pact/provider_param'
require 'pact/something_like'
1 change: 1 addition & 0 deletions lib/pact/provider/matchers/messages.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'term/ansicolor'
require 'pact/term'
require 'pact/provider_param'

module Pact
module Matchers
Expand Down
7 changes: 4 additions & 3 deletions lib/pact/provider/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ class Replayable
# See https://github.com/rack/rack/blob/e7d741c6282ca4cf4e01506f5681e6e6b14c0b32/SPEC#L87-89
NO_HTTP_PREFIX = ["CONTENT-TYPE", "CONTENT-LENGTH"]

def initialize expected_request
def initialize expected_request, provider_params={}
@expected_request = expected_request
@provider_params = provider_params
end

def method
expected_request.method
end

def path
expected_request.full_path
expected_request.full_path(@provider_params)
end

def body
Expand All @@ -35,7 +36,7 @@ def headers
request_headers = {}
return request_headers if expected_request.headers.is_a?(Pact::NullExpectation)
expected_request.headers.each do |key, value|
request_headers[rack_request_header_for(key)] = Pact::Reification.from_term(value)
request_headers[rack_request_header_for(key)] = Pact::Reification.from_term(value, @provider_params)
end
request_headers
end
Expand Down
4 changes: 2 additions & 2 deletions lib/pact/provider/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ def describe_interaction interaction, options
before do | example |
interaction_context.run_once :before do
Pact.configuration.logger.info "Running example '#{Pact::RSpec.full_description(example)}'"
set_up_provider_state interaction.provider_state, options[:consumer]
replay_interaction interaction
call_params = set_up_provider_state interaction.provider_state, options[:consumer]
replay_interaction interaction, call_params
interaction_context.last_response = last_response
end
end
Expand Down
6 changes: 6 additions & 0 deletions lib/pact/provider/state/provider_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class ProviderState

attr_accessor :name
attr_accessor :namespace
attr_accessor :provider_params

extend Pact::DSL

Expand All @@ -77,6 +78,11 @@ def initialize name, namespace, &block
@set_up_defined = false
@tear_down_defined = false
@no_op_defined = false
@provider_params = {}
end

def provider_param var_name, value
@provider_params[var_name] = value
end

dsl do
Expand Down
5 changes: 4 additions & 1 deletion lib/pact/provider/state/provider_state_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ def set_up_provider_state
get_global_base_provider_state.set_up
get_consumer_base_provider_state.set_up
if provider_state_name
get_provider_state.set_up
provider_state = get_provider_state
provider_state.set_up
return provider_state.provider_params
end
return {}
end

def tear_down_provider_state
Expand Down
4 changes: 2 additions & 2 deletions lib/pact/provider/test_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ module TestMethods
include Pact::Logging
include Rack::Test::Methods

def replay_interaction interaction
request = Request::Replayable.new(interaction.request)
def replay_interaction interaction, provider_params={}
request = Request::Replayable.new(interaction.request, provider_params)
args = [request.path, request.body, request.headers]

logger.info "Sending #{request.method.upcase} request to path: \"#{request.path}\" with headers: #{request.headers}, see debug logs for body"
Expand Down
64 changes: 46 additions & 18 deletions spec/features/foo_bar_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,65 @@

describe "Bar", :pact => true do

it "can retrieve a thing" do

Pact.clear_configuration
Pact.clear_consumer_world
before :all do
Pact.clear_configuration
Pact.clear_consumer_world

Pact.service_consumer "Foo" do
has_pact_with "Bar" do
mock_service :bar_service do
pact_specification_version "2"
port 4638
end
Pact.service_consumer "Foo" do
has_pact_with "Bar" do
mock_service :bar_service do
pact_specification_version "2"
port 4638
end
end
end
end

bar_service.
upon_receiving("a retrieve thing request").with({
it "can retrieve a thing" do
bar_service.
upon_receiving("a retrieve thing request").with({
method: :get,
path: '/thing'
}).
will_respond_with({
will_respond_with({
status: 200,
headers: { 'Content-Type' => 'application/json' },
body: Pact.each_like({status: Pact.term(/\d+/, "4")})
})

bar_response = Net::HTTP.get_response(URI('http://localhost:4638/thing'))
bar_response = Net::HTTP.get_response(URI('http://localhost:4638/thing'))

expect(bar_response.code).to eql '200'
expect(JSON.parse(bar_response.body)).to eq [{"status" => "4"}]
expect(bar_response.code).to eql '200'
expect(JSON.parse(bar_response.body)).to eq [{"status" => "4"}]

puts bar_service.write_pact
puts bar_service.write_pact
end

end
it 'can retrieve a specific thing with a provider param' do
bar_service.
upon_receiving("a retrieve specific thing request").with({
method: :get,
path: Pact.provider_param('/thing/:{id}', {id: '99'}),
headers: {
Authorization: Pact.provider_param('Bearer :{auth_token}', {auth_token: 'faketoken'})
}
}).
will_respond_with({
status: 200,
headers: { 'Content-Type' => 'application/json' },
body: Pact.each_like({status: Pact.term(/\d+/, "4")})
})

uri = URI('http://localhost:4638/thing/99')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = 'Bearer faketoken'
bar_response = Net::HTTP.start(uri.hostname, uri.port) { |http|
http.request(req)
}

expect(bar_response.code).to eql '200'
expect(JSON.parse(bar_response.body)).to eq [{"status" => "4"}]

puts bar_service.write_pact
end
end
5 changes: 5 additions & 0 deletions spec/features/production_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ def find_zebra_names
end

def call(env)
if (env['HTTP_AUTHORIZATION'])
if env['HTTP_AUTHORIZATION'] != 'password'
return [401, {'Content-Type' => 'application/json'}, {error: "The password is 'password'"}.to_json]
end
end
case env['PATH_INFO']
when "/zebra_names"
[200, {'Content-Type' => 'application/json'}, { names: find_zebra_names }.to_json]
Expand Down
15 changes: 15 additions & 0 deletions spec/features/provider_states/zebras.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,18 @@
FileUtils.rm_rf("tmp/a_mock_database.json")
end
end

Pact.provider_state "zebra with provider param" do
set_up do
some_data = {
id: '99',
name: 'Zee'
}
File.open("tmp/a_mock_database.json", "w") { |file| file << some_data.to_json }
provider_param :id, '99'
end

tear_down do
FileUtils.rm_rf("tmp/a_mock_database.json")
end
end
9 changes: 9 additions & 0 deletions spec/support/pact_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ def call env
[200, {'Content-Type' => 'text/plain'}, ['some text']]
elsif env['PATH_INFO'] == '/content_type_is_important'
[200, {'Content-Type' => 'application/json'}, [{message: "A message", note: "This will cause verify to fail if it using the wrong content type differ."}.to_json]]
elsif env['PATH_INFO'] == '/food_item/7'
[200, {'Content-Type' => 'application/json'}, [{message: 'One apple'}.to_json]]
else
raise "unexpected path #{env['PATH_INFO']}!!!"
end
Expand Down Expand Up @@ -46,6 +48,13 @@ def call env

WEATHER[:current_state] = 'sunny'
end

provider_state 'create one apple' do
set_up do
provider_param :item, 'apple'
provider_param :id, '7'
end
end
end
end

Expand Down
46 changes: 46 additions & 0 deletions spec/support/provider_param.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"consumer": {
"name": "some-test-consumer"
},
"provider": {
"name": "an unknown provider"
},
"interactions": [
{
"description": "a test request",
"request": {
"method": "get",
"path": "/food_item/5",
"query": "",
"headers": {
"Authorization": "Bearer faketoken"
},
"matchingRules": {
"$.path": {
"match": "provider_param",
"fill_string": "/food_item/:{id}"
},
"$.headers.Authorization": {
"match": "provider_param",
"fill_string": "Bearer :{auth_token}"
}
}
},
"response": {
"matchingRules": {
"$.headers.Content-Type" : {
"match": "regex", "regex": "json"
}
},
"status": 200,
"headers" : {
"Content-Type": "foo/json"
},
"body": {
"message" : "One apple"
}
},
"provider_state": "create one apple"
}
]
}
5 changes: 5 additions & 0 deletions tasks/pact-test.rake
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Pact::VerificationTask.new(:term_v2) do | pact |
pact.uri './spec/support/term-v2.json'
end

Pact::VerificationTask.new(:provider_param) do |pact|
pact.uri './spec/support/provider_param.json'
end

Pact::VerificationTask.new(:case_insensitive_response_header_matching) do | pact |
pact.uri './spec/support/case-insensitive-response-header-matching.json', :pact_helper => './spec/support/case-insensitive-response-header-matching.rb'
end
Expand Down Expand Up @@ -68,6 +72,7 @@ namespace :pact do
Rake::Task['pact:verify:test_app:content_type'].execute
Rake::Task['pact:verify:case_insensitive_response_header_matching'].execute
Rake::Task['pact:verify:term_v2'].execute
Rake::Task['pact:verify:provider_param'].execute
end

desc "All the verification tests with active support loaded"
Expand Down