pact 1.67.4 → 2.0.0

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 (239) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/lib/pact/configuration.rb +21 -0
  4. data/lib/pact/consumer/grpc_interaction_builder.rb +192 -0
  5. data/lib/pact/consumer/http_interaction_builder.rb +160 -0
  6. data/lib/pact/consumer/interaction_contents.rb +60 -0
  7. data/lib/pact/consumer/message_interaction_builder.rb +286 -0
  8. data/lib/pact/consumer/mock_server.rb +106 -0
  9. data/lib/pact/consumer/pact_config/base.rb +22 -0
  10. data/lib/pact/consumer/pact_config/grpc.rb +24 -0
  11. data/lib/pact/consumer/pact_config/http.rb +53 -0
  12. data/lib/pact/consumer/pact_config/message.rb +15 -0
  13. data/lib/pact/consumer/pact_config/plugin_async_message.rb +24 -0
  14. data/lib/pact/consumer/pact_config/plugin_http.rb +24 -0
  15. data/lib/pact/consumer/pact_config/plugin_sync_message.rb +24 -0
  16. data/lib/pact/consumer/pact_config.rb +28 -0
  17. data/lib/pact/consumer/plugin_async_message_interaction_builder.rb +169 -0
  18. data/lib/pact/consumer/plugin_http_interaction_builder.rb +199 -0
  19. data/lib/pact/consumer/plugin_sync_message_interaction_builder.rb +178 -0
  20. data/lib/pact/consumer.rb +6 -7
  21. data/lib/pact/generators/base.rb +285 -0
  22. data/lib/pact/generators.rb +47 -0
  23. data/lib/pact/matchers/base.rb +72 -0
  24. data/lib/pact/matchers/v1/equality.rb +17 -0
  25. data/lib/pact/matchers/v2/regex.rb +26 -0
  26. data/lib/pact/matchers/v2/type.rb +18 -0
  27. data/lib/pact/matchers/v3/boolean.rb +18 -0
  28. data/lib/pact/matchers/v3/content_type.rb +30 -0
  29. data/lib/pact/matchers/v3/date.rb +22 -0
  30. data/lib/pact/matchers/v3/date_time.rb +22 -0
  31. data/lib/pact/matchers/v3/decimal.rb +18 -0
  32. data/lib/pact/matchers/v3/each.rb +46 -0
  33. data/lib/pact/matchers/v3/include.rb +18 -0
  34. data/lib/pact/matchers/v3/integer.rb +18 -0
  35. data/lib/pact/matchers/v3/null.rb +13 -0
  36. data/lib/pact/matchers/v3/number.rb +18 -0
  37. data/lib/pact/matchers/v3/semver.rb +22 -0
  38. data/lib/pact/matchers/v3/time.rb +22 -0
  39. data/lib/pact/matchers/v3/values.rb +13 -0
  40. data/lib/pact/matchers/v4/each_key.rb +34 -0
  41. data/lib/pact/matchers/v4/each_key_value.rb +38 -0
  42. data/lib/pact/matchers/v4/each_value.rb +40 -0
  43. data/lib/pact/matchers/v4/not_empty.rb +22 -0
  44. data/lib/pact/matchers/v4/status_code.rb +15 -0
  45. data/lib/pact/matchers.rb +108 -0
  46. data/lib/pact/native/blocking_verifier.rb +15 -0
  47. data/lib/pact/native/logger.rb +24 -0
  48. data/lib/pact/provider/async_message_verifier.rb +29 -0
  49. data/lib/pact/provider/base_verifier.rb +259 -0
  50. data/lib/pact/provider/grpc_verifier.rb +40 -0
  51. data/lib/pact/provider/gruf_server.rb +73 -0
  52. data/lib/pact/provider/http_server.rb +77 -0
  53. data/lib/pact/provider/http_verifier.rb +45 -0
  54. data/lib/pact/provider/message_provider_servlet.rb +77 -0
  55. data/lib/pact/provider/mixed_verifier.rb +21 -0
  56. data/lib/pact/provider/pact_broker_proxy.rb +62 -0
  57. data/lib/pact/provider/pact_broker_proxy_runner.rb +78 -0
  58. data/lib/pact/provider/pact_config/async.rb +28 -0
  59. data/lib/pact/provider/pact_config/base.rb +101 -0
  60. data/lib/pact/provider/pact_config/grpc.rb +24 -0
  61. data/lib/pact/provider/pact_config/http.rb +25 -0
  62. data/lib/pact/provider/pact_config/mixed.rb +38 -0
  63. data/lib/pact/provider/pact_config.rb +24 -0
  64. data/lib/pact/provider/provider_server_runner.rb +90 -0
  65. data/lib/pact/provider/provider_state_configuration.rb +32 -0
  66. data/lib/pact/provider/provider_state_servlet.rb +84 -0
  67. data/lib/pact/provider.rb +6 -3
  68. data/lib/pact/railtie.rb +11 -0
  69. data/lib/pact/{v2/rspec → rspec}/support/pact_consumer_helpers.rb +8 -8
  70. data/lib/pact/{v2/rspec → rspec}/support/pact_provider_helpers.rb +25 -24
  71. data/lib/pact/{v2/rspec.rb → rspec.rb} +6 -5
  72. data/lib/pact/tasks/pact.rake +13 -0
  73. data/lib/pact/version.rb +1 -1
  74. data/lib/pact.rb +46 -11
  75. data/pact.gemspec +42 -65
  76. metadata +145 -404
  77. data/lib/pact/cli/generate_pact_docs.rb +0 -4
  78. data/lib/pact/cli/run_pact_verification.rb +0 -99
  79. data/lib/pact/cli/spec_criteria.rb +0 -26
  80. data/lib/pact/cli.rb +0 -45
  81. data/lib/pact/consumer/configuration/configuration_extensions.rb +0 -90
  82. data/lib/pact/consumer/configuration/dsl.rb +0 -11
  83. data/lib/pact/consumer/configuration/mock_service.rb +0 -112
  84. data/lib/pact/consumer/configuration/service_consumer.rb +0 -51
  85. data/lib/pact/consumer/configuration/service_provider.rb +0 -40
  86. data/lib/pact/consumer/configuration.rb +0 -10
  87. data/lib/pact/consumer/consumer_contract_builder.rb +0 -82
  88. data/lib/pact/consumer/consumer_contract_builders.rb +0 -10
  89. data/lib/pact/consumer/interaction_builder.rb +0 -45
  90. data/lib/pact/consumer/rspec.rb +0 -35
  91. data/lib/pact/consumer/spec_hooks.rb +0 -40
  92. data/lib/pact/consumer/world.rb +0 -37
  93. data/lib/pact/doc/README.md +0 -13
  94. data/lib/pact/doc/doc_file.rb +0 -40
  95. data/lib/pact/doc/generate.rb +0 -11
  96. data/lib/pact/doc/generator.rb +0 -82
  97. data/lib/pact/doc/interaction_view_model.rb +0 -124
  98. data/lib/pact/doc/markdown/consumer_contract_renderer.rb +0 -68
  99. data/lib/pact/doc/markdown/generator.rb +0 -26
  100. data/lib/pact/doc/markdown/index_renderer.rb +0 -43
  101. data/lib/pact/doc/markdown/interaction.erb +0 -14
  102. data/lib/pact/doc/markdown/interaction_renderer.rb +0 -43
  103. data/lib/pact/doc/sort_interactions.rb +0 -16
  104. data/lib/pact/hal/authorization_header_redactor.rb +0 -32
  105. data/lib/pact/hal/entity.rb +0 -110
  106. data/lib/pact/hal/http_client.rb +0 -128
  107. data/lib/pact/hal/link.rb +0 -112
  108. data/lib/pact/hal/non_json_entity.rb +0 -28
  109. data/lib/pact/hash_refinements.rb +0 -17
  110. data/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb +0 -112
  111. data/lib/pact/pact_broker/fetch_pacts.rb +0 -103
  112. data/lib/pact/pact_broker/notices.rb +0 -34
  113. data/lib/pact/pact_broker/pact_selection_description.rb +0 -66
  114. data/lib/pact/pact_broker.rb +0 -25
  115. data/lib/pact/project_root.rb +0 -7
  116. data/lib/pact/provider/configuration/configuration_extension.rb +0 -69
  117. data/lib/pact/provider/configuration/dsl.rb +0 -18
  118. data/lib/pact/provider/configuration/message_provider_dsl.rb +0 -63
  119. data/lib/pact/provider/configuration/pact_verification.rb +0 -48
  120. data/lib/pact/provider/configuration/pact_verification_from_broker.rb +0 -126
  121. data/lib/pact/provider/configuration/service_provider_config.rb +0 -32
  122. data/lib/pact/provider/configuration/service_provider_dsl.rb +0 -107
  123. data/lib/pact/provider/configuration.rb +0 -7
  124. data/lib/pact/provider/context.rb +0 -0
  125. data/lib/pact/provider/help/console_text.rb +0 -76
  126. data/lib/pact/provider/help/content.rb +0 -38
  127. data/lib/pact/provider/help/pact_diff.rb +0 -43
  128. data/lib/pact/provider/help/prompt_text.rb +0 -49
  129. data/lib/pact/provider/help/write.rb +0 -56
  130. data/lib/pact/provider/matchers/messages.rb +0 -66
  131. data/lib/pact/provider/pact_helper_locator.rb +0 -24
  132. data/lib/pact/provider/pact_source.rb +0 -40
  133. data/lib/pact/provider/pact_spec_runner.rb +0 -188
  134. data/lib/pact/provider/pact_uri.rb +0 -55
  135. data/lib/pact/provider/pact_verification.rb +0 -17
  136. data/lib/pact/provider/print_missing_provider_states.rb +0 -35
  137. data/lib/pact/provider/request.rb +0 -90
  138. data/lib/pact/provider/rspec/backtrace_formatter.rb +0 -43
  139. data/lib/pact/provider/rspec/calculate_exit_code.rb +0 -18
  140. data/lib/pact/provider/rspec/custom_options_file +0 -0
  141. data/lib/pact/provider/rspec/formatter_rspec_2.rb +0 -76
  142. data/lib/pact/provider/rspec/formatter_rspec_3.rb +0 -195
  143. data/lib/pact/provider/rspec/json_formatter.rb +0 -100
  144. data/lib/pact/provider/rspec/matchers.rb +0 -80
  145. data/lib/pact/provider/rspec/pact_broker_formatter.rb +0 -76
  146. data/lib/pact/provider/rspec.rb +0 -234
  147. data/lib/pact/provider/state/provider_state.rb +0 -180
  148. data/lib/pact/provider/state/provider_state_configured_modules.rb +0 -15
  149. data/lib/pact/provider/state/provider_state_manager.rb +0 -42
  150. data/lib/pact/provider/state/provider_state_proxy.rb +0 -39
  151. data/lib/pact/provider/state/set_up.rb +0 -13
  152. data/lib/pact/provider/state/tear_down.rb +0 -13
  153. data/lib/pact/provider/test_methods.rb +0 -77
  154. data/lib/pact/provider/verification_report.rb +0 -36
  155. data/lib/pact/provider/verification_results/create.rb +0 -88
  156. data/lib/pact/provider/verification_results/publish.rb +0 -143
  157. data/lib/pact/provider/verification_results/publish_all.rb +0 -50
  158. data/lib/pact/provider/verification_results/verification_result.rb +0 -40
  159. data/lib/pact/provider/world.rb +0 -50
  160. data/lib/pact/retry.rb +0 -37
  161. data/lib/pact/tasks/task_helper.rb +0 -62
  162. data/lib/pact/tasks/verification_task.rb +0 -95
  163. data/lib/pact/tasks.rb +0 -2
  164. data/lib/pact/templates/help.erb +0 -22
  165. data/lib/pact/templates/provider_state.erb +0 -14
  166. data/lib/pact/utils/metrics.rb +0 -100
  167. data/lib/pact/utils/string.rb +0 -35
  168. data/lib/pact/v2/configuration.rb +0 -23
  169. data/lib/pact/v2/consumer/grpc_interaction_builder.rb +0 -194
  170. data/lib/pact/v2/consumer/http_interaction_builder.rb +0 -162
  171. data/lib/pact/v2/consumer/interaction_contents.rb +0 -62
  172. data/lib/pact/v2/consumer/message_interaction_builder.rb +0 -288
  173. data/lib/pact/v2/consumer/mock_server.rb +0 -108
  174. data/lib/pact/v2/consumer/pact_config/base.rb +0 -24
  175. data/lib/pact/v2/consumer/pact_config/grpc.rb +0 -26
  176. data/lib/pact/v2/consumer/pact_config/http.rb +0 -55
  177. data/lib/pact/v2/consumer/pact_config/message.rb +0 -17
  178. data/lib/pact/v2/consumer/pact_config/plugin_async_message.rb +0 -26
  179. data/lib/pact/v2/consumer/pact_config/plugin_http.rb +0 -26
  180. data/lib/pact/v2/consumer/pact_config/plugin_sync_message.rb +0 -26
  181. data/lib/pact/v2/consumer/pact_config.rb +0 -30
  182. data/lib/pact/v2/consumer/plugin_async_message_interaction_builder.rb +0 -171
  183. data/lib/pact/v2/consumer/plugin_http_interaction_builder.rb +0 -201
  184. data/lib/pact/v2/consumer/plugin_sync_message_interaction_builder.rb +0 -180
  185. data/lib/pact/v2/consumer.rb +0 -8
  186. data/lib/pact/v2/generators/base.rb +0 -287
  187. data/lib/pact/v2/generators.rb +0 -49
  188. data/lib/pact/v2/matchers/base.rb +0 -74
  189. data/lib/pact/v2/matchers/v1/equality.rb +0 -19
  190. data/lib/pact/v2/matchers/v2/regex.rb +0 -19
  191. data/lib/pact/v2/matchers/v2/type.rb +0 -17
  192. data/lib/pact/v2/matchers/v3/boolean.rb +0 -17
  193. data/lib/pact/v2/matchers/v3/content_type.rb +0 -32
  194. data/lib/pact/v2/matchers/v3/date.rb +0 -18
  195. data/lib/pact/v2/matchers/v3/date_time.rb +0 -18
  196. data/lib/pact/v2/matchers/v3/decimal.rb +0 -17
  197. data/lib/pact/v2/matchers/v3/each.rb +0 -42
  198. data/lib/pact/v2/matchers/v3/include.rb +0 -17
  199. data/lib/pact/v2/matchers/v3/integer.rb +0 -17
  200. data/lib/pact/v2/matchers/v3/null.rb +0 -16
  201. data/lib/pact/v2/matchers/v3/number.rb +0 -17
  202. data/lib/pact/v2/matchers/v3/semver.rb +0 -23
  203. data/lib/pact/v2/matchers/v3/time.rb +0 -18
  204. data/lib/pact/v2/matchers/v3/values.rb +0 -16
  205. data/lib/pact/v2/matchers/v4/each_key.rb +0 -26
  206. data/lib/pact/v2/matchers/v4/each_key_value.rb +0 -32
  207. data/lib/pact/v2/matchers/v4/each_value.rb +0 -33
  208. data/lib/pact/v2/matchers/v4/not_empty.rb +0 -24
  209. data/lib/pact/v2/matchers/v4/status_code.rb +0 -17
  210. data/lib/pact/v2/matchers.rb +0 -110
  211. data/lib/pact/v2/native/blocking_verifier.rb +0 -17
  212. data/lib/pact/v2/native/logger.rb +0 -25
  213. data/lib/pact/v2/provider/async_message_verifier.rb +0 -28
  214. data/lib/pact/v2/provider/base_verifier.rb +0 -242
  215. data/lib/pact/v2/provider/grpc_verifier.rb +0 -38
  216. data/lib/pact/v2/provider/gruf_server.rb +0 -75
  217. data/lib/pact/v2/provider/http_server.rb +0 -79
  218. data/lib/pact/v2/provider/http_verifier.rb +0 -43
  219. data/lib/pact/v2/provider/message_provider_servlet.rb +0 -79
  220. data/lib/pact/v2/provider/mixed_verifier.rb +0 -22
  221. data/lib/pact/v2/provider/pact_broker_proxy.rb +0 -66
  222. data/lib/pact/v2/provider/pact_broker_proxy_runner.rb +0 -80
  223. data/lib/pact/v2/provider/pact_config/async.rb +0 -29
  224. data/lib/pact/v2/provider/pact_config/base.rb +0 -103
  225. data/lib/pact/v2/provider/pact_config/grpc.rb +0 -26
  226. data/lib/pact/v2/provider/pact_config/http.rb +0 -27
  227. data/lib/pact/v2/provider/pact_config/mixed.rb +0 -40
  228. data/lib/pact/v2/provider/pact_config.rb +0 -26
  229. data/lib/pact/v2/provider/provider_server_runner.rb +0 -92
  230. data/lib/pact/v2/provider/provider_state_configuration.rb +0 -32
  231. data/lib/pact/v2/provider/provider_state_servlet.rb +0 -86
  232. data/lib/pact/v2/provider.rb +0 -8
  233. data/lib/pact/v2/railtie.rb +0 -13
  234. data/lib/pact/v2/tasks/pact.rake +0 -13
  235. data/lib/pact/v2.rb +0 -71
  236. data/lib/tasks/pact.rake +0 -34
  237. /data/lib/pact/{v2/rspec → rspec}/support/pact_message_helpers.rb +0 -0
  238. /data/lib/pact/{v2/rspec → rspec}/support/waterdrop/pact_waterdrop_client.rb +0 -0
  239. /data/lib/pact/{v2/rspec → rspec}/support/webmock/webmock_helpers.rb +0 -0
@@ -0,0 +1,38 @@
1
+ # # frozen_string_literal: true
2
+
3
+ module Pact
4
+ module Provider
5
+ module PactConfig
6
+ # Mixed config allows composing one of each: async, grpc, http
7
+ class Mixed < Base
8
+ attr_reader :async_config, :grpc_config, :http_config
9
+
10
+ def initialize(provider_name:, opts: {})
11
+ super
12
+ @provider_setup_server = ProviderServerRunner.new(port: @provider_setup_port, logger: @logger)
13
+ if @broker_url.present?
14
+ @pact_proxy_server = PactBrokerProxyRunner.new(
15
+ port: @pact_proxy_port,
16
+ pact_broker_host: @broker_url,
17
+ pact_broker_user: @broker_username,
18
+ pact_broker_password: @broker_password,
19
+ pact_broker_token: @broker_token,
20
+ logger: @logger
21
+ )
22
+ end
23
+ @http_config = opts[:http] ? Http.new(provider_name: provider_name, opts: opts[:http].merge(provider_setup_server: provider_setup_server, pact_proxy_server: @pact_proxy_server)) : nil
24
+ @grpc_config = opts[:grpc] ? Grpc.new(provider_name: provider_name, opts: opts[:grpc].merge(provider_setup_server: provider_setup_server, pact_proxy_server: @pact_proxy_server)) : nil
25
+ @async_config = opts[:async] ? Async.new(provider_name: provider_name, opts: opts[:async].merge(provider_setup_server: provider_setup_server, pact_proxy_server: @pact_proxy_server)) : nil
26
+ end
27
+
28
+ def configs
29
+ [@async_config, @grpc_config, @http_config].compact
30
+ end
31
+
32
+ def start_servers
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require_relative "pact_config/grpc"
4
+
5
+ module Pact
6
+ module Provider
7
+ module PactConfig
8
+ def self.new(transport_type, provider_name:, opts: {})
9
+ case transport_type
10
+ when :http
11
+ Http.new(provider_name: provider_name, opts: opts)
12
+ when :grpc
13
+ Grpc.new(provider_name: provider_name, opts: opts)
14
+ when :async
15
+ Async.new(provider_name: provider_name, opts: opts)
16
+ when :mixed
17
+ Mixed.new(provider_name: provider_name, opts: opts)
18
+ else
19
+ raise ArgumentError, "unknown transport_type: #{transport_type}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webrick"
4
+
5
+ module Pact
6
+ module Provider
7
+ class ProviderServerRunner
8
+ attr_reader :logger
9
+
10
+ SETUP_PROVIDER_STATE_PATH = "/setup-provider"
11
+ VERIFY_MESSAGE_PATH = "/verify-message"
12
+
13
+ def initialize(port: 9001, host: "127.0.0.1", logger: nil)
14
+ @host = host
15
+ @port = port
16
+ @provider_setup_states = {}
17
+ @provider_teardown_states = {}
18
+ @logger = logger || Logger.new($stdout)
19
+
20
+ @state_servlet = ProviderStateServlet.new(logger: @logger)
21
+ @message_servlet = MessageProviderServlet.new(logger: @logger)
22
+ @thread = nil
23
+ end
24
+
25
+ def state_setup_url
26
+ "http://#{@host}:#{@port}#{SETUP_PROVIDER_STATE_PATH}"
27
+ end
28
+
29
+ def message_setup_url
30
+ "http://#{@host}:#{@port}#{VERIFY_MESSAGE_PATH}"
31
+ end
32
+
33
+ def start
34
+ raise "server already running, stop server before starting new one" if @thread
35
+
36
+ @server = WEBrick::HTTPServer.new(
37
+ { BindAddress: @host, Port: @port, Logger: @logger, AccessLog: [] },
38
+ WEBrick::Config::HTTP
39
+ )
40
+ @server.mount(SETUP_PROVIDER_STATE_PATH, @state_servlet)
41
+ @server.mount(VERIFY_MESSAGE_PATH, @message_servlet)
42
+
43
+ @thread = Thread.new do
44
+ @logger.debug "starting provider setup server"
45
+ @server.start
46
+ end
47
+ end
48
+
49
+ def stop
50
+ @logger.info("stopping provider setup server")
51
+
52
+ @server&.shutdown
53
+ @thread&.join
54
+
55
+ @logger.info("provider setup server stopped")
56
+ end
57
+
58
+ def run
59
+ start
60
+
61
+ yield
62
+ rescue => e
63
+ logger.fatal("FATAL ERROR: #{e.message} #{e.backtrace.join("\n")}")
64
+ raise
65
+ ensure
66
+ stop
67
+ end
68
+
69
+ def add_message_handler(state_name, &block)
70
+ @message_servlet.add_message_handler(state_name, &block)
71
+ end
72
+
73
+ def add_setup_state(state_name, use_before_setup_hook = true, &block)
74
+ @state_servlet.add_setup_state(state_name, use_before_setup_hook, &block)
75
+ end
76
+
77
+ def add_teardown_state(state_name, use_after_teardown_hook = true, &block)
78
+ @state_servlet.add_teardown_state(state_name, use_after_teardown_hook, &block)
79
+ end
80
+
81
+ def set_before_setup_hook(&block)
82
+ @state_servlet.before_setup(&block)
83
+ end
84
+
85
+ def set_after_teardown_hook(&block)
86
+ @state_servlet.after_teardown(&block)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pact
4
+ module Provider
5
+ class ProviderStateConfiguration
6
+ attr_reader :name, :opts, :setup_proc, :teardown_proc
7
+
8
+ class ProviderStateConfigurationError < ::Pact::Error; end
9
+
10
+ def initialize(name, opts: {})
11
+ @name = name
12
+ @opts = opts
13
+ @setup_proc = nil
14
+ @teardown_proc = nil
15
+ end
16
+
17
+ def set_up(&block)
18
+ @setup_proc = block
19
+ end
20
+
21
+ def tear_down(&block)
22
+ @teardown_proc = block
23
+ end
24
+
25
+ def validate!
26
+ return if @setup_proc || @teardown_proc
27
+
28
+ raise ProviderStateConfigurationError.new("no hooks configured for state #{@name}: \"provider_state\" declaration only needed if setup/teardown hooks are used for that state. Please add hooks or remove \"provider_state\" declaration") # rubocop:disable Layout/LineLength
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "webrick"
4
+
5
+ module Pact
6
+ module Provider
7
+ class ProviderStateServlet < WEBrick::HTTPServlet::ProcHandler
8
+ attr_reader :logger
9
+
10
+ def initialize(logger: nil)
11
+ super(build_proc)
12
+
13
+ @logger = logger || Logger.new($stdout)
14
+
15
+ @provider_setup_states = {}
16
+ @provider_teardown_states = {}
17
+
18
+ @before_setup_hook_proc = nil
19
+ @after_teardown_hook_proc = nil
20
+
21
+ @global_setup_hook = ::Pact.configuration.before_provider_state_proc
22
+ @global_teardown_hook = ::Pact.configuration.after_provider_state_proc
23
+ end
24
+
25
+ def add_setup_state(name, use_before_setup_hook, &block)
26
+ raise "provider state #{name} already configured" if @provider_setup_states[name].present?
27
+
28
+ @provider_setup_states[name] = {proc: block, use_hooks: use_before_setup_hook}
29
+ end
30
+
31
+ def add_teardown_state(name, use_after_teardown_hook, &block)
32
+ raise "provider state #{name} already configured" if @provider_teardown_states[name].present?
33
+
34
+ @provider_teardown_states[name] = {proc: block, use_hooks: use_after_teardown_hook}
35
+ end
36
+
37
+ def before_setup(&block)
38
+ @before_setup_hook_proc = block
39
+ end
40
+
41
+ def after_teardown(&block)
42
+ @after_teardown_hook_proc = block
43
+ end
44
+
45
+ private
46
+
47
+ def call_setup(state_name, state_data)
48
+ logger.debug "call_setup #{state_name} with #{state_data}"
49
+ @global_setup_hook&.call
50
+ @before_setup_hook_proc&.call(state_name, state_data) if @provider_setup_states.dig(state_name, :use_hooks)
51
+ @provider_setup_states.dig(state_name, :proc)&.call(state_data)
52
+ end
53
+
54
+ def call_teardown(state_name, state_data)
55
+ logger.debug "call_teardown #{state_name} with #{state_data}"
56
+ @provider_teardown_states.dig(state_name, :proc)&.call(state_data)
57
+ @after_teardown_hook_proc&.call(state_name, state_data) if @provider_setup_states.dig(state_name, :use_hooks)
58
+ @global_teardown_hook&.call
59
+ end
60
+
61
+ def build_proc
62
+ proc do |request, response|
63
+ # {"action" => "setup", "params" => {"order_uuid" => "mxfcpcsfUOHO"},"state" => "order exists and can be saved"}
64
+ # {"action"=> "teardown", "params" => {"order_uuid" => "mxfcpcsfUOHO"}, "state" => "order exists and can be saved"}
65
+ data = JSON.parse(request.body)
66
+
67
+ action = data["action"]
68
+ state_name = data["state"]
69
+ state_data = data["params"]
70
+
71
+ logger.warn("unknown callback state action: #{action}") if action.blank?
72
+
73
+ call_setup(state_name, state_data) if action == "setup"
74
+ call_teardown(state_name, state_data) if action == "teardown"
75
+
76
+ response.status = 200
77
+ rescue JSON::ParserError => ex
78
+ logger.error("cannot parse request: #{ex.message}")
79
+ response.status = 500
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/pact/provider.rb CHANGED
@@ -1,3 +1,6 @@
1
- require 'pact/configuration'
2
- require 'pact/provider/configuration'
3
- require 'pact/provider/world'
1
+ # frozen_string_literal: true
2
+
3
+ module Pact
4
+ module Provider
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/railtie'
4
+
5
+ module Pact
6
+ class Railtie < Rails::Railtie
7
+ rake_tasks do
8
+ load 'pact/tasks/pact.rake'
9
+ end
10
+ end
11
+ end
@@ -3,9 +3,9 @@
3
3
  require_relative "pact_message_helpers"
4
4
  require "json"
5
5
 
6
- module PactV2ConsumerDsl
7
- include Pact::V2::Matchers
8
- include Pact::V2::Generators
6
+ module PactConsumerDsl
7
+ include Pact::Matchers
8
+ include Pact::Generators
9
9
 
10
10
  module ClassMethods
11
11
  def has_http_pact_between(consumer, provider, opts: {})
@@ -39,7 +39,7 @@ module PactV2ConsumerDsl
39
39
 
40
40
  # rubocop:disable RSpec/BeforeAfterAll
41
41
  before(:context) do
42
- @_pact_config = Pact::V2::Consumer::PactConfig.new(transport_type, consumer_name: consumer, provider_name: provider, opts: opts)
42
+ @_pact_config = Pact::Consumer::PactConfig.new(transport_type, consumer_name: consumer, provider_name: provider, opts: opts)
43
43
  end
44
44
  # rubocop:enable RSpec/BeforeAfterAll
45
45
  end
@@ -59,7 +59,7 @@ module PactV2ConsumerDsl
59
59
 
60
60
  def execute_http_pact
61
61
  raise InteractionBuilderError.new("interaction is designed to be used one-time only") if defined?(@used)
62
- mock_server = Pact::V2::Consumer::MockServer.create_for_http!(
62
+ mock_server = Pact::Consumer::MockServer.create_for_http!(
63
63
  pact: pact_config.pact_handle, host: pact_config.mock_host, port: pact_config.mock_port
64
64
  )
65
65
 
@@ -70,7 +70,7 @@ module PactV2ConsumerDsl
70
70
  mock_server.write_pacts!(pact_config.pact_dir)
71
71
  else
72
72
  msg = mismatches_error_msg(mock_server)
73
- raise Pact::V2::Consumer::HttpInteractionBuilder::InteractionMismatchesError.new(msg)
73
+ raise Pact::Consumer::HttpInteractionBuilder::InteractionMismatchesError.new(msg)
74
74
  end
75
75
  @used = true
76
76
  mock_server&.cleanup
@@ -88,6 +88,6 @@ module PactV2ConsumerDsl
88
88
  end
89
89
 
90
90
  RSpec.configure do |config|
91
- config.include PactV2ConsumerDsl, pact_entity: :consumer
92
- config.extend PactV2ConsumerDsl::ClassMethods, pact_entity: :consumer
91
+ config.include PactConsumerDsl, pact_entity: :consumer
92
+ config.extend PactConsumerDsl::ClassMethods, pact_entity: :consumer
93
93
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "pact_message_helpers"
4
- require_relative "webmock/webmock_helpers"
3
+ require_relative 'pact_message_helpers'
4
+ require_relative 'webmock/webmock_helpers'
5
5
 
6
- module PactV2ProducerDsl
6
+ module PactProducerDsl
7
7
  module ClassMethods
8
- PACT_PROVIDER_NOT_DECLARED_MESSAGE = "http_pact_provider or grpc_pact_provider should be declared first"
8
+ PACT_PROVIDER_NOT_DECLARED_MESSAGE = 'http_pact_provider or grpc_pact_provider should be declared first'
9
9
 
10
10
  def http_pact_provider(provider, opts: {})
11
11
  _pact_provider(:http, provider, opts: opts)
@@ -26,22 +26,21 @@ module PactV2ProducerDsl
26
26
  def execute_mixed_pact_provider(transport_type, provider, opts: {})
27
27
  raise "#{transport_type}_pact_provider is designed to be used with RSpec" unless defined?(::RSpec)
28
28
  raise "#{transport_type}_pact_provider has to be declared at the top level of a suite" unless top_level?
29
- raise "mixed_pact_provider is designed to be run once per provider so cannot be declared more than once" if defined?(@_pact_config)
29
+ if defined?(@_pact_config)
30
+ raise 'mixed_pact_provider is designed to be run once per provider so cannot be declared more than once'
31
+ end
30
32
 
31
- pact_config_instance = Pact::V2::Provider::PactConfig.new(transport_type, provider_name: provider, opts: opts)
33
+ pact_config_instance = Pact::Provider::PactConfig.new(transport_type, provider_name: provider, opts: opts)
32
34
  instance_variable_set(:@_pact_config, pact_config_instance)
33
35
 
34
- # rubocop:disable RSpec/BeforeAfterAll
35
36
  before(:context) do
36
37
  # rspec allows only context ivars in specs and ignores the rest
37
38
  # so we use block-as-a-closure feature to save pact_config ivar reference and make it available for descendants
38
39
  @_pact_config = pact_config_instance
39
40
  end
40
- # rubocop:enable RSpec/BeforeAfterAll
41
-
42
41
  it "verifies mixed interactions with provider #{provider}" do
43
42
  pact_config.start_servers
44
- # todo: call any available verifier, or exit if none specified
43
+ # TODO: call any available verifier, or exit if none specified
45
44
  pact_config.http_config.new_verifier(@_pact_config).verify!
46
45
  end
47
46
  end
@@ -49,19 +48,18 @@ module PactV2ProducerDsl
49
48
  def _pact_provider(transport_type, provider, opts: {})
50
49
  raise "#{transport_type}_pact_provider is designed to be used with RSpec" unless defined?(::RSpec)
51
50
  raise "#{transport_type}_pact_provider has to be declared at the top level of a suite" unless top_level?
52
- raise "*_pact_provider is designed to be run once per provider so cannot be declared more than once" if defined?(@_pact_config)
51
+ if defined?(@_pact_config)
52
+ raise '*_pact_provider is designed to be run once per provider so cannot be declared more than once'
53
+ end
53
54
 
54
- pact_config_instance = Pact::V2::Provider::PactConfig.new(transport_type, provider_name: provider, opts: opts)
55
+ pact_config_instance = Pact::Provider::PactConfig.new(transport_type, provider_name: provider, opts: opts)
55
56
  instance_variable_set(:@_pact_config, pact_config_instance)
56
57
 
57
- # rubocop:disable RSpec/BeforeAfterAll
58
58
  before(:context) do
59
59
  # rspec allows only context ivars in specs and ignores the rest
60
60
  # so we use block-as-a-closure feature to save pact_config ivar reference and make it available for descendants
61
61
  @_pact_config = pact_config_instance
62
62
  end
63
- # rubocop:enable RSpec/BeforeAfterAll
64
-
65
63
  it "verifies interactions with provider #{provider}" do
66
64
  pact_config.new_verifier.verify!
67
65
  end
@@ -69,37 +67,40 @@ module PactV2ProducerDsl
69
67
 
70
68
  def before_state_setup(&block)
71
69
  raise PACT_PROVIDER_NOT_DECLARED_MESSAGE unless pact_config
70
+
72
71
  pact_config.before_setup(&block)
73
72
  end
74
73
 
75
74
  def after_state_teardown(&block)
76
75
  raise PACT_PROVIDER_NOT_DECLARED_MESSAGE unless pact_config
76
+
77
77
  pact_config.after_teardown(&block)
78
78
  end
79
79
 
80
80
  def provider_state(name, opts: {}, &block)
81
81
  raise PACT_PROVIDER_NOT_DECLARED_MESSAGE unless pact_config
82
+
82
83
  pact_config.new_provider_state(name, opts: opts, &block)
83
84
  end
84
85
 
85
86
  def handle_message(name, opts: {}, &block)
86
- async_klass = Pact::V2::Provider::PactConfig::Async
87
+ async_klass = Pact::Provider::PactConfig::Async
87
88
  if defined?(@_pact_config) &&
88
- @_pact_config.respond_to?(:async_config) &&
89
- @_pact_config.async_config.is_a?(async_klass)
89
+ @_pact_config.respond_to?(:async_config) &&
90
+ @_pact_config.async_config.is_a?(async_klass)
90
91
  @_pact_config.async_config.new_message_handler(name, opts: opts, &block)
91
92
  elsif pact_config &&
92
- pact_config.respond_to?(:async_config) &&
93
- pact_config.async_config.is_a?(async_klass)
93
+ pact_config.respond_to?(:async_config) &&
94
+ pact_config.async_config.is_a?(async_klass)
94
95
  pact_config.async_config.new_message_handler(name, opts: opts, &block)
95
96
  elsif defined?(@_pact_config) &&
96
- @_pact_config.is_a?(async_klass)
97
+ @_pact_config.is_a?(async_klass)
97
98
  @_pact_config.new_message_handler(name, opts: opts, &block)
98
99
  elsif pact_config.is_a?(async_klass)
99
100
  pact_config.new_message_handler(name, opts: opts, &block)
100
101
 
101
102
  else
102
- raise "handle_message can only be used with message_pact_provider or mixed_pact_provider with an async block"
103
+ raise 'handle_message can only be used with message_pact_provider or mixed_pact_provider with an async block'
103
104
  end
104
105
  end
105
106
 
@@ -114,8 +115,8 @@ module PactV2ProducerDsl
114
115
  end
115
116
 
116
117
  RSpec.configure do |config|
117
- config.include PactV2ProducerDsl, pact_entity: :provider
118
- config.extend PactV2ProducerDsl::ClassMethods, pact_entity: :provider
118
+ config.include PactProducerDsl, pact_entity: :provider
119
+ config.extend PactProducerDsl::ClassMethods, pact_entity: :provider
119
120
 
120
121
  config.around pact_entity: :provider do |example|
121
122
  WebmockHelpers.turned_off do
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rspec"
4
- require_relative "rspec/support/pact_consumer_helpers"
5
- require_relative "rspec/support/pact_provider_helpers"
3
+ require 'rspec'
4
+ require 'pact'
5
+ require_relative 'rspec/support/pact_consumer_helpers'
6
+ require_relative 'rspec/support/pact_provider_helpers'
6
7
 
7
8
  RSpec.configure do |config|
8
9
  config.define_derived_metadata(file_path: %r{spec/pact/}) { |metadata| metadata[:pact] = true }
9
10
 
10
- # it's not an error: consumer tests contain `providers` subdirectory (because we're testing against different providers)
11
+ # it's not an error: consumer tests contain `providers` subdirectory (because we're testing against different providers) # rubocop:disable Layout/LineLength
11
12
  config.define_derived_metadata(file_path: %r{spec/pact/providers/}) { |metadata| metadata[:pact_entity] = :consumer }
12
13
  # for provider tests it's the same thing: we're running tests which test consumers
13
14
  config.define_derived_metadata(file_path: %r{spec/pact/consumers/}) { |metadata| metadata[:pact_entity] = :provider }
14
15
 
15
16
  # exclude pact specs from generic rspec pipeline
16
- config.filter_run_excluding :pact_v2
17
+ config.filter_run_excluding :pact
17
18
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:pact).tap do |task|
6
+ task.pattern = 'spec/pact/consumers/**/*_spec.rb'
7
+ task.rspec_opts = '--require rails_helper --tag pact'
8
+ end
9
+
10
+ namespace :pact do
11
+ desc 'Verifies the pact files'
12
+ task verify: :pact
13
+ end
data/lib/pact/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # Remember to bump pact-provider-proxy when this changes major version
2
2
  module Pact
3
- VERSION = "1.67.4"
3
+ VERSION = "2.0.0"
4
4
  end
data/lib/pact.rb CHANGED
@@ -1,12 +1,47 @@
1
- require 'pact/support'
2
- require 'pact/version'
3
- require 'pact/configuration'
4
- require 'pact/consumer'
5
- require 'pact/provider'
6
- require 'pact/consumer_contract'
7
-
8
- begin
9
- require 'pact/v2'
10
- rescue LoadError
11
- # "Please ensure that the 'pact-ffi' gem is included in your Gemfile for pact/v2 support."
1
+ # frozen_string_literal: true
2
+
3
+ require 'zeitwerk'
4
+ require 'pact/ffi'
5
+
6
+ require 'pact/railtie' if defined?(Rails::Railtie)
7
+
8
+ module Pact
9
+ class Error < StandardError; end
10
+
11
+ class ImplementationRequired < Error; end
12
+
13
+ class FfiError < Error
14
+ def initialize(msg, reason, status)
15
+ super(msg)
16
+
17
+ @msg = msg
18
+ @reason = reason
19
+ @status = status
20
+ end
21
+
22
+ def message
23
+ "FFI error: reason: #{@reason}, status: #{@status}, message: #{@msg}"
24
+ end
25
+ end
26
+
27
+ def self.configure
28
+ yield configuration if block_given?
29
+ end
30
+
31
+ def self.configuration
32
+ @configuration ||= Pact::Configuration.new
33
+ end
12
34
  end
35
+
36
+ loader = Zeitwerk::Loader.new
37
+ loader.push_dir(File.join(__dir__))
38
+
39
+ loader.tag = 'pact'
40
+
41
+ loader.ignore("#{__dir__}/pact/version.rb")
42
+ loader.ignore("#{__dir__}/pact/rspec.rb")
43
+ loader.ignore("#{__dir__}/pact/rspec")
44
+ loader.ignore("#{__dir__}/pact/railtie.rb") unless defined?(Rails::Railtie)
45
+
46
+ loader.setup
47
+ loader.eager_load