pact 1.3.3 → 1.4.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +16 -1
- data/Gemfile +5 -0
- data/Gemfile.lock +34 -13
- data/README.md +3 -2
- data/example/animal-service/lib/animal_service/api.rb +1 -0
- data/example/zoo-app/lib/zoo_app/animal_service_client.rb +0 -9
- data/example/zoo-app/lib/zoo_app/models/alligator.rb +2 -0
- data/lib/pact.rb +6 -5
- data/lib/pact/cli.rb +0 -26
- data/lib/pact/consumer/configuration.rb +0 -1
- data/lib/pact/consumer/configuration/configuration_extensions.rb +51 -0
- data/lib/pact/consumer/consumer_contract_builder.rb +1 -2
- data/lib/pact/consumer/interaction_builder.rb +2 -4
- data/lib/pact/doc/interaction_view_model.rb +9 -6
- data/lib/pact/doc/sort_interactions.rb +1 -1
- data/lib/pact/provider/rspec.rb +11 -9
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +5 -0
- data/spec/lib/pact/consumer/interaction_builder_spec.rb +4 -8
- data/spec/support/case-insensitive-response-header-matching.json +21 -0
- data/spec/support/case-insensitive-response-header-matching.rb +15 -0
- data/tasks/pact-test.rake +5 -0
- metadata +42 -122
- data/lib/pact/configuration.rb +0 -195
- data/lib/pact/consumer/app_manager.rb +0 -158
- data/lib/pact/consumer/interactions_filter.rb +0 -48
- data/lib/pact/consumer/mock_service.rb +0 -2
- data/lib/pact/consumer/mock_service/app.rb +0 -82
- data/lib/pact/consumer/mock_service/interaction_delete.rb +0 -33
- data/lib/pact/consumer/mock_service/interaction_list.rb +0 -76
- data/lib/pact/consumer/mock_service/interaction_mismatch.rb +0 -73
- data/lib/pact/consumer/mock_service/interaction_post.rb +0 -31
- data/lib/pact/consumer/mock_service/interaction_replay.rb +0 -139
- data/lib/pact/consumer/mock_service/log_get.rb +0 -28
- data/lib/pact/consumer/mock_service/missing_interactions_get.rb +0 -30
- data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +0 -31
- data/lib/pact/consumer/mock_service/pact_post.rb +0 -33
- data/lib/pact/consumer/mock_service/rack_request_helper.rb +0 -51
- data/lib/pact/consumer/mock_service/verification_get.rb +0 -68
- data/lib/pact/consumer/mock_service_client.rb +0 -65
- data/lib/pact/consumer/mock_service_interaction_expectation.rb +0 -37
- data/lib/pact/consumer/request.rb +0 -27
- data/lib/pact/consumer/server.rb +0 -90
- data/lib/pact/consumer_contract.rb +0 -1
- data/lib/pact/consumer_contract/consumer_contract.rb +0 -115
- data/lib/pact/consumer_contract/consumer_contract_writer.rb +0 -84
- data/lib/pact/consumer_contract/file_name.rb +0 -19
- data/lib/pact/consumer_contract/headers.rb +0 -51
- data/lib/pact/consumer_contract/interaction.rb +0 -67
- data/lib/pact/consumer_contract/pact_file.rb +0 -24
- data/lib/pact/consumer_contract/request.rb +0 -73
- data/lib/pact/consumer_contract/service_consumer.rb +0 -28
- data/lib/pact/consumer_contract/service_provider.rb +0 -28
- data/lib/pact/logging.rb +0 -14
- data/lib/pact/matchers.rb +0 -1
- data/lib/pact/matchers/actual_type.rb +0 -16
- data/lib/pact/matchers/base_difference.rb +0 -37
- data/lib/pact/matchers/differ.rb +0 -153
- data/lib/pact/matchers/difference.rb +0 -13
- data/lib/pact/matchers/difference_indicator.rb +0 -26
- data/lib/pact/matchers/embedded_diff_formatter.rb +0 -62
- data/lib/pact/matchers/expected_type.rb +0 -35
- data/lib/pact/matchers/index_not_found.rb +0 -15
- data/lib/pact/matchers/list_diff_formatter.rb +0 -101
- data/lib/pact/matchers/matchers.rb +0 -139
- data/lib/pact/matchers/no_diff_indicator.rb +0 -18
- data/lib/pact/matchers/regexp_difference.rb +0 -13
- data/lib/pact/matchers/type_difference.rb +0 -16
- data/lib/pact/matchers/unexpected_index.rb +0 -11
- data/lib/pact/matchers/unexpected_key.rb +0 -11
- data/lib/pact/matchers/unix_diff_formatter.rb +0 -114
- data/lib/pact/reification.rb +0 -28
- data/lib/pact/rspec.rb +0 -53
- data/lib/pact/shared/active_support_support.rb +0 -51
- data/lib/pact/shared/dsl.rb +0 -76
- data/lib/pact/shared/jruby_support.rb +0 -18
- data/lib/pact/shared/json_differ.rb +0 -15
- data/lib/pact/shared/key_not_found.rb +0 -15
- data/lib/pact/shared/null_expectation.rb +0 -31
- data/lib/pact/shared/request.rb +0 -80
- data/lib/pact/shared/text_differ.rb +0 -14
- data/lib/pact/something_like.rb +0 -49
- data/lib/pact/symbolize_keys.rb +0 -12
- data/lib/pact/term.rb +0 -85
- data/spec/lib/pact/consumer/request_spec.rb +0 -24
- data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +0 -58
- data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +0 -180
- data/spec/lib/pact/consumer_contract/headers_spec.rb +0 -107
- data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -107
- data/spec/lib/pact/consumer_contract/request_spec.rb +0 -329
- data/spec/lib/pact/matchers/differ_spec.rb +0 -214
- data/spec/lib/pact/matchers/difference_spec.rb +0 -22
- data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +0 -90
- data/spec/lib/pact/matchers/index_not_found_spec.rb +0 -21
- data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +0 -114
- data/spec/lib/pact/matchers/matchers_spec.rb +0 -500
- data/spec/lib/pact/matchers/regexp_difference_spec.rb +0 -20
- data/spec/lib/pact/matchers/type_difference_spec.rb +0 -34
- data/spec/lib/pact/matchers/unexpected_index_spec.rb +0 -20
- data/spec/lib/pact/matchers/unexpected_key_spec.rb +0 -20
- data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +0 -216
- data/spec/lib/pact/reification_spec.rb +0 -67
- data/spec/lib/pact/shared/dsl_spec.rb +0 -86
- data/spec/lib/pact/shared/json_differ_spec.rb +0 -36
- data/spec/lib/pact/shared/key_not_found_spec.rb +0 -20
- data/spec/lib/pact/shared/request_spec.rb +0 -111
- data/spec/lib/pact/shared/text_differ_spec.rb +0 -54
- data/spec/lib/pact/something_like_spec.rb +0 -21
- data/spec/lib/pact/term_spec.rb +0 -89
- data/spec/support/dsl_spec_support.rb +0 -7
data/lib/pact/reification.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'randexp'
|
2
|
-
|
3
|
-
module Pact
|
4
|
-
module Reification
|
5
|
-
|
6
|
-
def self.from_term(term)
|
7
|
-
case term
|
8
|
-
when Pact::Term, Regexp, Pact::SomethingLike
|
9
|
-
term.generate
|
10
|
-
when Hash
|
11
|
-
term.inject({}) do |mem, (key,term)|
|
12
|
-
mem[key] = from_term(term)
|
13
|
-
mem
|
14
|
-
end
|
15
|
-
when Array
|
16
|
-
term.inject([]) do |mem, term|
|
17
|
-
mem << from_term(term)
|
18
|
-
mem
|
19
|
-
end
|
20
|
-
when Pact::Request::Base
|
21
|
-
from_term(term.to_hash)
|
22
|
-
else
|
23
|
-
term
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
data/lib/pact/rspec.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
# This is horrible, must work out a better way of doing this
|
3
|
-
module Pact
|
4
|
-
module RSpec
|
5
|
-
|
6
|
-
def self.color_enabled?
|
7
|
-
if ::RSpec.configuration.respond_to?(:color_enabled?)
|
8
|
-
::RSpec.configuration.color_enabled?(::RSpec.configuration.output_stream)
|
9
|
-
else
|
10
|
-
::RSpec.configuration.color_enabled?
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.formatter_class
|
15
|
-
if ::RSpec::Core::Formatters.respond_to?(:register)
|
16
|
-
require 'pact/provider/rspec/formatter_rspec_3'
|
17
|
-
Pact::Provider::RSpec::Formatter
|
18
|
-
else
|
19
|
-
require 'pact/provider/rspec/formatter_rspec_2'
|
20
|
-
Pact::Provider::RSpec::Formatter2
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.full_description example
|
26
|
-
example.respond_to?(:full_description) ? example.full_description : example.example.full_description
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.runner_defined?
|
30
|
-
defined?(::RSpec::Core::Runner)
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.is_rspec_3
|
34
|
-
::RSpec::Core::Formatters.respond_to?(:register)
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.is_rspec_2
|
38
|
-
!is_rspec_3
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.with_rspec_3
|
42
|
-
if is_rspec_3
|
43
|
-
yield
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.with_rspec_2
|
48
|
-
if is_rspec_2
|
49
|
-
yield
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module Pact
|
2
|
-
module ActiveSupportSupport
|
3
|
-
|
4
|
-
extend self
|
5
|
-
|
6
|
-
def fix_all_the_things thing
|
7
|
-
if thing.is_a?(Regexp)
|
8
|
-
fix_regexp(thing)
|
9
|
-
elsif thing.is_a?(Array)
|
10
|
-
thing.each{ | it | fix_all_the_things it }
|
11
|
-
elsif thing.is_a?(Hash)
|
12
|
-
thing.values.each{ | it | fix_all_the_things it }
|
13
|
-
elsif thing.class.name.start_with?("Pact")
|
14
|
-
thing.instance_variables.collect{ | iv_name | thing.instance_variable_get(iv_name)}.each do | iv |
|
15
|
-
fix_all_the_things iv
|
16
|
-
end
|
17
|
-
end
|
18
|
-
thing
|
19
|
-
end
|
20
|
-
|
21
|
-
# ActiveSupport JSON overwrites (i.e. TRAMPLES) the json methods of the Regexp class directly
|
22
|
-
# (beneath its destructive hooves of destruction).
|
23
|
-
# This does not seem to be able to be undone without affecting the JSON serialisation in the
|
24
|
-
# calling project, so the best way I've found to fix this issue is to reattach the
|
25
|
-
# original as_json to the Regexp instances in the ConsumerContract before we write them to the
|
26
|
-
# pact file. If anyone can find a better way, please submit a pull request ASAP!
|
27
|
-
def fix_regexp regexp
|
28
|
-
def regexp.as_json options = {}
|
29
|
-
{:json_class => 'Regexp', "o" => self.options, "s" => self.source }
|
30
|
-
end
|
31
|
-
regexp
|
32
|
-
end
|
33
|
-
|
34
|
-
# Having Active Support JSON loaded somehow kills the formatting of pretty_generate for objects.
|
35
|
-
# Don't ask me why, but it still seems to work for hashes, so the hacky work around is to
|
36
|
-
# reparse the generated JSON into a hash and pretty_generate that... sigh...
|
37
|
-
# Oh ActiveSupport, why....
|
38
|
-
def fix_json_formatting json
|
39
|
-
if json.include?("\n")
|
40
|
-
json
|
41
|
-
else
|
42
|
-
JSON.pretty_generate(JSON.parse(json, create_additions: false))
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def remove_unicode json
|
47
|
-
json.gsub(/\\u([0-9A-Za-z]{4})/) {|s| [$1.to_i(16)].pack("U")}
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|
data/lib/pact/shared/dsl.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
module Pact
|
2
|
-
|
3
|
-
class DslDelegator
|
4
|
-
|
5
|
-
def initialize delegation_target
|
6
|
-
@delegation_target = delegation_target
|
7
|
-
end
|
8
|
-
|
9
|
-
def instance_eval_with_previous_context_available(*args, &block)
|
10
|
-
with_previous_context_available(block.binding) do
|
11
|
-
bind_block_as_instance_method_on_self(&block).call(*args)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def method_missing(method, *args, &block)
|
18
|
-
if delegation_target_responds_to? method
|
19
|
-
delegation_target.send(method, *args, &block)
|
20
|
-
else
|
21
|
-
previous_context.send(method, *args, &block)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
attr_accessor :delegation_target, :previous_context
|
28
|
-
|
29
|
-
def bind_block_as_instance_method_on_self(&block)
|
30
|
-
create_instance_method_from_block(&block).bind(self)
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
def create_instance_method_from_block &block
|
35
|
-
meth = self.class.class_eval do
|
36
|
-
define_method :block_as_instance_method_, &block
|
37
|
-
meth = instance_method :block_as_instance_method_
|
38
|
-
remove_method :block_as_instance_method_
|
39
|
-
meth
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def with_previous_context_available(binding, &block)
|
44
|
-
@previous_context = binding.eval('self')
|
45
|
-
result = block.call
|
46
|
-
@previous_context = nil
|
47
|
-
result
|
48
|
-
end
|
49
|
-
|
50
|
-
def delegation_target_responds_to?(method)
|
51
|
-
delegation_target.respond_to? method
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
# Ripped from http://blog.joecorcoran.co.uk/2013/09/04/simple-pattern-ruby-dsl
|
58
|
-
# and then fixed up by using http://www.skorks.com/2013/03/a-closure-is-not-always-a-closure-in-ruby/
|
59
|
-
# to access variables and methods defined in the calling scope.
|
60
|
-
module DSL
|
61
|
-
def build(*args, &block)
|
62
|
-
new_instance_of_delegation_target_class = self.new(*args)
|
63
|
-
dsl_delegator_class = self.const_get('DSL_DELEGATOR_CLASS')
|
64
|
-
dsl_delegator = dsl_delegator_class.new(new_instance_of_delegation_target_class)
|
65
|
-
dsl_delegator.instance_eval_with_previous_context_available(&block)
|
66
|
-
new_instance_of_delegation_target_class.finalize
|
67
|
-
new_instance_of_delegation_target_class
|
68
|
-
end
|
69
|
-
|
70
|
-
def dsl(&block)
|
71
|
-
dsl_delegator_class = Class.new(DslDelegator, &block)
|
72
|
-
self.const_set('DSL_DELEGATOR_CLASS', dsl_delegator_class)
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Pact
|
2
|
-
module JRubySupport
|
3
|
-
|
4
|
-
# Under jruby, JSON.pretty_generate inserts a blank new line between the opening and closing
|
5
|
-
# brackets of an empty hash, like so:
|
6
|
-
# {
|
7
|
-
# "empty": {
|
8
|
-
#
|
9
|
-
# }
|
10
|
-
# }
|
11
|
-
# This screws up the UnixDiffFormatter, so we need to remove the blank lines.
|
12
|
-
|
13
|
-
def fix_blank_lines_in_empty_hashes json
|
14
|
-
json.gsub(/({\n)\n(\s*})/,'\1\2')
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Pact
|
2
|
-
class NullExpectation
|
3
|
-
def to_s
|
4
|
-
"<No expectation>"
|
5
|
-
end
|
6
|
-
|
7
|
-
def ==(other_object)
|
8
|
-
other_object.is_a? NullExpectation
|
9
|
-
end
|
10
|
-
|
11
|
-
def ===(other_object)
|
12
|
-
other_object.is_a? NullExpectation
|
13
|
-
end
|
14
|
-
|
15
|
-
def eql?(other_object)
|
16
|
-
self == other_object
|
17
|
-
end
|
18
|
-
|
19
|
-
def hash
|
20
|
-
2934820948209428748274238642672
|
21
|
-
end
|
22
|
-
|
23
|
-
def empty?
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
|
-
def nil?
|
28
|
-
true
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/pact/shared/request.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
require 'pact/matchers'
|
2
|
-
require 'pact/symbolize_keys'
|
3
|
-
require 'pact/consumer_contract/headers'
|
4
|
-
|
5
|
-
module Pact
|
6
|
-
|
7
|
-
module Request
|
8
|
-
|
9
|
-
class Base
|
10
|
-
include Pact::Matchers
|
11
|
-
include Pact::SymbolizeKeys
|
12
|
-
extend Pact::Matchers
|
13
|
-
|
14
|
-
attr_reader :method, :path, :headers, :body, :query, :options
|
15
|
-
|
16
|
-
def initialize(method, path, headers, body, query)
|
17
|
-
@method = method.to_s
|
18
|
-
@path = path.chomp('/')
|
19
|
-
@headers = Hash === headers ? Headers.new(headers) : headers # Could be a NullExpectation - TODO make this more elegant
|
20
|
-
@body = body
|
21
|
-
@query = query
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_json(options = {})
|
25
|
-
as_json.to_json(options)
|
26
|
-
end
|
27
|
-
|
28
|
-
def as_json options = {}
|
29
|
-
to_hash
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_hash
|
33
|
-
hash = {
|
34
|
-
method: method,
|
35
|
-
path: path,
|
36
|
-
}
|
37
|
-
|
38
|
-
hash.merge!(query: query) unless query.is_a? self.class.key_not_found.class
|
39
|
-
hash.merge!(headers: headers) unless headers.is_a? self.class.key_not_found.class
|
40
|
-
hash.merge!(body: body) unless body.is_a? self.class.key_not_found.class
|
41
|
-
hash
|
42
|
-
end
|
43
|
-
|
44
|
-
def method_and_path
|
45
|
-
"#{method.upcase} #{full_path}"
|
46
|
-
end
|
47
|
-
|
48
|
-
def full_path
|
49
|
-
display_path + display_query
|
50
|
-
end
|
51
|
-
|
52
|
-
def content_type
|
53
|
-
return nil if headers.is_a? self.class.key_not_found.class
|
54
|
-
headers['Content-Type']
|
55
|
-
end
|
56
|
-
|
57
|
-
protected
|
58
|
-
|
59
|
-
def self.key_not_found
|
60
|
-
raise NotImplementedError
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_hash_without_body
|
64
|
-
keep_keys = [:method, :path, :headers, :query]
|
65
|
-
as_json.reject{ |key, value| !keep_keys.include? key }.tap do | hash |
|
66
|
-
hash[:method] = method.upcase
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def display_path
|
71
|
-
path.empty? ? "/" : path
|
72
|
-
end
|
73
|
-
|
74
|
-
def display_query
|
75
|
-
(query.nil? || query.empty?) ? '' : "?#{Pact::Reification.from_term(query)}"
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
data/lib/pact/something_like.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'pact/symbolize_keys'
|
2
|
-
module Pact
|
3
|
-
|
4
|
-
# Specifies that the actual object should be considered a match if
|
5
|
-
# it includes the same keys, and the values of the keys are of the same class.
|
6
|
-
|
7
|
-
class SomethingLike
|
8
|
-
include SymbolizeKeys
|
9
|
-
|
10
|
-
attr_reader :contents
|
11
|
-
|
12
|
-
def initialize contents
|
13
|
-
@contents = contents
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_hash
|
17
|
-
{
|
18
|
-
:json_class => self.class.name,
|
19
|
-
:contents => contents
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
def as_json
|
24
|
-
to_hash
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_json opts = {}
|
28
|
-
as_json.to_json opts
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.json_create hash
|
32
|
-
new(symbolize_keys(hash)[:contents])
|
33
|
-
end
|
34
|
-
|
35
|
-
def eq other
|
36
|
-
self == other
|
37
|
-
end
|
38
|
-
|
39
|
-
def == other
|
40
|
-
other.is_a?(SomethingLike) && other.contents == self.contents
|
41
|
-
end
|
42
|
-
|
43
|
-
def generate
|
44
|
-
contents
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
|