pact 2.0.0 → 2.0.2
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 +4 -4
- data/CHANGELOG.md +23 -0
- data/lib/pact/consumer/grpc_interaction_builder.rb +1 -3
- data/lib/pact/consumer/http_interaction_builder.rb +3 -4
- data/lib/pact/consumer/interaction_contents.rb +21 -19
- data/lib/pact/consumer/message_interaction_builder.rb +1 -3
- data/lib/pact/consumer/pact_config/http.rb +1 -2
- data/lib/pact/consumer/plugin_async_message_interaction_builder.rb +1 -3
- data/lib/pact/consumer/plugin_http_interaction_builder.rb +1 -3
- data/lib/pact/consumer/plugin_sync_message_interaction_builder.rb +1 -3
- data/lib/pact/native/logger.rb +12 -3
- data/lib/pact/provider/base_verifier.rb +28 -5
- data/lib/pact/rspec/support/webmock/webmock_helpers.rb +1 -1
- data/lib/pact/support/core_ext.rb +93 -0
- data/lib/pact/version.rb +1 -1
- data/lib/pact.rb +6 -0
- data/pact.gemspec +6 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7025748777b864b3e23efaf7ac0cbdd79f41e52300737651a2dc6f20023c44b
|
|
4
|
+
data.tar.gz: 27e691b749816d4cf746279bcb68f6fca740c1718b8213fa7d134ed8c9882e8c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 572d6976b61a36b63c46433bee409d0f45bb1fdb44139c1440f15b77d5c0ed7c6e15fd348d5ca392a1e1cf0dd0f0919d16bf54e129878e4a07bcd0dcee6fc517
|
|
7
|
+
data.tar.gz: ee765594f4b73945b8a9d2bbd1dfa199b6ac73863bd1aa066d1e795e71f87d5152c26ba057788e5c1bec2520345205137e03f8930767a570b6dc20a0c46dee45
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
<a name="v2.0.2"></a>
|
|
2
|
+
### v2.0.2 (2026-08-12)
|
|
3
|
+
|
|
4
|
+
#### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* ensure pactffi_init_with_log_level is called when instantiating pact ([efa5deb](/../../commit/efa5deb))
|
|
7
|
+
* consumer_version_selectors are silently discarded ([a0a9cf4](/../../commit/a0a9cf4))
|
|
8
|
+
* fail early if no pacts found for verification ([3546fdc](/../../commit/3546fdc))
|
|
9
|
+
|
|
10
|
+
<a name="v2.0.1"></a>
|
|
11
|
+
### v2.0.1 (2026-05-29)
|
|
12
|
+
|
|
13
|
+
#### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **example**
|
|
16
|
+
* remove combustion dependency from examples ([281b284](/../../commit/281b284))
|
|
17
|
+
|
|
18
|
+
* align core_ext polyfills more closely with active_support implementations ([f08b8ce](/../../commit/f08b8ce))
|
|
19
|
+
* correct Object#blank? and Object#present? polyfill implementations ([53580b9](/../../commit/53580b9))
|
|
20
|
+
* add deep_dup polyfill alongside blank?/present? ([b116e14](/../../commit/b116e14))
|
|
21
|
+
* remove hard requirements on active_support and webmock ([e77cd34](/../../commit/e77cd34))
|
|
22
|
+
* support scalar request and response bodies in InteractionContents ([5440ed1](/../../commit/5440ed1))
|
|
23
|
+
|
|
1
24
|
<a name="v2.0.0"></a>
|
|
2
25
|
### v2.0.0 (2026-03-18)
|
|
3
26
|
|
|
@@ -171,12 +171,10 @@ module Pact
|
|
|
171
171
|
end
|
|
172
172
|
|
|
173
173
|
def init_pact
|
|
174
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@pact_config.log_level])
|
|
174
175
|
handle = PactFfi.new_pact(@pact_config.consumer_name, @pact_config.provider_name)
|
|
175
176
|
PactFfi.with_specification(handle, PactFfi::FfiSpecificationVersion["SPECIFICATION_VERSION_V4"])
|
|
176
177
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
177
|
-
|
|
178
|
-
Pact::Native::Logger.log_to_stdout(@pact_config.log_level)
|
|
179
|
-
|
|
180
178
|
handle
|
|
181
179
|
end
|
|
182
180
|
|
|
@@ -82,7 +82,7 @@ module Pact
|
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
if body
|
|
85
|
-
PactFfi.with_body(pact_interaction, interaction_part, "application/json", format_value(InteractionContents.basic(body)))
|
|
85
|
+
PactFfi.with_body(pact_interaction, interaction_part, "application/json", format_value(InteractionContents.basic(body).value))
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
self
|
|
@@ -97,7 +97,7 @@ module Pact
|
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
if body
|
|
100
|
-
PactFfi.with_body(pact_interaction, interaction_part, "application/json", format_value(InteractionContents.basic(body)))
|
|
100
|
+
PactFfi.with_body(pact_interaction, interaction_part, "application/json", format_value(InteractionContents.basic(body).value))
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
self
|
|
@@ -139,12 +139,11 @@ module Pact
|
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
def init_pact
|
|
142
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@pact_config.log_level])
|
|
142
143
|
handle = PactFfi.new_pact(pact_config.consumer_name, pact_config.provider_name)
|
|
143
144
|
PactFfi.with_specification(handle, PactFfi::FfiSpecificationVersion["SPECIFICATION_VERSION_#{pact_config.pact_specification}"])
|
|
144
145
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
145
146
|
|
|
146
|
-
Pact::Native::Logger.log_to_stdout(pact_config.log_level)
|
|
147
|
-
|
|
148
147
|
handle
|
|
149
148
|
end
|
|
150
149
|
|
|
@@ -17,36 +17,38 @@ module Pact
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def initialize(contents_hash, format)
|
|
20
|
-
init_hash(contents_hash, format)
|
|
20
|
+
serialized = init_hash(contents_hash, format)
|
|
21
|
+
# A scalar body (plain string, integer, etc.) serializes to a non-Hash
|
|
22
|
+
# value that cannot be merged pair by pair; expose it via #value instead.
|
|
23
|
+
if serialized.is_a?(Hash)
|
|
24
|
+
serialized.each_pair { |k, v| self[k] = v }
|
|
25
|
+
else
|
|
26
|
+
@value = serialized
|
|
27
|
+
end
|
|
21
28
|
@format = format
|
|
22
29
|
end
|
|
23
30
|
|
|
31
|
+
def value
|
|
32
|
+
defined?(@value) ? @value : self
|
|
33
|
+
end
|
|
34
|
+
|
|
24
35
|
private
|
|
25
36
|
|
|
26
37
|
def serialize(hash, format)
|
|
27
38
|
# serialize recursively
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if hash.is_a?(Pact::Matchers::Base)
|
|
31
|
-
return hash.as_basic if format == :basic
|
|
32
|
-
return hash.as_plugin if format == :plugin
|
|
33
|
-
end
|
|
34
|
-
if hash.is_a?(Pact::Generators::Base)
|
|
39
|
+
if hash.is_a?(Pact::Matchers::Base) || hash.is_a?(Pact::Generators::Base)
|
|
35
40
|
return hash.as_basic if format == :basic
|
|
36
41
|
return hash.as_plugin if format == :plugin
|
|
37
42
|
end
|
|
43
|
+
|
|
44
|
+
return hash.map { |value| serialize(value, format) } if hash.is_a?(Array)
|
|
45
|
+
|
|
46
|
+
# A value that is not a collection or a matcher/generator has nothing to
|
|
47
|
+
# recurse into, so return it unchanged (string, integer, boolean, nil, ...).
|
|
48
|
+
return hash unless hash.is_a?(Hash)
|
|
49
|
+
|
|
38
50
|
hash.each_pair do |key, value|
|
|
39
|
-
|
|
40
|
-
next hash[key] = value.map { |v| serialize(v, format) } if value.is_a?(Array)
|
|
41
|
-
|
|
42
|
-
if value.is_a?(Pact::Matchers::Base)
|
|
43
|
-
hash[key] = value.as_basic if format == :basic
|
|
44
|
-
hash[key] = value.as_plugin if format == :plugin
|
|
45
|
-
end
|
|
46
|
-
if value.is_a?(Pact::Generators::Base)
|
|
47
|
-
hash[key] = value.as_basic if format == :basic
|
|
48
|
-
hash[key] = value.as_plugin if format == :plugin
|
|
49
|
-
end
|
|
51
|
+
hash[key] = serialize(value, format)
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
hash
|
|
@@ -172,12 +172,10 @@ module Pact
|
|
|
172
172
|
end
|
|
173
173
|
|
|
174
174
|
def init_pact
|
|
175
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@pact_config.log_level])
|
|
175
176
|
handle = PactFfi::MessageConsumer.new_message_pact(@pact_config.consumer_name, @pact_config.provider_name)
|
|
176
177
|
PactFfi.with_specification(handle, PactFfi::FfiSpecificationVersion["SPECIFICATION_VERSION_V4"])
|
|
177
178
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
178
|
-
|
|
179
|
-
Pact::Native::Logger.log_to_stdout(@pact_config.log_level)
|
|
180
|
-
|
|
181
179
|
handle
|
|
182
180
|
end
|
|
183
181
|
|
|
@@ -39,12 +39,11 @@ module Pact
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def init_pact
|
|
42
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@log_level])
|
|
42
43
|
handle = PactFfi.new_pact(consumer_name, provider_name)
|
|
43
44
|
PactFfi.with_specification(handle, @pact_specification)
|
|
44
45
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
45
46
|
|
|
46
|
-
Pact::Native::Logger.log_to_stdout(@log_level)
|
|
47
|
-
|
|
48
47
|
handle
|
|
49
48
|
end
|
|
50
49
|
end
|
|
@@ -148,12 +148,10 @@ module Pact
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def init_pact
|
|
151
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@pact_config.log_level])
|
|
151
152
|
handle = PactFfi.new_pact(@pact_config.consumer_name, @pact_config.provider_name)
|
|
152
153
|
PactFfi.with_specification(handle, PactFfi::FfiSpecificationVersion["SPECIFICATION_VERSION_V4"])
|
|
153
154
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
154
|
-
|
|
155
|
-
Pact::Native::Logger.log_to_stdout(@pact_config.log_level)
|
|
156
|
-
|
|
157
155
|
handle
|
|
158
156
|
end
|
|
159
157
|
|
|
@@ -170,12 +170,10 @@ module Pact
|
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
def init_pact
|
|
173
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@pact_config.log_level])
|
|
173
174
|
handle = PactFfi.new_pact(@pact_config.consumer_name, @pact_config.provider_name)
|
|
174
175
|
PactFfi.with_specification(handle, PactFfi::FfiSpecificationVersion["SPECIFICATION_VERSION_V4"])
|
|
175
176
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
176
|
-
|
|
177
|
-
Pact::Native::Logger.log_to_stdout(@pact_config.log_level)
|
|
178
|
-
|
|
179
177
|
handle
|
|
180
178
|
end
|
|
181
179
|
|
|
@@ -157,12 +157,10 @@ module Pact
|
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
def init_pact
|
|
160
|
+
PactFfi.init_with_log_level(Native::Logger::LOG_LEVELS[@pact_config.log_level])
|
|
160
161
|
handle = PactFfi.new_pact(@pact_config.consumer_name, @pact_config.provider_name)
|
|
161
162
|
PactFfi.with_specification(handle, PactFfi::FfiSpecificationVersion["SPECIFICATION_VERSION_V4"])
|
|
162
163
|
PactFfi.with_pact_metadata(handle, "pact-ruby", "pact-ffi", PactFfi.version)
|
|
163
|
-
|
|
164
|
-
Pact::Native::Logger.log_to_stdout(@pact_config.log_level)
|
|
165
|
-
|
|
166
164
|
handle
|
|
167
165
|
end
|
|
168
166
|
|
data/lib/pact/native/logger.rb
CHANGED
|
@@ -5,7 +5,7 @@ require 'pact/ffi/logger'
|
|
|
5
5
|
module Pact
|
|
6
6
|
module Native
|
|
7
7
|
module Logger
|
|
8
|
-
|
|
8
|
+
LOG_FILTERS = {
|
|
9
9
|
off: PactFfi::FfiLogLevelFilter['LOG_LEVEL_OFF'],
|
|
10
10
|
error: PactFfi::FfiLogLevelFilter['LOG_LEVEL_ERROR'],
|
|
11
11
|
warn: PactFfi::FfiLogLevelFilter['LOG_LEVEL_WARN'],
|
|
@@ -14,10 +14,19 @@ module Pact
|
|
|
14
14
|
trace: PactFfi::FfiLogLevelFilter['LOG_LEVEL_TRACE']
|
|
15
15
|
}.freeze
|
|
16
16
|
|
|
17
|
+
LOG_LEVELS = {
|
|
18
|
+
off: PactFfi::FfiLogLevel['LOG_LEVEL_OFF'],
|
|
19
|
+
error: PactFfi::FfiLogLevel['LOG_LEVEL_ERROR'],
|
|
20
|
+
warn: PactFfi::FfiLogLevel['LOG_LEVEL_WARN'],
|
|
21
|
+
info: PactFfi::FfiLogLevel['LOG_LEVEL_INFO'],
|
|
22
|
+
debug: PactFfi::FfiLogLevel['LOG_LEVEL_DEBUG'],
|
|
23
|
+
trace: PactFfi::FfiLogLevel['LOG_LEVEL_TRACE']
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
17
26
|
def self.log_to_stdout(log_level)
|
|
18
|
-
raise 'invalid log level for PactFfi::FfiLogLevelFilter' unless
|
|
27
|
+
raise 'invalid log level for PactFfi::FfiLogLevelFilter' unless LOG_FILTERS.key?(log_level)
|
|
19
28
|
|
|
20
|
-
PactFfi::Logger.log_to_stdout(
|
|
29
|
+
PactFfi::Logger.log_to_stdout(LOG_FILTERS[log_level]) unless log_level == :off
|
|
21
30
|
end
|
|
22
31
|
end
|
|
23
32
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'pact/ffi/verifier'
|
|
4
4
|
require 'pact/native/logger'
|
|
5
5
|
require 'pact/native/blocking_verifier'
|
|
6
|
+
require 'json'
|
|
6
7
|
|
|
7
8
|
module Pact
|
|
8
9
|
module Provider
|
|
@@ -175,7 +176,7 @@ module Pact
|
|
|
175
176
|
PactFfi::Verifier.set_provider_info(pact_handle, @pact_config.provider_name, '', '', 0, '')
|
|
176
177
|
end
|
|
177
178
|
|
|
178
|
-
def add_provider_transport(
|
|
179
|
+
def add_provider_transport(_pact_handle)
|
|
179
180
|
raise PactImplementationRequired, 'Implement #add_provider_transport in a subclass'
|
|
180
181
|
end
|
|
181
182
|
|
|
@@ -200,6 +201,7 @@ module Pact
|
|
|
200
201
|
if @pact_config.pact_broker_proxy_url.blank? && @pact_config.pact_uri.blank?
|
|
201
202
|
path = @pact_config.pact_dir || (defined?(Rails) ? Rails.root.join('pacts').to_s : 'pacts')
|
|
202
203
|
logger.info("[verifier] pact broker url or pact uri is not set, using directory #{path} as a verification source") # rubocop:disable Layout/LineLength
|
|
204
|
+
ensure_provider_has_matching_pacts!(path)
|
|
203
205
|
return PactFfi::Verifier.add_directory_source(handle, path)
|
|
204
206
|
end
|
|
205
207
|
|
|
@@ -213,15 +215,15 @@ module Pact
|
|
|
213
215
|
PactFfi::Verifier.add_file_source(handle, @pact_config.pact_uri)
|
|
214
216
|
end
|
|
215
217
|
else
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
filters =
|
|
218
|
+
selectors = consumer_selectors || []
|
|
219
|
+
logger.info("[verifier] using pact broker url #{@pact_config.broker_url} with consumer selectors: #{JSON.dump(selectors)} as a verification source") # rubocop:disable Layout/LineLength
|
|
220
|
+
filters = selectors.map do |selector|
|
|
219
221
|
FFI::MemoryPointer.from_string(JSON.dump(selector).to_s)
|
|
220
222
|
end
|
|
221
223
|
filters_ptr = FFI::MemoryPointer.new(:pointer, filters.size + 1)
|
|
222
224
|
filters_ptr.write_array_of_pointer(filters)
|
|
223
225
|
PactFfi::Verifier.broker_source_with_selectors(handle, @pact_config.pact_broker_proxy_url,
|
|
224
|
-
@pact_config.broker_username, @pact_config.broker_password, @pact_config.broker_token, bool_to_int(@pact_config.enable_pending), @pact_config.include_wip_pacts_since, c_provider_version_tags, c_provider_version_tags_size, @pact_config.provider_version_branch, filters_ptr,
|
|
226
|
+
@pact_config.broker_username, @pact_config.broker_password, @pact_config.broker_token, bool_to_int(@pact_config.enable_pending), @pact_config.include_wip_pacts_since, c_provider_version_tags, c_provider_version_tags_size, @pact_config.provider_version_branch, filters_ptr, selectors.size, c_consumer_version_tags, c_consumer_version_tags_size) # rubocop:disable Layout/LineLength
|
|
225
227
|
end
|
|
226
228
|
end
|
|
227
229
|
|
|
@@ -254,6 +256,27 @@ module Pact
|
|
|
254
256
|
|
|
255
257
|
[DEFAULT_CONSUMER_SELECTORS]
|
|
256
258
|
end
|
|
259
|
+
|
|
260
|
+
def ensure_provider_has_matching_pacts!(path)
|
|
261
|
+
return unless @pact_config.fail_if_no_pacts_found
|
|
262
|
+
|
|
263
|
+
pact_paths = Dir.glob(File.join(path, '**', '*.json'))
|
|
264
|
+
raise VerifierError.new("No pact files found in #{path}") if pact_paths.empty?
|
|
265
|
+
|
|
266
|
+
return if pact_paths.any? { |p| pact_file_provider_name(p) == @pact_config.provider_name }
|
|
267
|
+
|
|
268
|
+
providers = pact_paths.map { |p| pact_file_provider_name(p) }.compact.uniq.sort
|
|
269
|
+
raise VerifierError.new(
|
|
270
|
+
"No pacts found for provider \"#{@pact_config.provider_name}\" in directory #{path}. " \
|
|
271
|
+
"Found providers: #{providers.join(', ')}"
|
|
272
|
+
)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def pact_file_provider_name(path)
|
|
276
|
+
JSON.parse(File.read(path)).dig('provider', 'name')
|
|
277
|
+
rescue StandardError
|
|
278
|
+
nil
|
|
279
|
+
end
|
|
257
280
|
end
|
|
258
281
|
end
|
|
259
282
|
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Minimal active_support polyfills for blank?/present? and deep_dup.
|
|
4
|
+
# Each block is skipped entirely if the method is already defined
|
|
5
|
+
# (e.g. active_support is loaded by the host application).
|
|
6
|
+
|
|
7
|
+
unless Object.method_defined?(:blank?)
|
|
8
|
+
class NilClass
|
|
9
|
+
def blank? = true
|
|
10
|
+
def present? = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class FalseClass
|
|
14
|
+
def blank? = true
|
|
15
|
+
def present? = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class TrueClass
|
|
19
|
+
def blank? = false
|
|
20
|
+
def present? = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class String
|
|
24
|
+
BLANK_RE = /\A[[:space:]]*\z/
|
|
25
|
+
|
|
26
|
+
def blank?
|
|
27
|
+
empty? || BLANK_RE.match?(self)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def present? = !blank?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class Symbol
|
|
34
|
+
alias_method :blank?, :empty?
|
|
35
|
+
def present? = !blank?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Array
|
|
39
|
+
alias_method :blank?, :empty?
|
|
40
|
+
def present? = !empty?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class Hash
|
|
44
|
+
alias_method :blank?, :empty?
|
|
45
|
+
def present? = !empty?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Object
|
|
49
|
+
def blank? = respond_to?(:empty?) ? !!empty? : false
|
|
50
|
+
def present? = !blank?
|
|
51
|
+
|
|
52
|
+
def presence
|
|
53
|
+
self if present?
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
unless Object.method_defined?(:deep_dup)
|
|
59
|
+
class Object
|
|
60
|
+
def deep_dup
|
|
61
|
+
dup
|
|
62
|
+
rescue TypeError
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class Array
|
|
68
|
+
def deep_dup
|
|
69
|
+
map(&:deep_dup)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class Hash
|
|
74
|
+
def deep_dup
|
|
75
|
+
hash = dup
|
|
76
|
+
each_pair do |key, value|
|
|
77
|
+
if ::String === key || ::Symbol === key
|
|
78
|
+
hash[key] = value.deep_dup
|
|
79
|
+
else
|
|
80
|
+
hash.delete(key)
|
|
81
|
+
hash[key.deep_dup] = value.deep_dup
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
hash
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class Module
|
|
89
|
+
def deep_dup
|
|
90
|
+
name.nil? ? super : self
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/pact/version.rb
CHANGED
data/lib/pact.rb
CHANGED
|
@@ -5,6 +5,11 @@ require 'pact/ffi'
|
|
|
5
5
|
|
|
6
6
|
require 'pact/railtie' if defined?(Rails::Railtie)
|
|
7
7
|
|
|
8
|
+
# Load core_ext polyfills (blank?/present?, deep_dup) before Zeitwerk eager-loads
|
|
9
|
+
# the rest of the gem. Each polyfill is skipped if already defined by active_support
|
|
10
|
+
# or any other library loaded by the host application.
|
|
11
|
+
require 'pact/support/core_ext'
|
|
12
|
+
|
|
8
13
|
module Pact
|
|
9
14
|
class Error < StandardError; end
|
|
10
15
|
|
|
@@ -41,6 +46,7 @@ loader.tag = 'pact'
|
|
|
41
46
|
loader.ignore("#{__dir__}/pact/version.rb")
|
|
42
47
|
loader.ignore("#{__dir__}/pact/rspec.rb")
|
|
43
48
|
loader.ignore("#{__dir__}/pact/rspec")
|
|
49
|
+
loader.ignore("#{__dir__}/pact/support/core_ext.rb")
|
|
44
50
|
loader.ignore("#{__dir__}/pact/railtie.rb") unless defined?(Rails::Railtie)
|
|
45
51
|
|
|
46
52
|
loader.setup
|
data/pact.gemspec
CHANGED
|
@@ -27,6 +27,12 @@ Gem::Specification.new do |gem|
|
|
|
27
27
|
'documentation_uri' => 'https://github.com/pact-foundation/pact-ruby/blob/master/README.md'
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
# Optional runtime dependencies (not required by pact itself):
|
|
31
|
+
# active_support — if already loaded, its blank?/present? take precedence over
|
|
32
|
+
# pact's built-in polyfill (lib/pact/support/blank.rb).
|
|
33
|
+
# webmock — only needed for WebMock integration via WebmockHelpers.
|
|
34
|
+
# Require it yourself before using that helper.
|
|
35
|
+
|
|
30
36
|
# Core dependencies (code loading)
|
|
31
37
|
gem.add_dependency 'zeitwerk', '~> 2.3'
|
|
32
38
|
# For Pact support via Pact Rust Core
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pact
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Fraser
|
|
@@ -487,6 +487,7 @@ files:
|
|
|
487
487
|
- lib/pact/rspec/support/pact_provider_helpers.rb
|
|
488
488
|
- lib/pact/rspec/support/waterdrop/pact_waterdrop_client.rb
|
|
489
489
|
- lib/pact/rspec/support/webmock/webmock_helpers.rb
|
|
490
|
+
- lib/pact/support/core_ext.rb
|
|
490
491
|
- lib/pact/tasks/pact.rake
|
|
491
492
|
- lib/pact/version.rb
|
|
492
493
|
- pact.gemspec
|
|
@@ -512,7 +513,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
512
513
|
- !ruby/object:Gem::Version
|
|
513
514
|
version: '0'
|
|
514
515
|
requirements: []
|
|
515
|
-
rubygems_version: 4.0.
|
|
516
|
+
rubygems_version: 4.0.18
|
|
516
517
|
specification_version: 4
|
|
517
518
|
summary: Enables consumer driven contract testing, providing a mock service and DSL
|
|
518
519
|
for the consumer project, and interaction playback and verification for the service
|