hs-pact-support 1.17.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +620 -0
- data/LICENSE.txt +22 -0
- data/README.md +5 -0
- data/lib/pact/array_like.rb +49 -0
- data/lib/pact/configuration.rb +193 -0
- data/lib/pact/consumer/request.rb +27 -0
- data/lib/pact/consumer_contract/consumer_contract.rb +97 -0
- data/lib/pact/consumer_contract/file_name.rb +22 -0
- data/lib/pact/consumer_contract/headers.rb +51 -0
- data/lib/pact/consumer_contract/http_consumer_contract_parser.rb +37 -0
- data/lib/pact/consumer_contract/interaction.rb +81 -0
- data/lib/pact/consumer_contract/interaction_parser.rb +23 -0
- data/lib/pact/consumer_contract/interaction_v2_parser.rb +57 -0
- data/lib/pact/consumer_contract/interaction_v3_parser.rb +92 -0
- data/lib/pact/consumer_contract/pact_file.rb +157 -0
- data/lib/pact/consumer_contract/provider_state.rb +34 -0
- data/lib/pact/consumer_contract/query.rb +138 -0
- data/lib/pact/consumer_contract/query_hash.rb +89 -0
- data/lib/pact/consumer_contract/query_string.rb +51 -0
- data/lib/pact/consumer_contract/request.rb +83 -0
- data/lib/pact/consumer_contract/response.rb +58 -0
- data/lib/pact/consumer_contract/service_consumer.rb +28 -0
- data/lib/pact/consumer_contract/service_provider.rb +28 -0
- data/lib/pact/consumer_contract/string_with_matching_rules.rb +17 -0
- data/lib/pact/consumer_contract.rb +1 -0
- data/lib/pact/errors.rb +21 -0
- data/lib/pact/helpers.rb +60 -0
- data/lib/pact/http/authorization_header_redactor.rb +32 -0
- data/lib/pact/logging.rb +14 -0
- data/lib/pact/matchers/actual_type.rb +16 -0
- data/lib/pact/matchers/base_difference.rb +39 -0
- data/lib/pact/matchers/differ.rb +153 -0
- data/lib/pact/matchers/difference.rb +13 -0
- data/lib/pact/matchers/difference_indicator.rb +26 -0
- data/lib/pact/matchers/embedded_diff_formatter.rb +60 -0
- data/lib/pact/matchers/expected_type.rb +35 -0
- data/lib/pact/matchers/extract_diff_messages.rb +76 -0
- data/lib/pact/matchers/index_not_found.rb +15 -0
- data/lib/pact/matchers/list_diff_formatter.rb +103 -0
- data/lib/pact/matchers/matchers.rb +285 -0
- data/lib/pact/matchers/multipart_form_diff_formatter.rb +41 -0
- data/lib/pact/matchers/no_diff_at_index.rb +18 -0
- data/lib/pact/matchers/regexp_difference.rb +13 -0
- data/lib/pact/matchers/type_difference.rb +16 -0
- data/lib/pact/matchers/unexpected_index.rb +11 -0
- data/lib/pact/matchers/unexpected_key.rb +11 -0
- data/lib/pact/matchers/unix_diff_formatter.rb +157 -0
- data/lib/pact/matchers.rb +1 -0
- data/lib/pact/matching_rules/extract.rb +91 -0
- data/lib/pact/matching_rules/jsonpath.rb +58 -0
- data/lib/pact/matching_rules/merge.rb +125 -0
- data/lib/pact/matching_rules/v3/extract.rb +94 -0
- data/lib/pact/matching_rules/v3/merge.rb +141 -0
- data/lib/pact/matching_rules.rb +30 -0
- data/lib/pact/reification.rb +56 -0
- data/lib/pact/rspec.rb +51 -0
- data/lib/pact/shared/active_support_support.rb +65 -0
- data/lib/pact/shared/dsl.rb +76 -0
- data/lib/pact/shared/form_differ.rb +32 -0
- data/lib/pact/shared/jruby_support.rb +18 -0
- data/lib/pact/shared/json_differ.rb +10 -0
- data/lib/pact/shared/key_not_found.rb +15 -0
- data/lib/pact/shared/multipart_form_differ.rb +16 -0
- data/lib/pact/shared/null_expectation.rb +31 -0
- data/lib/pact/shared/request.rb +106 -0
- data/lib/pact/shared/text_differ.rb +11 -0
- data/lib/pact/something_like.rb +49 -0
- data/lib/pact/specification_version.rb +18 -0
- data/lib/pact/support/version.rb +5 -0
- data/lib/pact/support.rb +12 -0
- data/lib/pact/symbolize_keys.rb +13 -0
- data/lib/pact/term.rb +85 -0
- data/lib/tasks/pact.rake +29 -0
- metadata +327 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pact/symbolize_keys'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
class ServiceConsumer
|
5
|
+
include SymbolizeKeys
|
6
|
+
|
7
|
+
attr_accessor :name
|
8
|
+
def initialize options
|
9
|
+
@name = options[:name]
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
name
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
{name: name}
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_json options = {}
|
21
|
+
to_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_hash hash
|
25
|
+
new(symbolize_keys(hash))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pact/symbolize_keys'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
class ServiceProvider
|
5
|
+
include SymbolizeKeys
|
6
|
+
|
7
|
+
attr_accessor :name
|
8
|
+
def initialize options
|
9
|
+
@name = options[:name] || '[provider name unknown - please update the pact gem in the consumer project to the latest version and regenerate the pacts]'
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
name
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
{name: name}
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_json options = {}
|
21
|
+
to_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_hash hash
|
25
|
+
new(symbolize_keys(hash))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Pact
|
2
|
+
class StringWithMatchingRules < String
|
3
|
+
attr_reader :matching_rules
|
4
|
+
attr_reader :pact_specification_version
|
5
|
+
|
6
|
+
def initialize string, pact_specification_version, matching_rules = {}
|
7
|
+
super(string)
|
8
|
+
@matching_rules = matching_rules
|
9
|
+
@pact_specification_version = pact_specification_version
|
10
|
+
end
|
11
|
+
|
12
|
+
# How can we show the matching rules too?
|
13
|
+
def to_s
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'pact/consumer_contract/consumer_contract'
|
data/lib/pact/errors.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Pact
|
2
|
+
class Error < ::StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
# Raised when the interaction is not defined correctly
|
6
|
+
class InvalidInteractionError < Error
|
7
|
+
def initialize(interaction)
|
8
|
+
super(build_message(interaction))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def build_message(interaction)
|
14
|
+
missing_attributes = []
|
15
|
+
missing_attributes << :description unless interaction.description
|
16
|
+
missing_attributes << :request unless interaction.request
|
17
|
+
missing_attributes << :response unless interaction.response
|
18
|
+
"Missing attributes: #{missing_attributes}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/pact/helpers.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'pact/something_like'
|
2
|
+
require 'pact/term'
|
3
|
+
require 'pact/array_like'
|
4
|
+
|
5
|
+
# Protected, exposed through Pact.term and Pact.like, and included in Pact::Consumer::RSpec
|
6
|
+
|
7
|
+
module Pact
|
8
|
+
module Helpers
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def term arg1, arg2 = nil
|
15
|
+
case arg1
|
16
|
+
when Hash then Pact::Term.new(arg1)
|
17
|
+
when Regexp then Pact::Term.new(matcher: arg1, generate: arg2)
|
18
|
+
when String then Pact::Term.new(matcher: arg2, generate: arg1)
|
19
|
+
else
|
20
|
+
raise ArgumentError, "Cannot create a Pact::Term from arguments #{arg1.inspect} and #{arg2.inspect}. Please provide a Regexp and a String."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def like content
|
25
|
+
Pact::SomethingLike.new(content)
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_like content, options = {}
|
29
|
+
Pact::ArrayLike.new(content, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def like_uuid uuid
|
33
|
+
Pact::Term.new(generate: uuid, matcher: /^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$/)
|
34
|
+
end
|
35
|
+
|
36
|
+
def like_datetime datetime
|
37
|
+
Pact::Term.new(generate: datetime, matcher: /^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)$/)
|
38
|
+
end
|
39
|
+
|
40
|
+
def like_datetime_with_milliseconds datetime
|
41
|
+
Pact::Term.new(generate: datetime, matcher: /^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d{3}([+-][0-2]\d:[0-5]\d|Z)$/)
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method :like_datetime_with_miliseconds, :like_datetime_with_milliseconds
|
45
|
+
|
46
|
+
def like_date date
|
47
|
+
Pact::Term.new(generate: date, matcher: /^\d{4}-[01]\d-[0-3]\d$/)
|
48
|
+
end
|
49
|
+
|
50
|
+
def like_datetime_rfc822 datetime
|
51
|
+
Pact::Term.new(
|
52
|
+
generate: datetime,
|
53
|
+
matcher: /(?x)(Mon|Tue|Wed|Thu|Fri|Sat|Sun),
|
54
|
+
\s\d{2}\s
|
55
|
+
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
|
56
|
+
\s\d{4}\s\d{2}:\d{2}:\d{2}\s(\+|-)\d{4}/
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Http
|
5
|
+
class AuthorizationHeaderRedactor < SimpleDelegator
|
6
|
+
def puts(*args)
|
7
|
+
__getobj__().puts(*redact_args(args))
|
8
|
+
end
|
9
|
+
|
10
|
+
def print(*args)
|
11
|
+
__getobj__().puts(*redact_args(args))
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(*args)
|
15
|
+
__getobj__().send(:<<, *redact_args(args))
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :redactions
|
21
|
+
|
22
|
+
def redact_args(args)
|
23
|
+
args.collect{ | s| redact(s) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def redact(string)
|
27
|
+
return string unless string.is_a?(String)
|
28
|
+
string.gsub(/Authorization: .*\\r\\n/, "Authorization: [redacted]\\r\\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/pact/logging.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pact/matchers/expected_type'
|
2
|
+
require 'pact/matchers/actual_type'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Matchers
|
6
|
+
class BaseDifference
|
7
|
+
|
8
|
+
attr_reader :expected, :actual, :message
|
9
|
+
attr_writer :message
|
10
|
+
|
11
|
+
def initialize expected, actual, message = nil
|
12
|
+
@expected = expected
|
13
|
+
@actual = actual
|
14
|
+
@message = message
|
15
|
+
end
|
16
|
+
|
17
|
+
def any?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_json options = {}
|
26
|
+
as_json.to_json(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
as_json.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def == other
|
34
|
+
other.class == self.class && other.expected == expected && other.actual == actual
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# Ripped from RSpec::Expectations::Differ in rspec/expectations/differ.rb in rspec-expectations 2.14.3
|
2
|
+
# Thank you kindly to the original author.
|
3
|
+
# Needed to be able to turn the colour off, but can't set RSpec.configuration.color to false
|
4
|
+
# once it has been set to true due to a "if bool" at the start of the color= method
|
5
|
+
|
6
|
+
require 'diff/lcs'
|
7
|
+
require 'diff/lcs/hunk'
|
8
|
+
require 'pp'
|
9
|
+
|
10
|
+
module Pact
|
11
|
+
module Matchers
|
12
|
+
class Differ
|
13
|
+
|
14
|
+
def initialize(color = false)
|
15
|
+
@color = color
|
16
|
+
end
|
17
|
+
|
18
|
+
# This is snagged from diff/lcs/ldiff.rb (which is a commandline tool)
|
19
|
+
def diff_as_string(input_data_new, input_data_old)
|
20
|
+
output = matching_encoding("", input_data_old)
|
21
|
+
data_old = input_data_old.split(matching_encoding("\n", input_data_old)).map! { |e| e.chomp }
|
22
|
+
data_new = input_data_new.split(matching_encoding("\n", input_data_new)).map! { |e| e.chomp }
|
23
|
+
diffs = Diff::LCS.diff(data_old, data_new)
|
24
|
+
return output if diffs.empty?
|
25
|
+
oldhunk = hunk = nil
|
26
|
+
file_length_difference = 0
|
27
|
+
diffs.each do |piece|
|
28
|
+
begin
|
29
|
+
hunk = Diff::LCS::Hunk.new(
|
30
|
+
data_old, data_new, piece, context_lines, file_length_difference
|
31
|
+
)
|
32
|
+
file_length_difference = hunk.file_length_difference
|
33
|
+
next unless oldhunk
|
34
|
+
# Hunks may overlap, which is why we need to be careful when our
|
35
|
+
# diff includes lines of context. Otherwise, we might print
|
36
|
+
# redundant lines.
|
37
|
+
if (context_lines > 0) and hunk.overlaps?(oldhunk)
|
38
|
+
if hunk.respond_to?(:merge)
|
39
|
+
# diff-lcs 1.2.x
|
40
|
+
hunk.merge(oldhunk)
|
41
|
+
else
|
42
|
+
# diff-lcs 1.1.3
|
43
|
+
hunk.unshift(oldhunk)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
output << matching_encoding(oldhunk.diff(format).to_s, output)
|
47
|
+
end
|
48
|
+
ensure
|
49
|
+
oldhunk = hunk
|
50
|
+
output << matching_encoding("\n", output)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
#Handle the last remaining hunk
|
54
|
+
output << matching_encoding(oldhunk.diff(format).to_s, output)
|
55
|
+
output << matching_encoding("\n", output)
|
56
|
+
color_diff output
|
57
|
+
rescue Encoding::CompatibilityError
|
58
|
+
if input_data_new.encoding != input_data_old.encoding
|
59
|
+
"Could not produce a diff because the encoding of the actual string (#{input_data_old.encoding}) "+
|
60
|
+
"differs from the encoding of the expected string (#{input_data_new.encoding})"
|
61
|
+
else
|
62
|
+
"Could not produce a diff because of the encoding of the string (#{input_data_old.encoding})"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def diff_as_object(actual, expected)
|
67
|
+
actual_as_string = object_to_string(actual)
|
68
|
+
expected_as_string = object_to_string(expected)
|
69
|
+
if diff = diff_as_string(actual_as_string, expected_as_string)
|
70
|
+
color_diff diff
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def red(text)
|
75
|
+
return text unless @color
|
76
|
+
color(text, 31)
|
77
|
+
end
|
78
|
+
|
79
|
+
def green(text)
|
80
|
+
return text unless @color
|
81
|
+
color(text, 32)
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def format
|
87
|
+
:unified
|
88
|
+
end
|
89
|
+
|
90
|
+
def context_lines
|
91
|
+
3
|
92
|
+
end
|
93
|
+
|
94
|
+
def color(text, color_code)
|
95
|
+
"\e[#{color_code}m#{text}\e[0m"
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def blue(text)
|
100
|
+
color(text, 34)
|
101
|
+
end
|
102
|
+
|
103
|
+
def color_diff(diff)
|
104
|
+
return diff unless @color
|
105
|
+
|
106
|
+
diff.lines.map { |line|
|
107
|
+
case line[0].chr
|
108
|
+
when "+"
|
109
|
+
green line
|
110
|
+
when "-"
|
111
|
+
red line
|
112
|
+
when "@"
|
113
|
+
line[1].chr == "@" ? blue(line) : line
|
114
|
+
else
|
115
|
+
line
|
116
|
+
end
|
117
|
+
}.join
|
118
|
+
end
|
119
|
+
|
120
|
+
def object_to_string(object)
|
121
|
+
case object
|
122
|
+
when Hash
|
123
|
+
object.keys.sort_by { |k| k.to_s }.map do |key|
|
124
|
+
pp_key = PP.singleline_pp(key, "")
|
125
|
+
pp_value = PP.singleline_pp(object[key], "")
|
126
|
+
|
127
|
+
# on 1.9.3 PP seems to minimise to US-ASCII, ensure we're matching source encoding
|
128
|
+
#
|
129
|
+
# note, PP is used to ensure the ordering of the internal values of key/value e.g.
|
130
|
+
# <# a: b: c:> not <# c: a: b:>
|
131
|
+
matching_encoding("#{pp_key} => #{pp_value}", key.to_s)
|
132
|
+
end.join(",\n")
|
133
|
+
when String
|
134
|
+
object =~ /\n/ ? object : object.inspect
|
135
|
+
else
|
136
|
+
PP.pp(object,"")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if String.method_defined?(:encoding)
|
141
|
+
def matching_encoding(string, source)
|
142
|
+
string.encode(source.encoding)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
def matching_encoding(string, source)
|
146
|
+
string
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'pact/shared/active_support_support'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
class DifferenceIndicator
|
5
|
+
|
6
|
+
include ActiveSupportSupport
|
7
|
+
|
8
|
+
def == other
|
9
|
+
other.class == self.class
|
10
|
+
end
|
11
|
+
|
12
|
+
def eql? other
|
13
|
+
self == other
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_json options = {}
|
17
|
+
remove_unicode as_json.to_json(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_json options = {}
|
21
|
+
to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'pact/shared/active_support_support'
|
2
|
+
require 'rainbow'
|
3
|
+
|
4
|
+
module Pact
|
5
|
+
module Matchers
|
6
|
+
class EmbeddedDiffFormatter
|
7
|
+
|
8
|
+
include Pact::ActiveSupportSupport
|
9
|
+
|
10
|
+
EXPECTED = /"EXPECTED([A-Z_]*)":/
|
11
|
+
|
12
|
+
ACTUAL = /"ACTUAL([A-Z_]*)":/
|
13
|
+
|
14
|
+
attr_reader :diff, :colour
|
15
|
+
|
16
|
+
def initialize diff, options = {}
|
17
|
+
@diff = diff
|
18
|
+
@colour = options.fetch(:colour, false)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.call diff, options = {colour: Pact.configuration.color_enabled}
|
22
|
+
new(diff, options).call
|
23
|
+
end
|
24
|
+
|
25
|
+
def call
|
26
|
+
to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_hash
|
30
|
+
diff
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
colourise_message_if_configured fix_json_formatting(diff.to_json)
|
35
|
+
end
|
36
|
+
|
37
|
+
def colourise_message_if_configured message
|
38
|
+
if colour
|
39
|
+
colourise_message message
|
40
|
+
else
|
41
|
+
message
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def colourise_message message
|
46
|
+
message.split("\n").collect{| line | colourise(line) }.join("\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
def colourise line
|
50
|
+
line.gsub(EXPECTED){|match| coloured_key match, :red }.gsub(ACTUAL){ | match | coloured_key match, :green }
|
51
|
+
end
|
52
|
+
|
53
|
+
def coloured_key match, colour
|
54
|
+
'"' + Rainbow(match.downcase.gsub(/^"|":$/,'')).color(colour) + '":'
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'pact/matchers/difference_indicator'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
class ExpectedType < Pact::DifferenceIndicator
|
5
|
+
|
6
|
+
def initialize value
|
7
|
+
@value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def type
|
11
|
+
@value.class.name
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json options = {}
|
15
|
+
type
|
16
|
+
end
|
17
|
+
|
18
|
+
def as_json options = {}
|
19
|
+
type
|
20
|
+
end
|
21
|
+
|
22
|
+
def eq? other
|
23
|
+
self.class == other.class && other.type == type
|
24
|
+
end
|
25
|
+
|
26
|
+
def == other
|
27
|
+
eq? other
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
type
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# @api public. Used by lib/pact/provider/rspec/pact_broker_formatter.rb
|
2
|
+
module Pact
|
3
|
+
module Matchers
|
4
|
+
class ExtractDiffMessages
|
5
|
+
|
6
|
+
attr_reader :diff
|
7
|
+
|
8
|
+
def initialize diff, options = {}
|
9
|
+
@diff = diff
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.call diff, options = {}
|
13
|
+
new(diff, options).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_hash
|
17
|
+
to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
diff_messages(diff).join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_a
|
29
|
+
diff_messages(diff)
|
30
|
+
end
|
31
|
+
|
32
|
+
def diff_messages obj, path = [], messages = []
|
33
|
+
case obj
|
34
|
+
when Hash then handle_hash obj, path, messages
|
35
|
+
when Array then handle_array obj, path, messages
|
36
|
+
when BaseDifference then handle_difference obj, path, messages
|
37
|
+
when NoDiffAtIndex then nil
|
38
|
+
else
|
39
|
+
raise "Invalid diff, expected Hash, Array, NoDiffAtIndex or BaseDifference, found #{obj.class}"
|
40
|
+
end
|
41
|
+
messages
|
42
|
+
end
|
43
|
+
|
44
|
+
def handle_hash hash, path, messages
|
45
|
+
hash.each_pair do | key, value |
|
46
|
+
next_part = key =~ /\s/ ? key.inspect : key
|
47
|
+
diff_messages value, path + [".#{next_part}"], messages
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def handle_array array, path, messages
|
52
|
+
array.each_with_index do | obj, index |
|
53
|
+
diff_messages obj, path + ["[#{index}]"], messages
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def handle_difference difference, path, messages
|
58
|
+
if difference.message
|
59
|
+
message = difference.message
|
60
|
+
message = message.gsub("<path>", path_to_s(path))
|
61
|
+
message = message.gsub("<parent_path>", parent_path_to_s(path))
|
62
|
+
messages << message
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def path_to_s path
|
67
|
+
"$" + path.join
|
68
|
+
end
|
69
|
+
|
70
|
+
def parent_path_to_s path
|
71
|
+
path_to_s(path[0..-2])
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|