pact 1.3.3 → 1.4.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 (212) hide show
  1. data/CHANGELOG.md +37 -1
  2. data/lib/pact/cli.rb +0 -26
  3. data/lib/pact/consumer/configuration/configuration_extensions.rb +51 -0
  4. data/lib/pact/consumer/configuration/mock_service.rb +2 -1
  5. data/lib/pact/consumer/configuration.rb +0 -1
  6. data/lib/pact/consumer/consumer_contract_builder.rb +3 -3
  7. data/lib/pact/consumer/interaction_builder.rb +3 -5
  8. data/lib/pact/doc/interaction_view_model.rb +9 -6
  9. data/lib/pact/doc/sort_interactions.rb +1 -1
  10. data/lib/pact/provider/configuration/configuration_extension.rb +0 -9
  11. data/lib/pact/provider/rspec.rb +11 -9
  12. data/lib/pact/version.rb +1 -1
  13. data/lib/pact.rb +6 -5
  14. data/pact.gemspec +6 -2
  15. metadata +57 -304
  16. data/.gitignore +0 -29
  17. data/.rspec +0 -2
  18. data/.ruby-version +0 -1
  19. data/.travis.yml +0 -8
  20. data/Gemfile +0 -4
  21. data/Gemfile.lock +0 -86
  22. data/README.md +0 -313
  23. data/Rakefile +0 -9
  24. data/config.ru +0 -3
  25. data/documentation/README.md +0 -13
  26. data/documentation/configuration.md +0 -166
  27. data/documentation/diff_formatter_embedded.png +0 -0
  28. data/documentation/diff_formatter_list.png +0 -0
  29. data/documentation/diff_formatter_unix.png +0 -0
  30. data/example/animal-service/Gemfile +0 -14
  31. data/example/animal-service/Gemfile.lock +0 -69
  32. data/example/animal-service/Rakefile +0 -5
  33. data/example/animal-service/config.ru +0 -3
  34. data/example/animal-service/db/animal_db.sqlite3 +0 -0
  35. data/example/animal-service/lib/animal_service/animal_repository.rb +0 -12
  36. data/example/animal-service/lib/animal_service/api.rb +0 -28
  37. data/example/animal-service/lib/animal_service/db.rb +0 -5
  38. data/example/animal-service/spec/service_consumers/pact_helper.rb +0 -11
  39. data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +0 -26
  40. data/example/zoo-app/Gemfile +0 -12
  41. data/example/zoo-app/Gemfile.lock +0 -63
  42. data/example/zoo-app/Rakefile +0 -5
  43. data/example/zoo-app/doc/pacts/markdown/README.md +0 -3
  44. data/example/zoo-app/doc/pacts/markdown/Zoo App - Animal Service.md +0 -75
  45. data/example/zoo-app/lib/zoo_app/animal_service_client.rb +0 -40
  46. data/example/zoo-app/lib/zoo_app/models/alligator.rb +0 -15
  47. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +0 -67
  48. data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +0 -71
  49. data/example/zoo-app/spec/service_providers/pact_helper.rb +0 -15
  50. data/example/zoo-app/spec/spec_helper.rb +0 -6
  51. data/lib/pact/configuration.rb +0 -195
  52. data/lib/pact/consumer/app_manager.rb +0 -158
  53. data/lib/pact/consumer/interactions_filter.rb +0 -48
  54. data/lib/pact/consumer/mock_service/app.rb +0 -82
  55. data/lib/pact/consumer/mock_service/interaction_delete.rb +0 -33
  56. data/lib/pact/consumer/mock_service/interaction_list.rb +0 -76
  57. data/lib/pact/consumer/mock_service/interaction_mismatch.rb +0 -73
  58. data/lib/pact/consumer/mock_service/interaction_post.rb +0 -31
  59. data/lib/pact/consumer/mock_service/interaction_replay.rb +0 -139
  60. data/lib/pact/consumer/mock_service/log_get.rb +0 -28
  61. data/lib/pact/consumer/mock_service/missing_interactions_get.rb +0 -30
  62. data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +0 -31
  63. data/lib/pact/consumer/mock_service/pact_post.rb +0 -33
  64. data/lib/pact/consumer/mock_service/rack_request_helper.rb +0 -51
  65. data/lib/pact/consumer/mock_service/verification_get.rb +0 -68
  66. data/lib/pact/consumer/mock_service.rb +0 -2
  67. data/lib/pact/consumer/mock_service_client.rb +0 -65
  68. data/lib/pact/consumer/mock_service_interaction_expectation.rb +0 -37
  69. data/lib/pact/consumer/request.rb +0 -27
  70. data/lib/pact/consumer/server.rb +0 -90
  71. data/lib/pact/consumer_contract/consumer_contract.rb +0 -115
  72. data/lib/pact/consumer_contract/consumer_contract_writer.rb +0 -84
  73. data/lib/pact/consumer_contract/file_name.rb +0 -19
  74. data/lib/pact/consumer_contract/headers.rb +0 -51
  75. data/lib/pact/consumer_contract/interaction.rb +0 -67
  76. data/lib/pact/consumer_contract/pact_file.rb +0 -24
  77. data/lib/pact/consumer_contract/request.rb +0 -73
  78. data/lib/pact/consumer_contract/service_consumer.rb +0 -28
  79. data/lib/pact/consumer_contract/service_provider.rb +0 -28
  80. data/lib/pact/consumer_contract.rb +0 -1
  81. data/lib/pact/logging.rb +0 -14
  82. data/lib/pact/matchers/actual_type.rb +0 -16
  83. data/lib/pact/matchers/base_difference.rb +0 -37
  84. data/lib/pact/matchers/differ.rb +0 -153
  85. data/lib/pact/matchers/difference.rb +0 -13
  86. data/lib/pact/matchers/difference_indicator.rb +0 -26
  87. data/lib/pact/matchers/embedded_diff_formatter.rb +0 -62
  88. data/lib/pact/matchers/expected_type.rb +0 -35
  89. data/lib/pact/matchers/index_not_found.rb +0 -15
  90. data/lib/pact/matchers/list_diff_formatter.rb +0 -101
  91. data/lib/pact/matchers/matchers.rb +0 -139
  92. data/lib/pact/matchers/no_diff_indicator.rb +0 -18
  93. data/lib/pact/matchers/regexp_difference.rb +0 -13
  94. data/lib/pact/matchers/type_difference.rb +0 -16
  95. data/lib/pact/matchers/unexpected_index.rb +0 -11
  96. data/lib/pact/matchers/unexpected_key.rb +0 -11
  97. data/lib/pact/matchers/unix_diff_formatter.rb +0 -114
  98. data/lib/pact/matchers.rb +0 -1
  99. data/lib/pact/reification.rb +0 -28
  100. data/lib/pact/rspec.rb +0 -53
  101. data/lib/pact/shared/active_support_support.rb +0 -51
  102. data/lib/pact/shared/dsl.rb +0 -76
  103. data/lib/pact/shared/jruby_support.rb +0 -18
  104. data/lib/pact/shared/json_differ.rb +0 -15
  105. data/lib/pact/shared/key_not_found.rb +0 -15
  106. data/lib/pact/shared/null_expectation.rb +0 -31
  107. data/lib/pact/shared/request.rb +0 -80
  108. data/lib/pact/shared/text_differ.rb +0 -14
  109. data/lib/pact/something_like.rb +0 -49
  110. data/lib/pact/symbolize_keys.rb +0 -12
  111. data/lib/pact/term.rb +0 -85
  112. data/scratchpad.rb +0 -52
  113. data/spec/features/consumption_spec.rb +0 -114
  114. data/spec/features/production_spec.rb +0 -155
  115. data/spec/features/provider_states/zebras.rb +0 -28
  116. data/spec/integration/consumer_spec.rb +0 -212
  117. data/spec/integration/pact/consumer_configuration_spec.rb +0 -66
  118. data/spec/integration/pact/provider_configuration_spec.rb +0 -25
  119. data/spec/lib/pact/cli_spec.rb +0 -47
  120. data/spec/lib/pact/configuration_spec.rb +0 -297
  121. data/spec/lib/pact/consumer/app_manager_spec.rb +0 -41
  122. data/spec/lib/pact/consumer/configuration_spec.rb +0 -57
  123. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +0 -69
  124. data/spec/lib/pact/consumer/interaction_builder_spec.rb +0 -91
  125. data/spec/lib/pact/consumer/interactions_spec.rb +0 -64
  126. data/spec/lib/pact/consumer/mock_service/app_spec.rb +0 -52
  127. data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +0 -78
  128. data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +0 -70
  129. data/spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb +0 -12
  130. data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +0 -88
  131. data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +0 -142
  132. data/spec/lib/pact/consumer/mock_service_client_spec.rb +0 -88
  133. data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +0 -54
  134. data/spec/lib/pact/consumer/request_spec.rb +0 -24
  135. data/spec/lib/pact/consumer/service_consumer_spec.rb +0 -11
  136. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +0 -58
  137. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +0 -180
  138. data/spec/lib/pact/consumer_contract/consumer_contract_writer_spec.rb +0 -111
  139. data/spec/lib/pact/consumer_contract/headers_spec.rb +0 -107
  140. data/spec/lib/pact/consumer_contract/interaction_spec.rb +0 -107
  141. data/spec/lib/pact/consumer_contract/request_spec.rb +0 -329
  142. data/spec/lib/pact/doc/generator_spec.rb +0 -84
  143. data/spec/lib/pact/doc/interaction_view_model_spec.rb +0 -132
  144. data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +0 -29
  145. data/spec/lib/pact/doc/markdown/index_renderer_spec.rb +0 -29
  146. data/spec/lib/pact/matchers/differ_spec.rb +0 -214
  147. data/spec/lib/pact/matchers/difference_spec.rb +0 -22
  148. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +0 -90
  149. data/spec/lib/pact/matchers/index_not_found_spec.rb +0 -21
  150. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +0 -114
  151. data/spec/lib/pact/matchers/matchers_spec.rb +0 -500
  152. data/spec/lib/pact/matchers/regexp_difference_spec.rb +0 -20
  153. data/spec/lib/pact/matchers/type_difference_spec.rb +0 -34
  154. data/spec/lib/pact/matchers/unexpected_index_spec.rb +0 -20
  155. data/spec/lib/pact/matchers/unexpected_key_spec.rb +0 -20
  156. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +0 -216
  157. data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +0 -30
  158. data/spec/lib/pact/provider/configuration/pact_verification_spec.rb +0 -43
  159. data/spec/lib/pact/provider/configuration/service_provider_config_spec.rb +0 -21
  160. data/spec/lib/pact/provider/configuration/service_provider_dsl_spec.rb +0 -108
  161. data/spec/lib/pact/provider/configuration_spec.rb +0 -50
  162. data/spec/lib/pact/provider/matchers/messages_spec.rb +0 -116
  163. data/spec/lib/pact/provider/pact_helper_locator_spec.rb +0 -54
  164. data/spec/lib/pact/provider/print_missing_provider_states_spec.rb +0 -19
  165. data/spec/lib/pact/provider/request_spec.rb +0 -78
  166. data/spec/lib/pact/provider/rspec/formatter_rspec_2_spec.rb +0 -68
  167. data/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb +0 -72
  168. data/spec/lib/pact/provider/rspec_spec.rb +0 -55
  169. data/spec/lib/pact/provider/state/provider_state_manager_spec.rb +0 -89
  170. data/spec/lib/pact/provider/state/provider_state_proxy_spec.rb +0 -80
  171. data/spec/lib/pact/provider/state/provider_state_spec.rb +0 -213
  172. data/spec/lib/pact/provider/world_spec.rb +0 -41
  173. data/spec/lib/pact/reification_spec.rb +0 -67
  174. data/spec/lib/pact/shared/dsl_spec.rb +0 -86
  175. data/spec/lib/pact/shared/json_differ_spec.rb +0 -36
  176. data/spec/lib/pact/shared/key_not_found_spec.rb +0 -20
  177. data/spec/lib/pact/shared/request_spec.rb +0 -111
  178. data/spec/lib/pact/shared/text_differ_spec.rb +0 -54
  179. data/spec/lib/pact/something_like_spec.rb +0 -21
  180. data/spec/lib/pact/tasks/task_helper_spec.rb +0 -74
  181. data/spec/lib/pact/tasks/verification_task_spec.rb +0 -75
  182. data/spec/lib/pact/term_spec.rb +0 -89
  183. data/spec/pact_specification/compliance-1.0.0.rb +0 -47
  184. data/spec/spec_helper.rb +0 -22
  185. data/spec/standalone/consumer_fail_test.rb +0 -55
  186. data/spec/standalone/consumer_pass_test.rb +0 -51
  187. data/spec/support/a_consumer-a_producer.json +0 -32
  188. data/spec/support/a_consumer-a_provider.json +0 -32
  189. data/spec/support/active_support_if_configured.rb +0 -6
  190. data/spec/support/app_for_config_ru.rb +0 -4
  191. data/spec/support/consumer_contract_template.json +0 -24
  192. data/spec/support/dsl_spec_support.rb +0 -7
  193. data/spec/support/factories.rb +0 -82
  194. data/spec/support/generated_index.md +0 -4
  195. data/spec/support/generated_markdown.md +0 -55
  196. data/spec/support/interaction_view_model.json +0 -63
  197. data/spec/support/interaction_view_model_with_terms.json +0 -50
  198. data/spec/support/markdown_pact.json +0 -48
  199. data/spec/support/missing_provider_states_output.txt +0 -25
  200. data/spec/support/options.json +0 -21
  201. data/spec/support/options_app.rb +0 -15
  202. data/spec/support/pact_helper.rb +0 -57
  203. data/spec/support/shared_examples_for_request.rb +0 -94
  204. data/spec/support/spec_support.rb +0 -20
  205. data/spec/support/stubbing.json +0 -22
  206. data/spec/support/stubbing_using_allow.rb +0 -29
  207. data/spec/support/term.json +0 -48
  208. data/spec/support/test_app_fail.json +0 -61
  209. data/spec/support/test_app_pass.json +0 -38
  210. data/spec/support/test_app_with_right_content_type_differ.json +0 -23
  211. data/tasks/pact-test.rake +0 -109
  212. data/tasks/spec.rake +0 -8
@@ -1,31 +0,0 @@
1
- require 'pact/consumer/mock_service/rack_request_helper'
2
- module Pact
3
- module Consumer
4
- class MockServiceAdministrationEndpoint
5
-
6
- attr_accessor :logger, :name
7
-
8
- def initialize name, logger
9
- @name = name
10
- @logger = logger
11
- end
12
-
13
- include RackRequestHelper
14
-
15
- def match? env
16
- headers_from(env)['X-Pact-Mock-Service'] &&
17
- env['REQUEST_PATH'] == request_path &&
18
- env['REQUEST_METHOD'] == request_method
19
- end
20
-
21
- def request_path
22
- raise NotImplementedError
23
- end
24
-
25
- def request_method
26
- raise NotImplementedError
27
- end
28
-
29
- end
30
- end
31
- end
@@ -1,33 +0,0 @@
1
- require 'pact/consumer/mock_service/mock_service_administration_endpoint'
2
- require 'pact/consumer_contract/consumer_contract_writer'
3
-
4
- module Pact
5
- module Consumer
6
- class PactPost < MockServiceAdministrationEndpoint
7
-
8
- attr_accessor :consumer_contract, :interactions
9
-
10
- def initialize name, logger, interactions
11
- super name, logger
12
- @interactions = interactions
13
- end
14
-
15
- def request_path
16
- '/pact'
17
- end
18
-
19
- def request_method
20
- 'POST'
21
- end
22
-
23
- def respond env
24
- consumer_contract_details = JSON.parse(env['rack.input'].string, symbolize_names: true)
25
- logger.info "Writing pact with details #{consumer_contract_details}"
26
- consumer_contract_writer = ConsumerContractWriter.new(consumer_contract_details.merge(interactions: interactions), logger)
27
- json = consumer_contract_writer.write
28
-
29
- [200, {'Content-Type' =>'application/json'}, [json]]
30
- end
31
- end
32
- end
33
- end
@@ -1,51 +0,0 @@
1
- module Pact
2
- module Consumer
3
-
4
- module RackRequestHelper
5
- REQUEST_KEYS = {
6
- 'REQUEST_METHOD' => :method,
7
- 'PATH_INFO' => :path,
8
- 'QUERY_STRING' => :query,
9
- 'rack.input' => :body
10
- }
11
-
12
- def params_hash env
13
- env["QUERY_STRING"].split("&").collect{| param| param.split("=")}.inject({}){|params, param| params[param.first] = URI.decode(param.last); params }
14
- end
15
-
16
- def request_as_hash_from env
17
- request = env.inject({}) do |memo, (k, v)|
18
- request_key = REQUEST_KEYS[k]
19
- memo[request_key] = v if request_key
20
- memo
21
- end
22
-
23
- request[:headers] = headers_from env
24
- body_string = request[:body].read
25
-
26
- if body_string.empty?
27
- request.delete :body
28
- else
29
- body_is_json = request[:headers]['Content-Type'] =~ /json/
30
- request[:body] = body_is_json ? JSON.parse(body_string) : body_string
31
- end
32
- request[:method] = request[:method].downcase
33
- request
34
- end
35
-
36
- private
37
-
38
- def headers_from env
39
- headers = env.reject{ |key, value| !(key.start_with?("HTTP") || key == 'CONTENT_TYPE' || key == 'CONTENT_LENGTH')}
40
- headers.inject({}) do | hash, header |
41
- hash[standardise_header(header.first)] = header.last
42
- hash
43
- end
44
- end
45
-
46
- def standardise_header header
47
- header.gsub(/^HTTP_/, '').split("_").collect{|word| word[0] + word[1..-1].downcase}.join("-")
48
- end
49
- end
50
- end
51
- end
@@ -1,68 +0,0 @@
1
- require 'pact/consumer/mock_service/mock_service_administration_endpoint'
2
-
3
- module Pact
4
- module Consumer
5
- class VerificationGet < MockServiceAdministrationEndpoint
6
-
7
- include RackRequestHelper
8
- attr_accessor :interaction_list, :log_description
9
-
10
- def initialize name, logger, interaction_list, log_description
11
- super name, logger
12
- @interaction_list = interaction_list
13
- @log_description = log_description
14
- end
15
-
16
- def request_path
17
- '/interactions/verification'
18
- end
19
-
20
- def request_method
21
- 'GET'
22
- end
23
-
24
- def respond env
25
- if interaction_list.all_matched?
26
- logger.info "Verifying - interactions matched for example \"#{example_description(env)}\""
27
- [200, {'Content-Type' => 'text/plain'}, ['Interactions matched']]
28
- else
29
- error_message = FailureMessage.new(interaction_list).to_s
30
- logger.warn "Verifying - actual interactions do not match expected interactions for example \"#{example_description(env)}\". \n#{error_message}"
31
- logger.warn error_message
32
- [500, {'Content-Type' => 'text/plain'}, ["Actual interactions do not match expected interactions for mock #{name}.\n\n#{error_message}See #{log_description} for details."]]
33
- end
34
- end
35
-
36
- def example_description env
37
- params_hash(env)['example_description']
38
- end
39
-
40
- class FailureMessage
41
-
42
- def initialize interaction_list
43
- @interaction_list = interaction_list
44
- end
45
-
46
- def to_s
47
- titles_and_summaries.collect do | title, summaries |
48
- "#{title}:\n\t#{summaries.join("\n\t")}\n\n" if summaries.any?
49
- end.compact.join
50
-
51
- end
52
-
53
- private
54
-
55
- attr_reader :interaction_list
56
-
57
- def titles_and_summaries
58
- {
59
- "Incorrect requests" => interaction_list.interaction_mismatches_summaries,
60
- "Missing requests" => interaction_list.missing_interactions_summaries,
61
- "Unexpected requests" => interaction_list.unexpected_requests_summaries,
62
- }
63
- end
64
-
65
- end
66
- end
67
- end
68
- end
@@ -1,2 +0,0 @@
1
- require 'pact/consumer/mock_service/app'
2
-
@@ -1,65 +0,0 @@
1
- require 'net/http'
2
- require 'pact/consumer/mock_service_interaction_expectation'
3
-
4
- module Pact
5
- module Consumer
6
- class MockServiceClient
7
-
8
- MOCK_SERVICE_ADMINISTRATON_HEADERS = {'X-Pact-Mock-Service' => 'true'}
9
-
10
- def initialize port
11
- @http = Net::HTTP.new('localhost', port)
12
- end
13
-
14
- def verify example_description
15
- response = http.request_get("/interactions/verification?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
16
- raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
17
- end
18
-
19
- def log msg
20
- http.request_get("/log?msg=#{URI.encode(msg)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
21
- end
22
-
23
- def wait_for_interactions wait_max_seconds, poll_interval
24
- wait_until_true(wait_max_seconds, poll_interval) do
25
- response = http.request_get("/interactions/missing", MOCK_SERVICE_ADMINISTRATON_HEADERS)
26
- JSON.parse(response.body)['size'] == 0
27
- end
28
- end
29
-
30
- def clear_interactions example_description
31
- http.delete("/interactions?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
32
- end
33
-
34
- def add_expected_interaction interaction
35
- response = http.request_post('/interactions', MockServiceInteractionExpectation.new(interaction).to_json, MOCK_SERVICE_ADMINISTRATON_HEADERS.merge("Content-Type" => "application/json"))
36
- raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
37
- end
38
-
39
- def self.clear_interactions port, example_description
40
- Net::HTTP.new("localhost", port).delete("/interactions?example_description=#{URI.encode(example_description)}", MOCK_SERVICE_ADMINISTRATON_HEADERS)
41
- end
42
-
43
- def write_pact pacticipant_details
44
- response = http.request_post("/pact", pacticipant_details.to_json, MOCK_SERVICE_ADMINISTRATON_HEADERS.merge("Content-Type" => "application/json"))
45
- raise "\e[31m#{response.body}\e[m" unless response.is_a? Net::HTTPSuccess
46
- response.body
47
- end
48
-
49
- private
50
-
51
- attr_reader :http
52
-
53
- #todo: in need a better home (where can we move it?)
54
- def wait_until_true timeout=3, interval=0.1
55
- time_limit = Time.now + timeout
56
- loop do
57
- result = yield
58
- return if result || Time.now >= time_limit
59
- sleep interval
60
- end
61
- end
62
-
63
- end
64
- end
65
- end
@@ -1,37 +0,0 @@
1
- require 'pact/reification'
2
-
3
- # Represents the Interaction in the form required by the MockService
4
- # The json generated will be posted to the MockService to register the expectation
5
- module Pact
6
- module Consumer
7
- class MockServiceInteractionExpectation
8
-
9
-
10
- def initialize interaction
11
- @interaction = interaction
12
- end
13
-
14
- def to_hash
15
- hash = {:description => interaction.description}
16
- hash[:provider_state] = interaction.provider_state if interaction.provider_state
17
- options = interaction.request.options.empty? ? {} : { options: interaction.request.options}
18
- hash[:request] = interaction.request.as_json.merge(options)
19
- hash[:response] = interaction.response
20
- hash
21
- end
22
-
23
- def as_json options = {}
24
- to_hash
25
- end
26
-
27
- def to_json opts = {}
28
- as_json.to_json(opts)
29
- end
30
-
31
- private
32
-
33
- attr_reader :interaction
34
-
35
- end
36
- end
37
- end
@@ -1,27 +0,0 @@
1
- require 'pact/shared/request'
2
- require 'pact/shared/key_not_found'
3
-
4
- module Pact
5
- module Consumer
6
- module Request
7
- class Actual < Pact::Request::Base
8
-
9
- def self.from_hash(hash)
10
- sym_hash = symbolize_keys hash
11
- method = sym_hash.fetch(:method)
12
- path = sym_hash.fetch(:path)
13
- query = sym_hash.fetch(:query)
14
- headers = sym_hash.fetch(:headers)
15
- body = sym_hash.fetch(:body, nil)
16
- new(method, path, headers, body, query)
17
- end
18
-
19
- protected
20
-
21
- def self.key_not_found
22
- nil
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,90 +0,0 @@
1
- require 'uri'
2
- require 'net/http'
3
- require 'rack'
4
-
5
- # Copied shamelessly from Capybara
6
- module Pact
7
- class Server
8
- class Middleware
9
- attr_accessor :error
10
-
11
- def initialize(app)
12
- @app = app
13
- end
14
-
15
- def call(env)
16
- if env["PATH_INFO"] == "/__identify__"
17
- [200, {}, [@app.object_id.to_s]]
18
- else
19
- begin
20
- @app.call(env)
21
- rescue StandardError => e
22
- @error = e unless @error
23
- raise e
24
- end
25
- end
26
- end
27
- end
28
-
29
- class << self
30
- def ports
31
- @ports ||= {}
32
- end
33
- end
34
-
35
- attr_reader :app, :port
36
-
37
- def initialize(app, port)
38
- @app = app
39
- @middleware = Middleware.new(@app)
40
- @server_thread = nil # supress warnings
41
- @port = port
42
- end
43
-
44
- def reset_error!
45
- @middleware.error = nil
46
- end
47
-
48
- def error
49
- @middleware.error
50
- end
51
-
52
- def host
53
- "localhost"
54
- end
55
-
56
- def responsive?
57
- return false if @server_thread && @server_thread.join(0)
58
-
59
- res = Net::HTTP.start(host, @port) { |http| http.get('/__identify__') }
60
-
61
- if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
62
- return res.body == @app.object_id.to_s
63
- end
64
- rescue SystemCallError
65
- return false
66
- end
67
-
68
- def run_default_server(app, port)
69
- require 'rack/handler/webrick'
70
- Rack::Handler::WEBrick.run(app, :Port => port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
71
- end
72
-
73
- def boot
74
- unless responsive?
75
- Pact::Server.ports[@app.object_id] = @port
76
-
77
- @server_thread = Thread.new do
78
- run_default_server(@middleware, @port)
79
- end
80
-
81
- Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }
82
- end
83
- rescue Timeout::Error
84
- raise "Rack application timed out during boot"
85
- else
86
- self
87
- end
88
-
89
- end
90
- end
@@ -1,115 +0,0 @@
1
- require 'pact/logging'
2
- require 'pact/something_like'
3
- require 'pact/symbolize_keys'
4
- require 'pact/term'
5
- require 'pact/version'
6
- require 'pact/shared/active_support_support'
7
- require 'date'
8
- require 'json/add/regexp'
9
- require 'open-uri'
10
- require_relative 'service_consumer'
11
- require_relative 'service_provider'
12
- require_relative 'interaction'
13
- require_relative 'request'
14
- require_relative 'pact_file'
15
- require_relative 'file_name'
16
-
17
-
18
-
19
- module Pact
20
-
21
- class ConsumerContract
22
-
23
- include SymbolizeKeys
24
- include Logging
25
- include FileName
26
- include ActiveSupportSupport
27
-
28
- attr_accessor :interactions
29
- attr_accessor :consumer
30
- attr_accessor :provider
31
-
32
- def initialize(attributes = {})
33
- @interactions = attributes[:interactions] || []
34
- @consumer = attributes[:consumer]
35
- @provider = attributes[:provider]
36
- end
37
-
38
- def to_hash
39
- {
40
- provider: @provider.as_json,
41
- consumer: @consumer.as_json,
42
- interactions: @interactions.collect(&:as_json),
43
- metadata: {
44
- pactSpecificationVersion: "1.0.0"
45
- }
46
- }
47
- end
48
-
49
- def as_json(options = {})
50
- fix_all_the_things to_hash
51
- end
52
-
53
- def to_json(options = {})
54
- as_json.to_json(options)
55
- end
56
-
57
- def self.from_hash(hash)
58
- hash = symbolize_keys(hash)
59
- new({
60
- :interactions => hash[:interactions].collect { |hash| Interaction.from_hash(hash)},
61
- :consumer => ServiceConsumer.from_hash(hash[:consumer]),
62
- :provider => ServiceProvider.from_hash(hash[:provider])
63
- })
64
- end
65
-
66
- def self.from_json string
67
- deserialised_object = JSON.load(maintain_backwards_compatiblity_with_producer_keys(string))
68
- from_hash(deserialised_object)
69
- end
70
-
71
- def self.from_uri uri, options = {}
72
- from_json(Pact::PactFile.read(uri, options))
73
- end
74
-
75
- def self.maintain_backwards_compatiblity_with_producer_keys string
76
- string.gsub('"producer":', '"provider":').gsub('"producer_state":', '"provider_state":')
77
- end
78
-
79
- def find_interaction criteria
80
- interactions = find_interactions criteria
81
- if interactions.size == 0
82
- raise "Could not find interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
83
- elsif interactions.size > 1
84
- raise "Found more than 1 interaction matching #{criteria} in pact file between #{consumer.name} and #{provider.name}."
85
- end
86
- interactions.first
87
- end
88
-
89
- def find_interactions criteria
90
- interactions.select{ | interaction| interaction.matches_criteria?(criteria)}
91
- end
92
-
93
- def each
94
- interactions.each do | interaction |
95
- yield interaction
96
- end
97
- end
98
-
99
- def pact_file_name
100
- file_name consumer.name, provider.name
101
- end
102
-
103
- def pactfile_path
104
- raise 'You must first specify a consumer and service name' unless (consumer && consumer.name && provider && provider.name)
105
- @pactfile_path ||= file_path consumer.name, provider.name
106
- end
107
-
108
- def update_pactfile
109
- logger.debug "Updating pact file for #{provider.name} at #{pactfile_path}"
110
- File.open(pactfile_path, 'w') do |f|
111
- f.write fix_json_formatting(JSON.pretty_generate(self))
112
- end
113
- end
114
- end
115
- end
@@ -1,84 +0,0 @@
1
- require 'pact/consumer_contract'
2
- require 'pact/consumer/interactions_filter'
3
- require 'pact/consumer_contract/file_name'
4
-
5
- module Pact
6
-
7
- class ConsumerContractWriter
8
-
9
- attr_reader :consumer_contract_details, :pactfile_write_mode, :interactions, :logger
10
-
11
- def initialize consumer_contract_details, logger
12
- @logger = logger
13
- @consumer_contract_details = consumer_contract_details
14
- @pactfile_write_mode = consumer_contract_details.fetch(:pactfile_write_mode, :overwrite).to_sym
15
- @interactions = consumer_contract_details.fetch(:interactions)
16
- end
17
-
18
- def consumer_contract
19
- @consumer_contract ||= Pact::ConsumerContract.new(
20
- consumer: ServiceConsumer.new(name: consumer_contract_details[:consumer][:name]),
21
- provider: ServiceProvider.new(name: consumer_contract_details[:provider][:name]),
22
- interactions: interactions_for_new_consumer_contract)
23
- end
24
-
25
- def write
26
- consumer_contract.update_pactfile
27
- consumer_contract.to_json
28
- end
29
-
30
- def interactions_for_new_consumer_contract
31
- if pactfile_write_mode == :update
32
- merged_interactions = existing_interactions
33
- filter = Consumer::UpdatableInteractionsFilter.new(merged_interactions)
34
- interactions.each {|i| filter << i }
35
- merged_interactions
36
- else
37
- interactions
38
- end
39
- end
40
-
41
- def existing_interactions
42
- interactions = []
43
- if pactfile_exists?
44
- begin
45
- interactions = existing_consumer_contract.interactions
46
- info_and_puts "*****************************************************************************"
47
- info_and_puts "Updating existing file .#{pactfile_path.gsub(Dir.pwd, '')} as config.pactfile_write_mode is :update"
48
- info_and_puts "Only interactions defined in this test run will be updated."
49
- info_and_puts "As interactions are identified by description and provider state, pleased note that if either of these have changed, the old interactions won't be removed from the pact file until the specs are next run with :pactfile_write_mode => :overwrite."
50
- info_and_puts "*****************************************************************************"
51
- rescue StandardError => e
52
- warn_and_stderr "Could not load existing consumer contract from #{pactfile_path} due to #{e}"
53
- logger.error e
54
- logger.error e.backtrace
55
- warn_and_stderr "Creating a new file."
56
- end
57
- end
58
- interactions
59
- end
60
-
61
- def pactfile_exists?
62
- File.exist?(pactfile_path)
63
- end
64
-
65
- def pactfile_path
66
- Pact::FileName.file_path consumer_contract_details[:consumer][:name], consumer_contract_details[:provider][:name]
67
- end
68
-
69
- def existing_consumer_contract
70
- Pact::ConsumerContract.from_uri(pactfile_path)
71
- end
72
-
73
- def warn_and_stderr msg
74
- Pact.configuration.error_stream.puts msg
75
- logger.warn msg
76
- end
77
-
78
- def info_and_puts msg
79
- $stdout.puts msg
80
- logger.info msg
81
- end
82
- end
83
-
84
- end
@@ -1,19 +0,0 @@
1
- module Pact
2
-
3
- module FileName
4
-
5
- extend self
6
-
7
- def file_name consumer_name, provider_name
8
- "#{filenamify(consumer_name)}-#{filenamify(provider_name)}.json"
9
- end
10
-
11
- def file_path consumer_name, provider_name, pact_dir = Pact.configuration.pact_dir
12
- File.join(pact_dir, file_name(consumer_name, provider_name))
13
- end
14
-
15
- def filenamify name
16
- name.downcase.gsub(/\s/, '_')
17
- end
18
- end
19
- end
@@ -1,51 +0,0 @@
1
- module Pact
2
-
3
- class DuplicateHeaderError < StandardError; end
4
- class InvalidHeaderNameTypeError < StandardError; end
5
-
6
- class Headers < Hash
7
-
8
- def initialize hash = {}
9
- hash.each_pair do | key, value |
10
- check_for_invalid key
11
- self[find_matching_key(key)] = value
12
- end
13
- self.freeze
14
- end
15
-
16
- def [] key
17
- super(find_matching_key(key))
18
- end
19
-
20
- def fetch *args, &block
21
- args[0] = find_matching_key(args[0]) if args.first
22
- super(*args, &block)
23
- end
24
-
25
- def key? key
26
- super(find_matching_key(key))
27
- end
28
-
29
- alias_method :has_key?, :key?
30
- alias_method :include?, :key?
31
-
32
- private
33
-
34
- def find_matching_key key
35
- key = key.to_s
36
- match = keys.find { |k| k.downcase == key.downcase }
37
- match.nil? ? key : match
38
- end
39
-
40
- def check_for_invalid key
41
- unless (String === key || Symbol === key)
42
- raise InvalidHeaderNameTypeError.new "Header name (#{key}) must be a String or a Symbol."
43
- end
44
- if key? key
45
- raise DuplicateHeaderError.new "Duplicate header found (#{find_matching_key(key)} and #{key}. Please use a comma separated single value when multiple headers with the same name are required."
46
- end
47
- end
48
-
49
- end
50
-
51
- end