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,158 +0,0 @@
1
- require 'thwait'
2
-
3
- require 'net/http'
4
- require 'uri'
5
- require 'find_a_port'
6
- require 'pact/logging'
7
- require 'pact/consumer/server'
8
- require 'singleton'
9
-
10
- module Pact
11
- module Consumer
12
- class AppManager
13
-
14
- include Pact::Logging
15
-
16
- include Singleton
17
-
18
- def initialize
19
- @apps_spawned = false
20
- @app_registrations = []
21
- end
22
-
23
- def register_mock_service_for name, url
24
- uri = URI(url)
25
- raise "Currently only http is supported" unless uri.scheme == 'http'
26
- raise "Currently only services on localhost are supported" unless uri.host == 'localhost'
27
-
28
- register(MockService.new(log_file: create_log_file(name), name: name), uri.port)
29
- end
30
-
31
- def register(app, port = FindAPort.available_port)
32
- existing = existing_app_on_port port
33
- raise "Port #{port} is already being used by #{existing}" if existing and not existing == app
34
- app_registration = register_app app, port
35
- app_registration.spawn if @apps_spawned
36
- port
37
- end
38
-
39
- def existing_app_on_port port
40
- app_registration = @app_registrations.find { |app_registration| app_registration.port == port }
41
- app_registration ? app_registration.app : nil
42
- end
43
-
44
- def app_registered_on?(port)
45
- app_registrations.any? { |app_registration| app_registration.port == port }
46
- end
47
-
48
- def ports_of_mock_services
49
- app_registrations.find_all(&:is_a_mock_service?).collect(&:port)
50
- end
51
-
52
- def kill_all
53
- app_registrations.find_all(&:spawned?).collect(&:kill)
54
- @apps_spawned = false
55
- end
56
-
57
- def clear_all
58
- kill_all
59
- @app_registrations = []
60
- end
61
-
62
- def spawn_all
63
- app_registrations.find_all(&:not_spawned?).collect(&:spawn)
64
- @apps_spawned = true
65
- end
66
-
67
- private
68
-
69
- def create_log_file service_name
70
- FileUtils::mkdir_p Pact.configuration.log_dir
71
- log = File.open(log_file_path(service_name), 'w')
72
- log.sync = true
73
- log
74
- end
75
-
76
- def log_file_path service_name
77
- File.join(Pact.configuration.log_dir, "#{log_file_name(service_name)}.log")
78
- end
79
-
80
- def log_file_name service_name
81
- lower_case_name = service_name.downcase.gsub(/\s+/, '_')
82
- if lower_case_name.include?('_service')
83
- lower_case_name.gsub('_service', '_mock_service')
84
- else
85
- lower_case_name + '_mock_service'
86
- end
87
- end
88
-
89
- def app_registrations
90
- @app_registrations
91
- end
92
-
93
- def register_app app, port
94
- app_registration = AppRegistration.new :app => app, :port => port
95
- app_registrations << app_registration
96
- app_registration
97
- end
98
- end
99
-
100
- class AppRegistration
101
- include Pact::Logging
102
- attr_accessor :port
103
- attr_accessor :app
104
- attr_accessor :pid
105
-
106
- def initialize opts
107
- @max_wait = 10
108
- @port = opts[:port]
109
- @pid = opts[:pid]
110
- @app = opts[:app]
111
- end
112
-
113
- def kill
114
- # TODO: need to work out how to kill
115
- # logger.info "Killing #{self}"
116
- # Process.kill(9, pid)
117
- # Process.wait(pid)
118
- # self.pid = nil
119
- self.pid = nil
120
- end
121
-
122
- def not_spawned?
123
- !spawned?
124
- end
125
-
126
- def spawned?
127
- self.pid != nil
128
- end
129
-
130
- def is_a_mock_service?
131
- app.is_a? MockService
132
- end
133
-
134
- def to_s
135
- "#{app} on port #{port}" + (@pid ? " with pid #{pid}" : "")
136
- end
137
-
138
- def spawn
139
- logger.info "Starting app #{self}..."
140
- Pact::Server.new(app, port).boot
141
- self.pid = 'unknown'
142
- logger.info "Started with pid #{pid}"
143
- end
144
-
145
- def wait_until
146
- waited = 0
147
- wait_time = 0.1
148
- while waited < @max_wait do
149
- break if yield
150
- sleep wait_time
151
- waited += wait_time
152
- raise "Waited longer than #{@max_wait} seconds" if waited >= @max_wait
153
- end
154
- end
155
-
156
- end
157
- end
158
- end
@@ -1,48 +0,0 @@
1
- #
2
- # When running in pactfile_write_mode :overwrite, all interactions are cleared from the
3
- # pact file, and all new interactions should be distinct (unique description and provider state).
4
- # When running in pactfile_write_mode :update, an interaction with the same description
5
- # and provider state as an existing one will just overwrite that one interaction.
6
- #
7
-
8
- module Pact
9
- module Consumer
10
-
11
- #TODO: think of a better word than filter
12
- class InteractionsFilter
13
- def initialize interactions = []
14
- @interactions = interactions
15
- end
16
-
17
- def index_of interaction
18
- @interactions.find_index{ |i| i.matches_criteria?(description: interaction.description, provider_state: interaction.provider_state)}
19
- end
20
- end
21
-
22
- class UpdatableInteractionsFilter < InteractionsFilter
23
-
24
- def << interaction
25
- if (ndx = index_of(interaction))
26
- @interactions[ndx] = interaction
27
- else
28
- @interactions << interaction
29
- end
30
- end
31
-
32
- end
33
-
34
- class DistinctInteractionsFilter < InteractionsFilter
35
-
36
- def << interaction
37
- if (ndx = index_of(interaction))
38
- if @interactions[ndx] != interaction
39
- raise "Interaction with same description (#{interaction.description}) and provider state (#{interaction.provider_state}) already exists"
40
- end
41
- else
42
- @interactions << interaction
43
- end
44
- end
45
- end
46
-
47
- end
48
- end
@@ -1,82 +0,0 @@
1
- require 'uri'
2
- require 'json'
3
- require 'logger'
4
- require 'awesome_print'
5
- require 'awesome_print/core_ext/logger' #For some reason we get an error indicating that the method 'ap' is private unless we load this specifically
6
- require 'pact/consumer/request'
7
- require 'pact/consumer/mock_service/interaction_list'
8
- require 'pact/consumer/mock_service/interaction_delete'
9
- require 'pact/consumer/mock_service/interaction_post'
10
- require 'pact/consumer/mock_service/interaction_replay'
11
- require 'pact/consumer/mock_service/missing_interactions_get'
12
- require 'pact/consumer/mock_service/verification_get'
13
- require 'pact/consumer/mock_service/log_get'
14
- require 'pact/consumer/mock_service/pact_post'
15
-
16
- AwesomePrint.defaults = {
17
- indent: -2,
18
- plain: true,
19
- index: false
20
- }
21
-
22
- module Pact
23
- module Consumer
24
-
25
- class MockService
26
-
27
- def initialize options = {}
28
- log_description = configure_logger options
29
- interaction_list = InteractionList.new
30
-
31
- @name = options.fetch(:name, "MockService")
32
- interactions = []
33
- @handlers = [
34
- MissingInteractionsGet.new(@name, @logger, interaction_list),
35
- VerificationGet.new(@name, @logger, interaction_list, log_description),
36
- InteractionPost.new(@name, @logger, interaction_list),
37
- InteractionDelete.new(@name, @logger, interaction_list),
38
- LogGet.new(@name, @logger),
39
- PactPost.new(@name, @logger, interactions),
40
- InteractionReplay.new(@name, @logger, interaction_list, interactions)
41
- ]
42
- end
43
-
44
- def configure_logger options
45
- options = {log_file: $stdout}.merge options
46
- log_stream = options[:log_file]
47
- @logger = Logger.new log_stream
48
- @logger.level = Pact.configuration.logger.level
49
-
50
- if log_stream.is_a? File
51
- File.absolute_path(log_stream).gsub(Dir.pwd + "/", '')
52
- else
53
- "standard out/err"
54
- end
55
- end
56
-
57
- def to_s
58
- "#{@name} #{super.to_s}"
59
- end
60
-
61
- def call env
62
- response = []
63
- begin
64
- relevant_handler = @handlers.detect { |handler| handler.match? env }
65
- response = relevant_handler.respond env
66
- rescue StandardError => e
67
- @logger.error 'Error ocurred in mock service:'
68
- @logger.ap e, :error
69
- @logger.ap e.backtrace
70
- response = [500, {'Content-Type' => 'application/json'}, [{message: e.message, backtrace: e.backtrace}.to_json]]
71
- rescue Exception => e
72
- @logger.error 'Exception ocurred in mock service:'
73
- @logger.ap e, :error
74
- @logger.ap e.backtrace
75
- raise e
76
- end
77
- response
78
- end
79
-
80
- end
81
- end
82
- end
@@ -1,33 +0,0 @@
1
- require 'pact/consumer/mock_service/rack_request_helper'
2
- require 'pact/consumer/mock_service/mock_service_administration_endpoint'
3
-
4
- module Pact
5
- module Consumer
6
-
7
- class InteractionDelete < MockServiceAdministrationEndpoint
8
-
9
- include RackRequestHelper
10
-
11
- attr_accessor :interaction_list
12
-
13
- def initialize name, logger, interaction_list
14
- super name, logger
15
- @interaction_list = interaction_list
16
- end
17
-
18
- def request_path
19
- '/interactions'
20
- end
21
-
22
- def request_method
23
- 'DELETE'
24
- end
25
-
26
- def respond env
27
- interaction_list.clear
28
- logger.info "Cleared interactions before example \"#{params_hash(env)['example_description']}\""
29
- [200, {}, ['Deleted interactions']]
30
- end
31
- end
32
- end
33
- end
@@ -1,76 +0,0 @@
1
- module Pact
2
- module Consumer
3
- class InteractionList
4
-
5
- attr_reader :interactions
6
- attr_reader :unexpected_requests
7
- attr_reader :interaction_mismatches
8
-
9
- def initialize
10
- clear
11
- end
12
-
13
- # For testing, sigh
14
- def clear
15
- @interactions = []
16
- @matched_interactions = []
17
- @interaction_mismatches = []
18
- @unexpected_requests = []
19
- end
20
-
21
- def add interactions
22
- @interactions << interactions
23
- end
24
-
25
- def register_matched interaction
26
- @matched_interactions << interaction
27
- end
28
-
29
- def register_unexpected_request request
30
- @unexpected_requests << request
31
- end
32
-
33
- def register_interaction_mismatch interaction_mismatch
34
- @interaction_mismatches << interaction_mismatch
35
- end
36
-
37
- def all_matched?
38
- interaction_diffs.empty?
39
- end
40
-
41
- def missing_interactions
42
- @interactions - @matched_interactions - @interaction_mismatches.collect(&:candidate_interactions).flatten
43
- end
44
-
45
- def missing_interactions_summaries
46
- missing_interactions.collect(&:request).collect(&:method_and_path)
47
- end
48
-
49
- def interaction_mismatches_summaries
50
- interaction_mismatches.collect(&:short_summary)
51
- end
52
-
53
- def unexpected_requests_summaries
54
- unexpected_requests.collect(&:method_and_path)
55
- end
56
-
57
- def interaction_diffs
58
- {
59
- :missing_interactions => missing_interactions_summaries,
60
- :interaction_mismatches => interaction_mismatches_summaries,
61
- :unexpected_requests => unexpected_requests_summaries
62
- }.inject({}) do | hash, pair |
63
- hash[pair.first] = pair.last if pair.last.any?
64
- hash
65
- end
66
- end
67
-
68
- def find_candidate_interactions actual_request
69
- interactions.select do | interaction |
70
- interaction.request.matches_route? actual_request
71
- end
72
- end
73
-
74
- end
75
- end
76
- end
@@ -1,73 +0,0 @@
1
- module Pact
2
- module Consumer
3
-
4
- # Presents the differences between an actual request, and a list of
5
- # expected interactions where the methods and paths match the actual request.
6
- # This is used to display a helpful message to the user when a request
7
- # comes in that doesn't match any of the expected interactions.
8
- class InteractionMismatch
9
-
10
- attr_accessor :candidate_interactions, :actual_request
11
-
12
- # Assumes the method and path matches...
13
-
14
- def initialize candidate_interactions, actual_request
15
- @candidate_interactions = candidate_interactions
16
- @actual_request = actual_request
17
- @candiate_diffs = candidate_interactions.collect{ | candidate_interaction| CandidateDiff.new(candidate_interaction, actual_request)}
18
- end
19
-
20
- def to_hash
21
- candiate_diffs.collect(&:to_hash)
22
- end
23
-
24
- def to_s
25
- candiate_diffs.collect(&:to_s).join("\n")
26
- end
27
-
28
- def short_summary
29
- mismatched_attributes = candiate_diffs.collect(&:mismatched_attributes).flatten.uniq.join(", ").reverse.sub(",", "dna ").reverse #OMG what a hack!
30
- actual_request.method_and_path + " (request #{mismatched_attributes} did not match)"
31
- end
32
-
33
- private
34
-
35
- attr_accessor :candiate_diffs
36
-
37
- class CandidateDiff
38
-
39
- attr_accessor :candidate_interaction, :actual_request
40
-
41
- def initialize candidate_interaction, actual_request
42
- @candidate_interaction = candidate_interaction
43
- @actual_request = actual_request
44
- end
45
-
46
- def mismatched_attributes
47
- diff.keys
48
- end
49
-
50
- def to_hash
51
- summary = {:description => candidate_interaction.description}
52
- summary[:provider_state] = candidate_interaction.provider_state if candidate_interaction.provider_state
53
- summary.merge(diff)
54
- end
55
-
56
- def to_s
57
- [
58
- "Diff with interaction: #{candidate_interaction.description_with_provider_state_quoted}",
59
- diff_formatter.call(diff, {colour: false})
60
- ].join("\n")
61
- end
62
-
63
- def diff_formatter
64
- Pact.configuration.diff_formatter_for_content_type(candidate_interaction.request.content_type)
65
- end
66
-
67
- def diff
68
- @diff ||= candidate_interaction.request.difference(actual_request)
69
- end
70
- end
71
- end
72
- end
73
- end
@@ -1,31 +0,0 @@
1
- require 'pact/consumer/mock_service/mock_service_administration_endpoint'
2
-
3
- module Pact
4
- module Consumer
5
- class InteractionPost < MockServiceAdministrationEndpoint
6
-
7
- attr_accessor :interaction_list
8
-
9
- def initialize name, logger, interaction_list
10
- super name, logger
11
- @interaction_list = interaction_list
12
- end
13
-
14
- def request_path
15
- '/interactions'
16
- end
17
-
18
- def request_method
19
- 'POST'
20
- end
21
-
22
- def respond env
23
- interaction = Interaction.from_hash(JSON.load(env['rack.input'].string))
24
- interaction_list.add interaction
25
- logger.info "Registered expected interaction #{interaction.request.method_and_path}"
26
- logger.debug JSON.pretty_generate JSON.parse(interaction.to_json)
27
- [200, {}, ['Added interaction']]
28
- end
29
- end
30
- end
31
- end
@@ -1,139 +0,0 @@
1
- require 'pact/matchers'
2
- require 'pact/consumer/mock_service/rack_request_helper'
3
- require 'pact/consumer/mock_service/interaction_mismatch'
4
- require 'pact/consumer_contract'
5
- require 'pact/consumer/interactions_filter'
6
-
7
- module Pact
8
- module Consumer
9
-
10
- class InteractionReplay
11
- include Pact::Matchers
12
- include RackRequestHelper
13
-
14
- attr_accessor :name, :logger, :interaction_list, :interactions
15
-
16
- def initialize name, logger, interaction_list, interactions
17
- @name = name
18
- @logger = logger
19
- @interaction_list = interaction_list
20
- @interactions = DistinctInteractionsFilter.new(interactions)
21
- end
22
-
23
- def match? env
24
- true # default handler
25
- end
26
-
27
- def respond env
28
- find_response request_as_hash_from(env)
29
- end
30
-
31
- private
32
-
33
- def add_verified_interaction interaction
34
- interactions << interaction
35
- end
36
-
37
- def find_response request_hash
38
- actual_request = Request::Actual.from_hash(request_hash)
39
- logger.info "Received request #{actual_request.method_and_path}"
40
- logger.debug pretty_generate actual_request
41
- candidate_interactions = interaction_list.find_candidate_interactions actual_request
42
- matching_interactions = find_matching_interactions actual_request, from: candidate_interactions
43
-
44
- case matching_interactions.size
45
- when 0 then handle_unrecognised_request actual_request, candidate_interactions
46
- when 1 then handle_matched_interaction matching_interactions.first
47
- else
48
- handle_more_than_one_matching_interaction actual_request, matching_interactions
49
- end
50
- end
51
-
52
- def find_matching_interactions actual_request, opts
53
- candidate_interactions = opts.fetch(:from)
54
- candidate_interactions.select do | candidate_interaction |
55
- candidate_interaction.request.matches? actual_request
56
- end
57
- end
58
-
59
- def handle_matched_interaction interaction
60
- interaction_list.register_matched interaction
61
- add_verified_interaction interaction
62
- response = response_from(interaction.response)
63
- logger.info "Found matching response for #{interaction.request.method_and_path}"
64
- logger.debug pretty_generate(interaction.response)
65
- response
66
- end
67
-
68
- def multiple_interactions_found_response actual_request, matching_interactions
69
- response = {
70
- message: "Multiple interaction found for #{actual_request.method_and_path}",
71
- matching_interactions: matching_interactions.collect{ | interaction | request_summary_for(interaction) }
72
- }
73
- [500, {'Content-Type' => 'application/json'}, [response.to_json]]
74
- end
75
-
76
- def handle_more_than_one_matching_interaction actual_request, matching_interactions
77
- logger.error "Multiple interactions found for #{actual_request.method_and_path}:"
78
- matching_interactions.each do | interaction |
79
- logger.debug pretty_generate(interaction)
80
- end
81
- multiple_interactions_found_response actual_request, matching_interactions
82
- end
83
-
84
- def interaction_mismatch actual_request, candidate_interactions
85
- InteractionMismatch.new(candidate_interactions, actual_request)
86
- end
87
-
88
- def request_summary_for interaction
89
- summary = {:description => interaction.description}
90
- summary[:provider_state] if interaction.provider_state
91
- summary[:request] = interaction.request
92
- summary
93
- end
94
-
95
- def unrecognised_request_response interaction_mismatch
96
- response = {
97
- message: "No interaction found for #{interaction_mismatch.actual_request.method_and_path}",
98
- interaction_diffs: interaction_mismatch.to_hash
99
- }
100
- [500, {'Content-Type' => 'application/json'}, [response.to_json]]
101
- end
102
-
103
- def log_unrecognised_request_and_interaction_diff interaction_mismatch
104
- logger.error "No matching interaction found on #{name} for #{interaction_mismatch.actual_request.method_and_path}"
105
- logger.error 'Interaction diffs for that route:'
106
- logger.error(interaction_mismatch.to_s)
107
- end
108
-
109
- def handle_unrecognised_request actual_request, candidate_interactions
110
- interaction_mismatch = interaction_mismatch(actual_request, candidate_interactions)
111
- if candidate_interactions.any?
112
- interaction_list.register_interaction_mismatch interaction_mismatch
113
- else
114
- interaction_list.register_unexpected_request actual_request
115
- end
116
- log_unrecognised_request_and_interaction_diff interaction_mismatch
117
- unrecognised_request_response interaction_mismatch
118
- end
119
-
120
- def response_from response
121
- [response['status'], (response['headers'] || {}).to_hash, [render_body(Pact::Reification.from_term(response['body']))]]
122
- end
123
-
124
- def render_body body
125
- return '' unless body
126
- body.kind_of?(String) ? body.force_encoding('utf-8') : body.to_json
127
- end
128
-
129
- def logger_info_ap msg
130
- logger.info msg
131
- end
132
-
133
- #Doesn't seem to reliably pretty generate unless we go to JSON and back again :(
134
- def pretty_generate object
135
- JSON.pretty_generate(JSON.parse(object.to_json))
136
- end
137
- end
138
- end
139
- end
@@ -1,28 +0,0 @@
1
- require 'pact/consumer/mock_service/mock_service_administration_endpoint'
2
-
3
- module Pact
4
- module Consumer
5
- class LogGet < MockServiceAdministrationEndpoint
6
-
7
- include RackRequestHelper
8
-
9
- def request_path
10
- '/log'
11
- end
12
-
13
- def request_method
14
- 'GET'
15
- end
16
-
17
-
18
- def respond env
19
- logger.info "Debug message from client - #{message(env)}"
20
- [200, {}, []]
21
- end
22
-
23
- def message env
24
- params_hash(env)['msg']
25
- end
26
- end
27
- end
28
- end
@@ -1,30 +0,0 @@
1
- require 'pact/consumer/mock_service/mock_service_administration_endpoint'
2
-
3
- module Pact
4
- module Consumer
5
-
6
- class MissingInteractionsGet < MockServiceAdministrationEndpoint
7
- include RackRequestHelper
8
-
9
- def initialize name, logger, interaction_list
10
- super name, logger
11
- @interaction_list = interaction_list
12
- end
13
-
14
- def request_path
15
- '/interactions/missing'
16
- end
17
-
18
- def request_method
19
- 'GET'
20
- end
21
-
22
- def respond env
23
- number_of_missing_interactions = @interaction_list.missing_interactions.size
24
- logger.info "Number of missing interactions for mock \"#{name}\" = #{number_of_missing_interactions}"
25
- [200, {}, [{size: number_of_missing_interactions}.to_json]]
26
- end
27
-
28
- end
29
- end
30
- end