pact 1.64.0 → 1.67.5

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +130 -0
  3. data/lib/pact/cli/run_pact_verification.rb +0 -1
  4. data/lib/pact/consumer/consumer_contract_builder.rb +1 -1
  5. data/lib/pact/hal/http_client.rb +19 -1
  6. data/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb +19 -8
  7. data/lib/pact/provider/configuration/message_provider_dsl.rb +4 -0
  8. data/lib/pact/provider/configuration/pact_verification_from_broker.rb +8 -2
  9. data/lib/pact/provider/help/console_text.rb +4 -8
  10. data/lib/pact/provider/help/prompt_text.rb +2 -4
  11. data/lib/pact/provider/matchers/messages.rb +3 -5
  12. data/lib/pact/provider/print_missing_provider_states.rb +3 -5
  13. data/lib/pact/provider/request.rb +25 -5
  14. data/lib/pact/provider/rspec/formatter_rspec_2.rb +1 -3
  15. data/lib/pact/provider/rspec/formatter_rspec_3.rb +1 -3
  16. data/lib/pact/provider/rspec/pact_broker_formatter.rb +2 -2
  17. data/lib/pact/provider/rspec.rb +5 -3
  18. data/lib/pact/provider/test_methods.rb +9 -3
  19. data/lib/pact/v2/configuration.rb +23 -0
  20. data/lib/pact/v2/consumer/grpc_interaction_builder.rb +194 -0
  21. data/lib/pact/v2/consumer/http_interaction_builder.rb +162 -0
  22. data/lib/pact/v2/consumer/interaction_contents.rb +62 -0
  23. data/lib/pact/v2/consumer/message_interaction_builder.rb +288 -0
  24. data/lib/pact/v2/consumer/mock_server.rb +108 -0
  25. data/lib/pact/v2/consumer/pact_config/base.rb +24 -0
  26. data/lib/pact/v2/consumer/pact_config/grpc.rb +26 -0
  27. data/lib/pact/v2/consumer/pact_config/http.rb +55 -0
  28. data/lib/pact/v2/consumer/pact_config/message.rb +17 -0
  29. data/lib/pact/v2/consumer/pact_config/plugin_async_message.rb +26 -0
  30. data/lib/pact/v2/consumer/pact_config/plugin_http.rb +26 -0
  31. data/lib/pact/v2/consumer/pact_config/plugin_sync_message.rb +26 -0
  32. data/lib/pact/v2/consumer/pact_config.rb +30 -0
  33. data/lib/pact/v2/consumer/plugin_async_message_interaction_builder.rb +171 -0
  34. data/lib/pact/v2/consumer/plugin_http_interaction_builder.rb +201 -0
  35. data/lib/pact/v2/consumer/plugin_sync_message_interaction_builder.rb +180 -0
  36. data/lib/pact/v2/consumer.rb +8 -0
  37. data/lib/pact/v2/generators/base.rb +287 -0
  38. data/lib/pact/v2/generators.rb +49 -0
  39. data/lib/pact/v2/matchers/base.rb +74 -0
  40. data/lib/pact/v2/matchers/v1/equality.rb +19 -0
  41. data/lib/pact/v2/matchers/v2/regex.rb +19 -0
  42. data/lib/pact/v2/matchers/v2/type.rb +17 -0
  43. data/lib/pact/v2/matchers/v3/boolean.rb +17 -0
  44. data/lib/pact/v2/matchers/v3/content_type.rb +32 -0
  45. data/lib/pact/v2/matchers/v3/date.rb +18 -0
  46. data/lib/pact/v2/matchers/v3/date_time.rb +18 -0
  47. data/lib/pact/v2/matchers/v3/decimal.rb +17 -0
  48. data/lib/pact/v2/matchers/v3/each.rb +42 -0
  49. data/lib/pact/v2/matchers/v3/include.rb +17 -0
  50. data/lib/pact/v2/matchers/v3/integer.rb +17 -0
  51. data/lib/pact/v2/matchers/v3/null.rb +16 -0
  52. data/lib/pact/v2/matchers/v3/number.rb +17 -0
  53. data/lib/pact/v2/matchers/v3/semver.rb +23 -0
  54. data/lib/pact/v2/matchers/v3/time.rb +18 -0
  55. data/lib/pact/v2/matchers/v3/values.rb +16 -0
  56. data/lib/pact/v2/matchers/v4/each_key.rb +26 -0
  57. data/lib/pact/v2/matchers/v4/each_key_value.rb +32 -0
  58. data/lib/pact/v2/matchers/v4/each_value.rb +33 -0
  59. data/lib/pact/v2/matchers/v4/not_empty.rb +24 -0
  60. data/lib/pact/v2/matchers/v4/status_code.rb +17 -0
  61. data/lib/pact/v2/matchers.rb +110 -0
  62. data/lib/pact/v2/native/blocking_verifier.rb +17 -0
  63. data/lib/pact/v2/native/logger.rb +25 -0
  64. data/lib/pact/v2/provider/async_message_verifier.rb +28 -0
  65. data/lib/pact/v2/provider/base_verifier.rb +242 -0
  66. data/lib/pact/v2/provider/grpc_verifier.rb +38 -0
  67. data/lib/pact/v2/provider/gruf_server.rb +75 -0
  68. data/lib/pact/v2/provider/http_server.rb +79 -0
  69. data/lib/pact/v2/provider/http_verifier.rb +43 -0
  70. data/lib/pact/v2/provider/message_provider_servlet.rb +79 -0
  71. data/lib/pact/v2/provider/mixed_verifier.rb +22 -0
  72. data/lib/pact/v2/provider/pact_broker_proxy.rb +66 -0
  73. data/lib/pact/v2/provider/pact_broker_proxy_runner.rb +80 -0
  74. data/lib/pact/v2/provider/pact_config/async.rb +29 -0
  75. data/lib/pact/v2/provider/pact_config/base.rb +103 -0
  76. data/lib/pact/v2/provider/pact_config/grpc.rb +26 -0
  77. data/lib/pact/v2/provider/pact_config/http.rb +27 -0
  78. data/lib/pact/v2/provider/pact_config/mixed.rb +40 -0
  79. data/lib/pact/v2/provider/pact_config.rb +26 -0
  80. data/lib/pact/v2/provider/provider_server_runner.rb +92 -0
  81. data/lib/pact/v2/provider/provider_state_configuration.rb +32 -0
  82. data/lib/pact/v2/provider/provider_state_servlet.rb +86 -0
  83. data/lib/pact/v2/provider.rb +8 -0
  84. data/lib/pact/v2/railtie.rb +13 -0
  85. data/lib/pact/v2/rspec/support/pact_consumer_helpers.rb +93 -0
  86. data/lib/pact/v2/rspec/support/pact_message_helpers.rb +42 -0
  87. data/lib/pact/v2/rspec/support/pact_provider_helpers.rb +129 -0
  88. data/lib/pact/v2/rspec/support/waterdrop/pact_waterdrop_client.rb +27 -0
  89. data/lib/pact/v2/rspec/support/webmock/webmock_helpers.rb +30 -0
  90. data/lib/pact/v2/rspec.rb +17 -0
  91. data/lib/pact/v2/tasks/pact.rake +13 -0
  92. data/lib/pact/v2.rb +71 -0
  93. data/lib/pact/version.rb +1 -1
  94. data/lib/pact.rb +6 -0
  95. data/lib/tasks/pact.rake +2 -2
  96. data/pact.gemspec +57 -9
  97. metadata +420 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 174a9376cd442f1edd545cd006e1b15f07804077bb91060678e224d1717c6a5b
4
- data.tar.gz: 4b5d1a84949fbad2dedeb1233626ef649ac4352840a204ea20c6496d3c0c0493
3
+ metadata.gz: 8be91a33981b95189c08f545d3746c76f2f2ad8642777f753cc3b414233986de
4
+ data.tar.gz: 1bc7d8a6e8a08c47b79e73f68e0caed9585a0eafb0bc316a4e589f2b3f9028a3
5
5
  SHA512:
6
- metadata.gz: 957b95b85b59906f1a59bb23fe2b85674c1574171a0880a508df9c6413bc7fe3f2b54fc3fe766eab3fdd8f18e68eaabf4efda43da50df01c66ebe2e9a0f19111
7
- data.tar.gz: 6a34522651d931773d8ee92565ffd5173fd3f2cd99ba1211d25985da499b62d993a5b62b87257afb11a759cf691aa7702efe9e1773d11165794980d1301138e1
6
+ metadata.gz: a73f8cf2aa2956f7e0c7ed2dc8ab35fefbf1b7a2b0ab88d21bb3936a4761ae60d2fd622c4f2a767f2b6e75837556aeb055011667def9a90b8fbe1f9df74bf0f9
7
+ data.tar.gz: e27d62a8822b43ded6ccd48b926c2833292617834c7c2b8dda45d93a26a769d1093909d87921f8c15962445d3ef2012b1df2d5417ed7a07259a4275862c9f4b9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,133 @@
1
+ <a name="v1.67.5"></a>
2
+ ### v1.67.5 (2026-02-13)
3
+
4
+ #### Bug Fixes
5
+
6
+ * retry HTTP requests on 5xx status codes (502, 503, 504) ([2174a31](/../../commit/2174a31))
7
+
8
+ <a name="v1.67.4"></a>
9
+ ### v1.67.4 (2026-02-09)
10
+
11
+ #### Bug Fixes
12
+
13
+ * suppress v2 load warning in v1 mode ([4f7bab2](/../../commit/4f7bab2))
14
+ * pact-v2 verifier - pact_proxy_port was not honoured ([6a60bae](/../../commit/6a60bae))
15
+
16
+ <a name="v1.67.3"></a>
17
+ ### v1.67.3 (2025-11-06)
18
+
19
+ #### Bug Fixes
20
+
21
+ * ensure message consumers with plugins cleanup processes ([8df23e6](/../../commit/8df23e6))
22
+
23
+ <a name="v1.67.2"></a>
24
+ ### v1.67.2 (2025-10-22)
25
+
26
+ #### Bug Fixes
27
+
28
+ * **v2**
29
+ * allow configurable loggers in verifier ([9fad7fa](/../../commit/9fad7fa))
30
+
31
+ <a name="v1.67.1"></a>
32
+ ### v1.67.1 (2025-10-22)
33
+
34
+ #### Bug Fixes
35
+
36
+ * **deps**
37
+ * make pact-ffi optional in v1 releases for pact-ruby-standalone consumption ([e3cd0d6](/../../commit/e3cd0d6))
38
+
39
+ <a name="v1.67.0"></a>
40
+ ### v1.67.0 (2025-10-16)
41
+
42
+ #### Features
43
+
44
+ * add support for generate_from_provider_state ([4ff7812](/../../commit/4ff7812))
45
+ * add pact-ruby v2 generators ([4db935b](/../../commit/4db935b))
46
+ * add pact plugin consumer interfaces for http/async/sync messages ([ca19f86](/../../commit/ca19f86))
47
+ * add more matchers ([ccb82b9](/../../commit/ccb82b9))
48
+ * load pact/v2 into namespace ([4ac42ec](/../../commit/4ac42ec))
49
+ * add pact v2 interface ([4595015](/../../commit/4595015))
50
+
51
+ #### Bug Fixes
52
+
53
+ * ensure we always print mismatchs in consumer tests for better dx ([f9cb106](/../../commit/f9cb106))
54
+ * json load diff regression downstream, relax restrictions ([481eab9](/../../commit/481eab9))
55
+
56
+ <a name="v1.66.2"></a>
57
+ ### v1.66.2 (2025-10-03)
58
+
59
+ #### Bug Fixes
60
+
61
+ * **spec**
62
+ * update rspec keyword vs arg changes https://github.com/rspec/rspec-mocks/pull/1473 ([c1c17fc](/../../commit/c1c17fc))
63
+
64
+ * correct generators import and update specs ([d025342](/../../commit/d025342))
65
+ * example/animal-service/Gemfile to reduce vulnerabilities ([4dfb3f5](/../../commit/4dfb3f5))
66
+ * example/animal-service/Gemfile to reduce vulnerabilities ([3d8fa31](/../../commit/3d8fa31))
67
+ * example/zoo-app/Gemfile to reduce vulnerabilities ([5ff8945](/../../commit/5ff8945))
68
+
69
+ <a name="v1.66.1"></a>
70
+ ### v1.66.1 (2025-01-20)
71
+
72
+ #### Bug Fixes
73
+
74
+ * HTTP_HOST headers for sinatra 4.x ([173bfb7](/../../commit/173bfb7))
75
+
76
+ <a name="v1.66.0"></a>
77
+ ### v1.66.0 (2024-11-29)
78
+
79
+ #### Features
80
+
81
+ * **generators**
82
+ * Add more generators as per spec ([f55adf1](/../../commit/f55adf1))
83
+ * Pass context and add ProviderState generator ([7a1cf3b](/../../commit/7a1cf3b))
84
+
85
+ #### Bug Fixes
86
+
87
+ * add HTTPS_HOST header if invoking a Sinatra app ([ed44189](/../../commit/ed44189))
88
+ * example/animal-service/Gemfile to reduce vulnerabilities ([981ebee](/../../commit/981ebee))
89
+
90
+ <a name="v1.65.3"></a>
91
+ ### v1.65.3 (2024-10-23)
92
+
93
+ #### Bug Fixes
94
+
95
+ * **test**
96
+ * explicitly require ostruct as non stdlib in ruby 3.5.x ([c9a8525](/../../commit/c9a8525))
97
+
98
+ <a name="v1.65.2"></a>
99
+ ### v1.65.2 (2024-09-26)
100
+
101
+ <a name="v1.65.1"></a>
102
+ ### v1.65.1 (2024-08-08)
103
+
104
+ #### Bug Fixes
105
+
106
+ * set color codes even on dumb terms (prev behaviour) ([4f01bc9](/../../commit/4f01bc9))
107
+ * use .empty? in handling_no_pacts_found ([43bce74](/../../commit/43bce74))
108
+
109
+ <a name="v1.65.0"></a>
110
+ ### v1.65.0 (2024-08-06)
111
+
112
+ #### Features
113
+
114
+ * support app_version_branch in MessageProviderDSL ([1653128](/../../commit/1653128))
115
+ * allow setting fail_if_no_pacts_found in honours_pacts_from_pact_broker ([f0f142e](/../../commit/f0f142e))
116
+
117
+ #### Bug Fixes
118
+
119
+ * handle case in no_pacts_found - undefined method empty? for nil ([0145d2d](/../../commit/0145d2d))
120
+ * remove unused ConsumerContractBuilder contract_details accessor ([fb5488e](/../../commit/fb5488e))
121
+ * example/animal-service/Gemfile to reduce vulnerabilities ([2bbefe2](/../../commit/2bbefe2))
122
+ * example/zoo-app/Gemfile to reduce vulnerabilities ([e10f914](/../../commit/e10f914))
123
+ * example/animal-service/Gemfile to reduce vulnerabilities ([7560918](/../../commit/7560918))
124
+ * example/zoo-app/Gemfile to reduce vulnerabilities ([b4cbe85](/../../commit/b4cbe85))
125
+ * example/animal-service/Gemfile to reduce vulnerabilities ([4028087](/../../commit/4028087))
126
+ * ConsumerContractBuilder exposing incorrect field ([c805c3e](/../../commit/c805c3e))
127
+
128
+ * **test**
129
+ * alias Rack/Rackup WEBrick handler in x509 test for backwards compat ([cc77498](/../../commit/cc77498))
130
+
1
131
  <a name="v1.64.0"></a>
2
132
  ### v1.64.0 (2023-11-09)
3
133
 
@@ -72,7 +72,6 @@ module Pact
72
72
 
73
73
  def run_with_configured_pacts_from_pact_helper
74
74
  pact_urls = Pact.provider_world.pact_urls
75
- raise "Please configure a pact to verify" if pact_urls.empty?
76
75
  Pact::Provider::PactSpecRunner.new(pact_urls, pact_spec_options).run
77
76
  end
78
77
 
@@ -11,7 +11,7 @@ module Pact
11
11
 
12
12
  include Pact::Logging
13
13
 
14
- attr_reader :consumer_contract, :mock_service_base_url
14
+ attr_reader :mock_service_base_url
15
15
 
16
16
  def initialize(attributes)
17
17
  @interaction_builder = nil
@@ -6,6 +6,18 @@ require 'openssl'
6
6
 
7
7
  module Pact
8
8
  module Hal
9
+ class RetriableHttpStatusError < StandardError
10
+ RETRIABLE_STATUS_CODES = [502, 503, 504].freeze
11
+
12
+ attr_reader :status_code, :response_body
13
+
14
+ def initialize status_code, response_body
15
+ @status_code = status_code
16
+ @response_body = response_body
17
+ super("HTTP #{status_code} error: #{response_body}")
18
+ end
19
+ end
20
+
9
21
  class HttpClient
10
22
  attr_accessor :username, :password, :verbose, :token
11
23
 
@@ -65,9 +77,15 @@ module Pact
65
77
  end
66
78
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
67
79
  end
68
- http.start do |http|
80
+ result = http.start do |http|
69
81
  http.request request
70
82
  end
83
+
84
+ # Raise error on specific 5xx status codes to trigger retry
85
+ status_code = result.code.to_i
86
+ raise RetriableHttpStatusError.new(status_code, result.body) if RetriableHttpStatusError::RETRIABLE_STATUS_CODES.include?(status_code)
87
+
88
+ result
71
89
  end
72
90
  Response.new(response)
73
91
  end
@@ -39,15 +39,17 @@ module Pact
39
39
  end
40
40
 
41
41
  def call
42
- if index.can?(PACTS_FOR_VERIFICATION_RELATION) || index.can?(PACTS_FOR_VERIFICATION_RELATION_BETA)
43
- log_message
44
- pacts_for_verification
45
- else
46
- old_selectors = consumer_version_selectors.collect do | selector |
47
- { name: selector[:tag], all: !selector[:latest], fallback: selector[:fallbackTag]}
42
+ handling_no_pacts_found do
43
+ if index.can?(PACTS_FOR_VERIFICATION_RELATION) || index.can?(PACTS_FOR_VERIFICATION_RELATION_BETA)
44
+ log_message
45
+ pacts_for_verification
46
+ else
47
+ old_selectors = consumer_version_selectors.collect do | selector |
48
+ { name: selector[:tag], all: !selector[:latest], fallback: selector[:fallbackTag]}
49
+ end
50
+ # Fall back to old method of fetching pacts
51
+ FetchPacts.call(provider, old_selectors, broker_base_url, http_client_options)
48
52
  end
49
- # Fall back to old method of fetching pacts
50
- FetchPacts.call(provider, old_selectors, broker_base_url, http_client_options)
51
53
  end
52
54
  end
53
55
 
@@ -96,6 +98,15 @@ module Pact
96
98
  def log_message
97
99
  Pact.configuration.output_stream.puts "INFO: #{pact_selection_description(provider, consumer_version_selectors, options, broker_base_url)}"
98
100
  end
101
+
102
+ def handling_no_pacts_found
103
+ pacts_found = yield
104
+ raise "No pacts found to verify" if pacts_found.empty? && options[:fail_if_no_pacts_found] != false
105
+ if pacts_found.empty? && options[:fail_if_no_pacts_found] == false
106
+ Pact.configuration.output_stream.puts "WARN: No pacts found to verify & fail_if_no_pacts_found is set to false."
107
+ end
108
+ pacts_found
109
+ end
99
110
  end
100
111
  end
101
112
  end
@@ -34,6 +34,10 @@ module Pact
34
34
  self.tags = tags
35
35
  end
36
36
 
37
+ def app_version_branch branch
38
+ self.branch = branch
39
+ end
40
+
37
41
  def publish_verification_results publish_verification_results
38
42
  self.publish_verification_results = publish_verification_results
39
43
  Pact::RSpec.with_rspec_2 do
@@ -15,7 +15,7 @@ module Pact
15
15
  # in parent scope, it will clash with these ones,
16
16
  # so put an underscore in front of the name to be safer.
17
17
 
18
- attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_branch, :_provider_version_tags, :_basic_auth_options, :_enable_pending, :_include_wip_pacts_since, :_verbose, :_consumer_version_selectors
18
+ attr_accessor :_provider_name, :_pact_broker_base_url, :_consumer_version_tags, :_provider_version_branch, :_provider_version_tags, :_basic_auth_options, :_enable_pending, :_include_wip_pacts_since, :_verbose, :_consumer_version_selectors, :_fail_if_no_pacts_found
19
19
 
20
20
  def initialize(provider_name, provider_version_branch, provider_version_tags)
21
21
  @_provider_name = provider_name
@@ -26,6 +26,7 @@ module Pact
26
26
  @_enable_pending = false
27
27
  @_include_wip_pacts_since = nil
28
28
  @_verbose = false
29
+ @_fail_if_no_pacts_found = true # CLI defaults to false, unfortunately for consistency
29
30
  end
30
31
 
31
32
  dsl do
@@ -46,6 +47,11 @@ module Pact
46
47
  self._enable_pending = enable_pending
47
48
  end
48
49
 
50
+ # Underlying code defaults to true if not specified
51
+ def fail_if_no_pacts_found fail_if_no_pacts_found
52
+ self._fail_if_no_pacts_found = fail_if_no_pacts_found
53
+ end
54
+
49
55
  def include_wip_pacts_since since
50
56
  self._include_wip_pacts_since = if since.respond_to?(:xmlschema)
51
57
  since.xmlschema
@@ -74,7 +80,7 @@ module Pact
74
80
  _provider_version_tags,
75
81
  _pact_broker_base_url,
76
82
  _basic_auth_options.merge(verbose: _verbose),
77
- { include_pending_status: _enable_pending, include_wip_pacts_since: _include_wip_pacts_since }
83
+ { include_pending_status: _enable_pending, include_wip_pacts_since: _include_wip_pacts_since, fail_if_no_pacts_found: _fail_if_no_pacts_found }
78
84
  )
79
85
 
80
86
  Pact.provider_world.add_pact_uri_source fetch_pacts
@@ -2,15 +2,13 @@ require 'pact/provider/help/content'
2
2
  require 'fileutils'
3
3
  require 'pact/consumer/configuration'
4
4
  require 'pact/provider/help/write'
5
- require 'term/ansicolor'
5
+ require 'rainbow'
6
6
 
7
7
  module Pact
8
8
  module Provider
9
9
  module Help
10
10
  class ConsoleText
11
11
 
12
- C = ::Term::ANSIColor
13
-
14
12
  def self.call reports_dir = Pact.configuration.reports_dir, options = {color: true}
15
13
  new(reports_dir || Pact.configuration.reports_dir, options).call
16
14
  end
@@ -46,13 +44,11 @@ module Pact
46
44
  end
47
45
 
48
46
  def error_text_coloured
49
- C.red(error_text_plain)
47
+ Rainbow(error_text_plain).red
50
48
  end
51
49
 
52
50
  class ColorizeMarkdown
53
51
 
54
- C = ::Term::ANSIColor
55
-
56
52
  def self.call markdown
57
53
  markdown.split("\n").collect do | line |
58
54
  if line.start_with?("# ")
@@ -66,11 +62,11 @@ module Pact
66
62
  end
67
63
 
68
64
  def self.yellow_underling string
69
- C.underline(C.yellow(string))
65
+ Rainbow(string).yellow.underline
70
66
  end
71
67
 
72
68
  def self.green string
73
- C.green(string)
69
+ Rainbow(string).green
74
70
  end
75
71
 
76
72
  end
@@ -1,5 +1,5 @@
1
1
  require 'pact/consumer/configuration'
2
- require 'term/ansicolor'
2
+ require 'rainbow'
3
3
  require 'pathname'
4
4
 
5
5
  module Pact
@@ -7,8 +7,6 @@ module Pact
7
7
  module Help
8
8
  class PromptText
9
9
 
10
- C = ::Term::ANSIColor
11
-
12
10
  def self.call reports_dir = Pact.configuration.reports_dir, options = {color: Pact.configuration.color_enabled}
13
11
  new(reports_dir, options).call
14
12
  end
@@ -31,7 +29,7 @@ module Pact
31
29
  end
32
30
 
33
31
  def prompt_text_colored
34
- C.yellow(prompt_text_plain)
32
+ Rainbow(prompt_text_plain).yellow
35
33
  end
36
34
 
37
35
  def rake_args
@@ -1,15 +1,13 @@
1
- require 'term/ansicolor'
1
+ require 'rainbow'
2
2
  require 'pact/term'
3
3
 
4
4
  module Pact
5
5
  module Matchers
6
6
  module Messages
7
7
 
8
- C = ::Term::ANSIColor
9
-
10
8
  def match_term_failure_message diff, actual, diff_formatter, color_enabled
11
9
  actual_string = String === actual ? actual : actual.to_json
12
- maybe_coloured_string = color_enabled ? C.white(actual_string) : actual_string
10
+ maybe_coloured_string = color_enabled ? Rainbow(actual_string).white : actual_string
13
11
  message = "Actual: #{maybe_coloured_string}\n\n"
14
12
  formatted_diff = diff_formatter.call(diff)
15
13
  message + colorize_if_enabled(formatted_diff, color_enabled)
@@ -40,7 +38,7 @@ module Pact
40
38
  # RSpec wraps each line in the failure message with failure_color, turning it red.
41
39
  # To ensure the lines in the diff that should be white, stay white, put an
42
40
  # ANSI reset at the start of each line.
43
- formatted_diff.split("\n").collect{ |line| ::Term::ANSIColor.reset + line }.join("\n")
41
+ formatted_diff.split("\n").collect{ |line|"\e[0m#{line}" }.join("\n")
44
42
  else
45
43
  formatted_diff
46
44
  end
@@ -1,11 +1,9 @@
1
- require 'term/ansicolor'
1
+ require 'rainbow'
2
2
 
3
3
  module Pact
4
4
  module Provider
5
5
  class PrintMissingProviderStates
6
6
 
7
- C = ::Term::ANSIColor
8
-
9
7
  # Hash of consumer names to array of names of missing provider states
10
8
  def self.call missing_provider_states, output
11
9
  if missing_provider_states.any?
@@ -15,8 +13,8 @@ module Pact
15
13
 
16
14
  def self.colorize string
17
15
  lines = string.split("\n")
18
- first_line = C.cyan(C.underline(lines[0]))
19
- other_lines = C.cyan(lines[1..-1].join("\n"))
16
+ first_line = Rainbow(lines[0]).cyan.underline
17
+ other_lines = Rainbow(lines[1..-1].join("\n")).cyan
20
18
  first_line + "\n" + other_lines
21
19
  end
22
20
 
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
  require 'pact/reification'
3
3
  require 'pact/shared/null_expectation'
4
+ require 'pact/generators'
4
5
 
5
6
  module Pact
6
7
  module Provider
@@ -10,8 +11,9 @@ module Pact
10
11
  # See https://github.com/rack/rack/blob/e7d741c6282ca4cf4e01506f5681e6e6b14c0b32/SPEC#L87-89
11
12
  NO_HTTP_PREFIX = ["CONTENT-TYPE", "CONTENT-LENGTH"]
12
13
 
13
- def initialize expected_request
14
+ def initialize expected_request, state_params = nil
14
15
  @expected_request = expected_request
16
+ @state_params = state_params
15
17
  end
16
18
 
17
19
  def method
@@ -19,7 +21,7 @@ module Pact
19
21
  end
20
22
 
21
23
  def path
22
- expected_request.full_path
24
+ Pact::Generators.apply_generators(expected_request, "path", expected_request.full_path, @state_params)
23
25
  end
24
26
 
25
27
  def body
@@ -27,17 +29,22 @@ module Pact
27
29
  when String then expected_request.body
28
30
  when NullExpectation then ''
29
31
  else
30
- reified_body
32
+ generated_body
31
33
  end
32
34
  end
33
35
 
34
36
  def headers
35
37
  request_headers = {}
38
+ # https://github.com/pact-foundation/pact-ruby/pull/327
39
+ request_headers.merge!('HOST' => 'localhost') if defined?(Sinatra)
36
40
  return request_headers if expected_request.headers.is_a?(Pact::NullExpectation)
41
+
37
42
  expected_request.headers.each do |key, value|
38
- request_headers[rack_request_header_for(key)] = Pact::Reification.from_term(value)
43
+ request_headers[key] = Pact::Reification.from_term(value)
39
44
  end
40
- request_headers
45
+
46
+ request_headers = Pact::Generators.apply_generators(expected_request, "header", request_headers, @state_params)
47
+ request_headers.map{ |key,value| [rack_request_header_for(key), value]}.to_h
41
48
  end
42
49
 
43
50
  private
@@ -53,6 +60,19 @@ module Pact
53
60
  end
54
61
  end
55
62
 
63
+ def generated_body
64
+ result = Pact::Generators.apply_generators(expected_request, "body", reified_body, @state_params)
65
+
66
+ case result
67
+ when Hash
68
+ result.to_json
69
+ when String
70
+ result
71
+ else
72
+ raise "Expected body to be a String or Hash, but was #{result.class} with value #{result.inspect}"
73
+ end
74
+ end
75
+
56
76
  def rack_request_header_for header
57
77
  with_http_prefix(header.to_s.upcase).tr('-', '_')
58
78
  end
@@ -1,6 +1,6 @@
1
1
  require 'pact/provider/print_missing_provider_states'
2
2
  require 'rspec/core/formatters/documentation_formatter'
3
- require 'term/ansicolor'
3
+ require 'rainbow'
4
4
  require 'pact/provider/help/prompt_text'
5
5
 
6
6
  module Pact
@@ -13,8 +13,6 @@ module Pact
13
13
  end
14
14
  end
15
15
 
16
- C = ::Term::ANSIColor
17
-
18
16
  def dump_commands_to_rerun_failed_examples
19
17
  return if failed_examples.empty?
20
18
 
@@ -1,6 +1,6 @@
1
1
  require 'pact/provider/print_missing_provider_states'
2
2
  require 'rspec/core/formatters'
3
- require 'term/ansicolor'
3
+ require 'rainbow'
4
4
  require 'pact/provider/help/prompt_text'
5
5
 
6
6
  module Pact
@@ -22,8 +22,6 @@ module Pact
22
22
  :example_passed, :example_pending, :example_failed
23
23
  end
24
24
 
25
- C = ::Term::ANSIColor
26
-
27
25
  def example_group_started(notification)
28
26
  # This is the metadata on the top level "Verifying a pact between X and Y" describe block
29
27
  if @group_level == 0
@@ -1,6 +1,6 @@
1
1
  require 'rspec/core/formatters'
2
2
  require 'pact/provider/verification_results/publish_all'
3
- require 'term/ansicolor'
3
+ require 'rainbow'
4
4
  require 'pact/matchers/extract_diff_messages'
5
5
 
6
6
  module Pact
@@ -43,7 +43,7 @@ module Pact
43
43
  if example.exception
44
44
  hash[:exception] = {
45
45
  class: example.exception.class.name,
46
- message: ::Term::ANSIColor.uncolor(example.exception.message)
46
+ message: "\e[0m#{example.exception.message}"
47
47
  }
48
48
  end
49
49
 
@@ -25,6 +25,7 @@ module Pact
25
25
  pact_uri = pact_source.uri
26
26
  Pact.configuration.output_stream.puts "INFO: Reading pact at #{pact_uri}"
27
27
  consumer_contract = Pact::ConsumerContract.from_json(pact_json)
28
+
28
29
  suffix = pact_uri.metadata[:pending] ? " [PENDING]": ""
29
30
  example_group_description = "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}#{suffix}"
30
31
  example_group_metadata = { pactfile_uri: pact_uri, pact_criteria: options[:criteria] }
@@ -77,7 +78,6 @@ module Pact
77
78
  end
78
79
 
79
80
  def describe_interaction interaction, options
80
-
81
81
  # pact_uri and pact_interaction are used by
82
82
  # Pact::Provider::RSpec::PactBrokerFormatter
83
83
 
@@ -103,8 +103,9 @@ module Pact
103
103
  before do | example |
104
104
  interaction_context.run_once :before do
105
105
  Pact.configuration.logger.info "Running example '#{Pact::RSpec.full_description(example)}'"
106
- set_up_provider_states interaction.provider_states, options[:consumer]
107
- replay_interaction interaction, options[:request_customizer]
106
+ provider_states_result = set_up_provider_states interaction.provider_states, options[:consumer]
107
+ state_params = provider_states_result[interaction.provider_state];
108
+ replay_interaction interaction, options[:request_customizer], state_params
108
109
  interaction_context.last_response = last_response
109
110
  end
110
111
  end
@@ -129,6 +130,7 @@ module Pact
129
130
  include Pact::RSpec::Matchers
130
131
  extend Pact::Matchers::Messages
131
132
 
133
+
132
134
  let(:expected_contents) { expected_response.body[:contents].as_json }
133
135
  let(:response) { interaction_context.last_response }
134
136
  let(:differ) { Pact.configuration.body_differ_for_content_type diff_content_type }
@@ -14,8 +14,8 @@ module Pact
14
14
  include Pact::Logging
15
15
  include Rack::Test::Methods
16
16
 
17
- def replay_interaction interaction, request_customizer = nil
18
- request = Request::Replayable.new(interaction.request)
17
+ def replay_interaction interaction, request_customizer = nil, state_params = nil
18
+ request = Request::Replayable.new(interaction.request, state_params)
19
19
  request = request_customizer.call(request, interaction) if request_customizer
20
20
  args = [request.path, request.body, request.headers]
21
21
 
@@ -42,11 +42,17 @@ module Pact
42
42
  end
43
43
 
44
44
  def set_up_provider_states provider_states, consumer, options = {}
45
+ provider_states_result = {};
45
46
  # If there are no provider state, execute with an nil state to ensure global and base states are executed
46
47
  Pact.configuration.provider_state_set_up.call(nil, consumer, options) if provider_states.nil? || provider_states.empty?
47
48
  provider_states.each do | provider_state |
48
- Pact.configuration.provider_state_set_up.call(provider_state.name, consumer, options.merge(params: provider_state.params))
49
+ result = Pact.configuration.provider_state_set_up.call(provider_state.name, consumer, options.merge(params: provider_state.params))
50
+ if result.is_a?(Hash)
51
+ provider_states_result[provider_state.name] = result
52
+ end
49
53
  end
54
+
55
+ provider_states_result
50
56
  end
51
57
 
52
58
  def tear_down_provider_states provider_states, consumer, options = {}
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pact
4
+ module V2
5
+ class Configuration
6
+ attr_reader :before_provider_state_proc, :after_provider_state_proc
7
+
8
+ class GlobalProviderConfigurationError < ::Pact::V2::Error; end
9
+
10
+ def before_provider_state_setup(&block)
11
+ raise GlobalProviderConfigurationError, "no block given" unless block
12
+
13
+ @before_provider_state_proc = block
14
+ end
15
+
16
+ def after_provider_state_teardown(&block)
17
+ raise GlobalProviderConfigurationError, "no block given" unless block
18
+
19
+ @after_provider_state_proc = block
20
+ end
21
+ end
22
+ end
23
+ end