hs-pact-support 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|