pact 0.1.28 → 1.3.3

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 (285) hide show
  1. data/.gitignore +2 -1
  2. data/.ruby-version +1 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +374 -0
  5. data/Gemfile +0 -1
  6. data/Gemfile.lock +58 -55
  7. data/README.md +214 -139
  8. data/Rakefile +4 -28
  9. data/bin/pact +2 -2
  10. data/config.ru +3 -0
  11. data/documentation/README.md +13 -0
  12. data/documentation/configuration.md +166 -0
  13. data/documentation/diff_formatter_embedded.png +0 -0
  14. data/documentation/diff_formatter_list.png +0 -0
  15. data/documentation/diff_formatter_unix.png +0 -0
  16. data/example/animal-service/Gemfile +14 -0
  17. data/example/animal-service/Gemfile.lock +69 -0
  18. data/example/animal-service/Rakefile +5 -0
  19. data/example/animal-service/config.ru +3 -0
  20. data/example/animal-service/db/animal_db.sqlite3 +0 -0
  21. data/example/animal-service/lib/animal_service/animal_repository.rb +12 -0
  22. data/example/animal-service/lib/animal_service/api.rb +28 -0
  23. data/example/animal-service/lib/animal_service/db.rb +5 -0
  24. data/example/animal-service/spec/service_consumers/pact_helper.rb +11 -0
  25. data/example/animal-service/spec/service_consumers/provider_states_for_zoo_app.rb +26 -0
  26. data/example/zoo-app/Gemfile +12 -0
  27. data/example/zoo-app/Gemfile.lock +63 -0
  28. data/example/zoo-app/Rakefile +5 -0
  29. data/example/zoo-app/doc/pacts/markdown/README.md +3 -0
  30. data/example/zoo-app/doc/pacts/markdown/Zoo App - Animal Service.md +75 -0
  31. data/example/zoo-app/lib/zoo_app/animal_service_client.rb +40 -0
  32. data/example/zoo-app/lib/zoo_app/models/alligator.rb +15 -0
  33. data/example/zoo-app/spec/pacts/zoo_app-animal_service.json +67 -0
  34. data/example/zoo-app/spec/service_providers/animal_service_client_spec.rb +71 -0
  35. data/example/zoo-app/spec/service_providers/pact_helper.rb +15 -0
  36. data/example/zoo-app/spec/spec_helper.rb +6 -0
  37. data/lib/pact/cli.rb +138 -0
  38. data/lib/pact/configuration.rb +169 -28
  39. data/lib/pact/consumer/app_manager.rb +10 -29
  40. data/lib/pact/consumer/configuration/configuration_extensions.rb +15 -0
  41. data/lib/pact/consumer/configuration/dsl.rb +12 -0
  42. data/lib/pact/consumer/configuration/mock_service.rb +91 -0
  43. data/lib/pact/consumer/configuration/service_consumer.rb +51 -0
  44. data/lib/pact/consumer/configuration/service_provider.rb +40 -0
  45. data/lib/pact/consumer/configuration.rb +11 -0
  46. data/lib/pact/consumer/consumer_contract_builder.rb +44 -47
  47. data/lib/pact/consumer/interaction_builder.rb +41 -0
  48. data/lib/pact/consumer/interactions_filter.rb +48 -0
  49. data/lib/pact/consumer/mock_service/app.rb +82 -0
  50. data/lib/pact/consumer/mock_service/interaction_delete.rb +33 -0
  51. data/lib/pact/consumer/mock_service/interaction_list.rb +76 -0
  52. data/lib/pact/consumer/mock_service/interaction_mismatch.rb +73 -0
  53. data/lib/pact/consumer/mock_service/interaction_post.rb +31 -0
  54. data/lib/pact/consumer/mock_service/interaction_replay.rb +139 -0
  55. data/lib/pact/consumer/mock_service/log_get.rb +28 -0
  56. data/lib/pact/consumer/mock_service/missing_interactions_get.rb +30 -0
  57. data/lib/pact/consumer/mock_service/mock_service_administration_endpoint.rb +31 -0
  58. data/lib/pact/consumer/mock_service/pact_post.rb +33 -0
  59. data/lib/pact/consumer/mock_service/rack_request_helper.rb +51 -0
  60. data/lib/pact/consumer/mock_service/verification_get.rb +68 -0
  61. data/lib/pact/consumer/mock_service.rb +1 -339
  62. data/lib/pact/consumer/mock_service_client.rb +65 -0
  63. data/lib/pact/consumer/mock_service_interaction_expectation.rb +37 -0
  64. data/lib/pact/consumer/request.rb +27 -0
  65. data/lib/pact/consumer/rspec.rb +9 -19
  66. data/lib/pact/consumer/server.rb +90 -0
  67. data/lib/pact/consumer/spec_hooks.rb +38 -0
  68. data/lib/pact/consumer/world.rb +37 -0
  69. data/lib/pact/consumer.rb +10 -7
  70. data/lib/pact/consumer_contract/consumer_contract.rb +115 -0
  71. data/lib/pact/consumer_contract/consumer_contract_writer.rb +84 -0
  72. data/lib/pact/consumer_contract/file_name.rb +19 -0
  73. data/lib/pact/consumer_contract/headers.rb +51 -0
  74. data/lib/pact/consumer_contract/interaction.rb +67 -0
  75. data/lib/pact/consumer_contract/pact_file.rb +24 -0
  76. data/lib/pact/consumer_contract/request.rb +73 -0
  77. data/lib/pact/consumer_contract/service_consumer.rb +28 -0
  78. data/lib/pact/consumer_contract/service_provider.rb +28 -0
  79. data/lib/pact/consumer_contract.rb +1 -110
  80. data/lib/pact/doc/doc_file.rb +40 -0
  81. data/lib/pact/doc/generate.rb +11 -0
  82. data/lib/pact/doc/generator.rb +82 -0
  83. data/lib/pact/doc/interaction_view_model.rb +114 -0
  84. data/lib/pact/doc/markdown/consumer_contract_renderer.rb +56 -0
  85. data/lib/pact/doc/markdown/generator.rb +26 -0
  86. data/lib/pact/doc/markdown/index_renderer.rb +41 -0
  87. data/lib/pact/doc/markdown/interaction.erb +14 -0
  88. data/lib/pact/doc/markdown/interaction_renderer.rb +38 -0
  89. data/lib/pact/doc/sort_interactions.rb +17 -0
  90. data/lib/pact/matchers/actual_type.rb +16 -0
  91. data/lib/pact/matchers/base_difference.rb +37 -0
  92. data/lib/pact/matchers/differ.rb +153 -0
  93. data/lib/pact/matchers/difference.rb +13 -0
  94. data/lib/pact/matchers/difference_indicator.rb +26 -0
  95. data/lib/pact/matchers/embedded_diff_formatter.rb +62 -0
  96. data/lib/pact/matchers/expected_type.rb +35 -0
  97. data/lib/pact/matchers/index_not_found.rb +15 -0
  98. data/lib/pact/matchers/list_diff_formatter.rb +101 -0
  99. data/lib/pact/matchers/matchers.rb +91 -37
  100. data/lib/pact/matchers/no_diff_indicator.rb +18 -0
  101. data/lib/pact/matchers/regexp_difference.rb +13 -0
  102. data/lib/pact/matchers/type_difference.rb +16 -0
  103. data/lib/pact/matchers/unexpected_index.rb +11 -0
  104. data/lib/pact/matchers/unexpected_key.rb +11 -0
  105. data/lib/pact/matchers/unix_diff_formatter.rb +114 -0
  106. data/lib/pact/project_root.rb +7 -0
  107. data/lib/pact/provider/configuration/configuration_extension.rb +58 -0
  108. data/lib/pact/provider/configuration/dsl.rb +13 -0
  109. data/lib/pact/provider/configuration/pact_verification.rb +46 -0
  110. data/lib/pact/provider/configuration/service_provider_config.rb +16 -0
  111. data/lib/pact/provider/configuration/service_provider_dsl.rb +59 -0
  112. data/lib/pact/provider/configuration.rb +7 -0
  113. data/lib/pact/provider/context.rb +0 -0
  114. data/lib/pact/provider/matchers/messages.rb +45 -0
  115. data/lib/pact/provider/pact_helper_locator.rb +22 -0
  116. data/lib/pact/provider/pact_spec_runner.rb +123 -0
  117. data/lib/pact/provider/pact_verification.rb +17 -0
  118. data/lib/pact/provider/print_missing_provider_states.rb +30 -0
  119. data/lib/pact/provider/request.rb +70 -0
  120. data/lib/pact/provider/rspec/backtrace_formatter.rb +43 -0
  121. data/lib/pact/provider/rspec/custom_options_file +0 -0
  122. data/lib/pact/provider/rspec/formatter_rspec_2.rb +65 -0
  123. data/lib/pact/provider/rspec/formatter_rspec_3.rb +96 -0
  124. data/lib/pact/provider/rspec/matchers.rb +97 -0
  125. data/lib/pact/provider/rspec.rb +181 -0
  126. data/lib/pact/provider/state/provider_state.rb +181 -0
  127. data/lib/pact/provider/state/provider_state_configured_modules.rb +13 -0
  128. data/lib/pact/provider/state/provider_state_manager.rb +42 -0
  129. data/lib/pact/provider/state/provider_state_proxy.rb +39 -0
  130. data/lib/pact/provider/test_methods.rb +47 -0
  131. data/lib/pact/provider/verification_report.rb +36 -0
  132. data/lib/pact/provider/world.rb +23 -0
  133. data/lib/pact/provider.rb +3 -0
  134. data/lib/pact/reification.rb +6 -4
  135. data/lib/pact/rspec.rb +53 -0
  136. data/lib/pact/shared/active_support_support.rb +51 -0
  137. data/lib/pact/shared/dsl.rb +76 -0
  138. data/lib/pact/shared/jruby_support.rb +18 -0
  139. data/lib/pact/shared/json_differ.rb +15 -0
  140. data/lib/pact/shared/key_not_found.rb +15 -0
  141. data/lib/pact/shared/null_expectation.rb +31 -0
  142. data/lib/pact/shared/request.rb +80 -0
  143. data/lib/pact/shared/text_differ.rb +14 -0
  144. data/lib/pact/something_like.rb +49 -0
  145. data/lib/pact/symbolize_keys.rb +12 -0
  146. data/lib/pact/tasks/task_helper.rb +36 -0
  147. data/lib/pact/tasks/verification_task.rb +87 -0
  148. data/lib/pact/tasks.rb +2 -0
  149. data/lib/pact/templates/provider_state.erb +14 -0
  150. data/lib/pact/term.rb +47 -2
  151. data/lib/pact/version.rb +1 -1
  152. data/lib/pact.rb +1 -1
  153. data/lib/tasks/pact.rake +25 -2
  154. data/pact.gemspec +13 -11
  155. data/{scratchpad.txt → scratchpad.rb} +18 -2
  156. data/spec/features/consumption_spec.rb +24 -56
  157. data/spec/features/production_spec.rb +19 -24
  158. data/spec/features/{producer_states → provider_states}/zebras.rb +3 -3
  159. data/spec/integration/consumer_spec.rb +212 -0
  160. data/spec/integration/pact/consumer_configuration_spec.rb +66 -0
  161. data/spec/integration/pact/provider_configuration_spec.rb +25 -0
  162. data/spec/lib/pact/cli_spec.rb +47 -0
  163. data/spec/lib/pact/configuration_spec.rb +269 -7
  164. data/spec/lib/pact/consumer/app_manager_spec.rb +3 -3
  165. data/spec/lib/pact/consumer/configuration_spec.rb +57 -0
  166. data/spec/lib/pact/consumer/consumer_contract_builder_spec.rb +52 -70
  167. data/spec/lib/pact/consumer/interaction_builder_spec.rb +91 -0
  168. data/spec/lib/pact/consumer/interactions_spec.rb +64 -0
  169. data/spec/lib/pact/consumer/mock_service/app_spec.rb +52 -0
  170. data/spec/lib/pact/consumer/mock_service/interaction_list_spec.rb +78 -0
  171. data/spec/lib/pact/consumer/mock_service/interaction_mismatch_spec.rb +70 -0
  172. data/spec/lib/pact/consumer/mock_service/interaction_replay_spec.rb +12 -0
  173. data/spec/lib/pact/consumer/mock_service/rack_request_helper_spec.rb +88 -0
  174. data/spec/lib/pact/consumer/mock_service/verification_get_spec.rb +142 -0
  175. data/spec/lib/pact/consumer/mock_service_client_spec.rb +88 -0
  176. data/spec/lib/pact/consumer/mock_service_interaction_expectation_spec.rb +54 -0
  177. data/spec/lib/pact/consumer/request_spec.rb +24 -0
  178. data/spec/lib/pact/consumer/service_consumer_spec.rb +1 -1
  179. data/spec/lib/pact/consumer_contract/active_support_support_spec.rb +58 -0
  180. data/spec/lib/pact/consumer_contract/consumer_contract_spec.rb +180 -0
  181. data/spec/lib/pact/consumer_contract/consumer_contract_writer_spec.rb +111 -0
  182. data/spec/lib/pact/consumer_contract/headers_spec.rb +107 -0
  183. data/spec/lib/pact/consumer_contract/interaction_spec.rb +107 -0
  184. data/spec/lib/pact/{request_spec.rb → consumer_contract/request_spec.rb} +80 -67
  185. data/spec/lib/pact/doc/generator_spec.rb +84 -0
  186. data/spec/lib/pact/doc/interaction_view_model_spec.rb +132 -0
  187. data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +29 -0
  188. data/spec/lib/pact/doc/markdown/index_renderer_spec.rb +29 -0
  189. data/spec/lib/pact/matchers/differ_spec.rb +214 -0
  190. data/spec/lib/pact/matchers/difference_spec.rb +22 -0
  191. data/spec/lib/pact/matchers/embedded_diff_formatter_spec.rb +90 -0
  192. data/spec/lib/pact/matchers/index_not_found_spec.rb +21 -0
  193. data/spec/lib/pact/matchers/list_diff_formatter_spec.rb +114 -0
  194. data/spec/lib/pact/matchers/matchers_spec.rb +400 -254
  195. data/spec/lib/pact/matchers/regexp_difference_spec.rb +20 -0
  196. data/spec/lib/pact/matchers/type_difference_spec.rb +34 -0
  197. data/spec/lib/pact/matchers/unexpected_index_spec.rb +20 -0
  198. data/spec/lib/pact/matchers/unexpected_key_spec.rb +20 -0
  199. data/spec/lib/pact/matchers/unix_diff_formatter_spec.rb +216 -0
  200. data/spec/lib/pact/provider/configuration/configuration_extension_spec.rb +30 -0
  201. data/spec/lib/pact/provider/configuration/pact_verification_spec.rb +43 -0
  202. data/spec/lib/pact/provider/configuration/service_provider_config_spec.rb +21 -0
  203. data/spec/lib/pact/provider/configuration/service_provider_dsl_spec.rb +108 -0
  204. data/spec/lib/pact/provider/configuration_spec.rb +50 -0
  205. data/spec/lib/pact/provider/matchers/messages_spec.rb +116 -0
  206. data/spec/lib/pact/provider/pact_helper_locator_spec.rb +54 -0
  207. data/spec/lib/pact/provider/print_missing_provider_states_spec.rb +19 -0
  208. data/spec/lib/pact/provider/request_spec.rb +78 -0
  209. data/spec/lib/pact/provider/rspec/formatter_rspec_2_spec.rb +68 -0
  210. data/spec/lib/pact/provider/rspec/formatter_rspec_3_spec.rb +72 -0
  211. data/spec/lib/pact/provider/rspec_spec.rb +55 -0
  212. data/spec/lib/pact/provider/state/provider_state_manager_spec.rb +89 -0
  213. data/spec/lib/pact/provider/state/provider_state_proxy_spec.rb +80 -0
  214. data/spec/lib/pact/provider/state/provider_state_spec.rb +213 -0
  215. data/spec/lib/pact/provider/world_spec.rb +41 -0
  216. data/spec/lib/pact/reification_spec.rb +24 -0
  217. data/spec/lib/pact/shared/dsl_spec.rb +86 -0
  218. data/spec/lib/pact/shared/json_differ_spec.rb +36 -0
  219. data/spec/lib/pact/shared/key_not_found_spec.rb +20 -0
  220. data/spec/lib/pact/shared/request_spec.rb +111 -0
  221. data/spec/lib/pact/shared/text_differ_spec.rb +54 -0
  222. data/spec/lib/pact/something_like_spec.rb +21 -0
  223. data/spec/lib/pact/tasks/task_helper_spec.rb +74 -0
  224. data/spec/lib/pact/tasks/verification_task_spec.rb +75 -0
  225. data/spec/lib/pact/term_spec.rb +57 -4
  226. data/spec/pact_specification/compliance-1.0.0.rb +47 -0
  227. data/spec/spec_helper.rb +17 -0
  228. data/spec/standalone/consumer_fail_test.rb +55 -0
  229. data/spec/standalone/consumer_pass_test.rb +51 -0
  230. data/spec/support/a_consumer-a_producer.json +2 -4
  231. data/spec/support/a_consumer-a_provider.json +32 -0
  232. data/spec/support/active_support_if_configured.rb +6 -0
  233. data/spec/support/app_for_config_ru.rb +4 -0
  234. data/spec/support/consumer_contract_template.json +24 -0
  235. data/spec/support/dsl_spec_support.rb +7 -0
  236. data/spec/support/factories.rb +82 -0
  237. data/spec/support/generated_index.md +4 -0
  238. data/spec/support/generated_markdown.md +55 -0
  239. data/spec/support/interaction_view_model.json +63 -0
  240. data/spec/support/interaction_view_model_with_terms.json +50 -0
  241. data/spec/support/markdown_pact.json +48 -0
  242. data/spec/support/missing_provider_states_output.txt +25 -0
  243. data/spec/support/options.json +21 -0
  244. data/spec/support/options_app.rb +15 -0
  245. data/spec/support/pact_helper.rb +57 -0
  246. data/spec/support/shared_examples_for_request.rb +94 -0
  247. data/spec/support/spec_support.rb +20 -0
  248. data/spec/support/stubbing.json +22 -0
  249. data/spec/support/stubbing_using_allow.rb +29 -0
  250. data/spec/support/term.json +48 -0
  251. data/spec/support/test_app_fail.json +41 -2
  252. data/spec/support/test_app_pass.json +19 -2
  253. data/spec/support/test_app_with_right_content_type_differ.json +23 -0
  254. data/tasks/pact-test.rake +98 -8
  255. data/tasks/spec.rake +8 -0
  256. metadata +393 -95
  257. data/lib/pact/app.rb +0 -32
  258. data/lib/pact/consumer/configuration_dsl.rb +0 -71
  259. data/lib/pact/consumer/dsl.rb +0 -98
  260. data/lib/pact/consumer/interaction.rb +0 -70
  261. data/lib/pact/consumer/run_condor.rb +0 -4
  262. data/lib/pact/consumer/run_mock_contract_service.rb +0 -13
  263. data/lib/pact/consumer/service_consumer.rb +0 -22
  264. data/lib/pact/consumer/service_producer.rb +0 -23
  265. data/lib/pact/json_warning.rb +0 -23
  266. data/lib/pact/producer/configuration_dsl.rb +0 -62
  267. data/lib/pact/producer/matchers.rb +0 -22
  268. data/lib/pact/producer/pact_spec_runner.rb +0 -57
  269. data/lib/pact/producer/producer_state.rb +0 -81
  270. data/lib/pact/producer/rspec.rb +0 -127
  271. data/lib/pact/producer/test_methods.rb +0 -89
  272. data/lib/pact/producer.rb +0 -1
  273. data/lib/pact/rake_task.rb +0 -64
  274. data/lib/pact/request.rb +0 -109
  275. data/lib/pact/verification_task.rb +0 -57
  276. data/spec/integration/pact/configuration_spec.rb +0 -65
  277. data/spec/lib/pact/consumer/dsl_spec.rb +0 -52
  278. data/spec/lib/pact/consumer/interaction_spec.rb +0 -108
  279. data/spec/lib/pact/consumer/mock_service_spec.rb +0 -147
  280. data/spec/lib/pact/consumer_contract_spec.rb +0 -125
  281. data/spec/lib/pact/producer/configuration_dsl_spec.rb +0 -101
  282. data/spec/lib/pact/producer/producer_state_spec.rb +0 -103
  283. data/spec/lib/pact/producer/rspec_spec.rb +0 -48
  284. data/spec/lib/pact/verification_task_spec.rb +0 -64
  285. data/spec/support/pact_rake_support.rb +0 -41
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'pact/tasks/verification_task'
3
+
4
+ module Pact
5
+ describe VerificationTask do
6
+ before :all do
7
+ @pact_helper = '/custom/path/pact_helper .rb'
8
+ @pact_uri = 'http://example.org/pact.json'
9
+ @task_name = 'pact:verify:pact_rake_spec'
10
+ @task_name_with_explict_pact_helper = 'pact:verify:pact_rake_spec_with_explict_pact_helper'
11
+ @consumer = 'some-consumer'
12
+ @criteria = {:description => /wiffle/}
13
+
14
+ VerificationTask.new(:pact_rake_spec_with_explict_pact_helper) do | pact |
15
+ pact.uri @pact_uri, pact_helper: @pact_helper
16
+ end
17
+
18
+ VerificationTask.new(:pact_rake_spec) do | pact |
19
+ pact.uri @pact_uri
20
+ end
21
+ end
22
+
23
+ before do
24
+ allow(Pact::TaskHelper).to receive(:execute_pact_verify).and_return(0)
25
+ end
26
+
27
+ let(:exit_code) {0}
28
+
29
+
30
+ describe '.initialize' do
31
+ context 'with an explict pact_helper' do
32
+ it 'creates the tasks' do
33
+ expect(Rake::Task.tasks).to include_task @task_name
34
+ end
35
+ end
36
+ context 'with no explict pact_helper' do
37
+ it 'creates the tasks' do
38
+ expect(Rake::Task.tasks).to include_task @task_name_with_explict_pact_helper
39
+ end
40
+ end
41
+ end
42
+
43
+ describe 'execute' do
44
+
45
+ context "with no explicit pact_helper" do
46
+ it 'verifies the pacts using the TaskHelper' do
47
+ expect(Pact::TaskHelper).to receive(:execute_pact_verify).with(@pact_uri, nil, nil)
48
+ Rake::Task[@task_name].execute
49
+ end
50
+ end
51
+
52
+ context "with an explict pact_helper" do
53
+ let(:verification_config) { [ uri: @pact_uri, pact_helper: @pact_helper] }
54
+ it 'verifies the pacts using the TaskHelper' do
55
+ expect(Pact::TaskHelper).to receive(:execute_pact_verify).with(@pact_uri, @pact_helper, nil)
56
+ Rake::Task[@task_name_with_explict_pact_helper].execute
57
+ end
58
+ end
59
+
60
+ context 'when all specs pass' do
61
+
62
+ it 'does not raise an exception' do
63
+ Rake::Task[@task_name].execute
64
+ end
65
+ end
66
+
67
+ end
68
+ end
69
+ end
70
+
71
+ RSpec::Matchers.define :include_task do |expected|
72
+ match do |actual|
73
+ actual.any? { |task| task.name == expected }
74
+ end
75
+ end
@@ -3,6 +3,38 @@ require 'spec_helper'
3
3
  module Pact
4
4
  describe Term do
5
5
 
6
+ describe 'initialize' do
7
+ let(:matcher) { /e/ }
8
+ let(:generate) { 'apple'}
9
+ subject { Term.new(generate: generate, matcher: matcher) }
10
+ context "when a matcher and generate are specified" do
11
+ context "when the matcher matches the generated value" do
12
+ it 'does not raise an exception' do
13
+ subject
14
+ end
15
+ end
16
+
17
+ context "when the matcher does not match the generated value" do
18
+ let(:generate) { 'banana' }
19
+ it 'raises an exception' do
20
+ expect { subject }.to raise_error /does not match/
21
+ end
22
+ end
23
+ end
24
+ context 'when a matcher is not specified' do
25
+ let(:matcher) { nil }
26
+ it 'raises an exception' do
27
+ expect { subject }.to raise_error /Please specify a matcher/
28
+ end
29
+ end
30
+ context 'when a generate is not specified' do
31
+ let(:generate) { nil }
32
+ it 'raises an exception' do
33
+ expect { subject }.to raise_error /Please specify a value/
34
+ end
35
+ end
36
+ end
37
+
6
38
  describe "equality" do
7
39
  context "when the matcher and generate attrs are the same" do
8
40
  let(:this) { Term.new(generate: 'A', matcher: /A/) }
@@ -14,8 +46,8 @@ module Pact
14
46
  end
15
47
 
16
48
  context "when the generate attrs are different" do
17
- let(:this) { Term.new(generate: /A/) }
18
- let(:that) { Term.new(generate: /B/) }
49
+ let(:this) { Term.new(generate: 'A', matcher: /.*/) }
50
+ let(:that) { Term.new(generate: 'B', matcher: /.*/) }
19
51
 
20
52
  it "is not equal" do
21
53
  expect(this).to_not eq that
@@ -23,8 +55,8 @@ module Pact
23
55
  end
24
56
 
25
57
  context "when the matcher attrs are different" do
26
- let(:this) { Term.new(matcher: 'A') }
27
- let(:that) { Term.new(matcher: 'B') }
58
+ let(:this) { Term.new(matcher: /A/, generate: 'AB') }
59
+ let(:that) { Term.new(matcher: /B/, generate: 'AB') }
28
60
 
29
61
  it "is not equal" do
30
62
  expect(this).to_not eq that
@@ -32,5 +64,26 @@ module Pact
32
64
  end
33
65
  end
34
66
 
67
+ describe 'empty?' do
68
+
69
+ subject { Term.new(generate: 'some', matcher: /some/) }
70
+
71
+ it 'should return false' do
72
+ expect(subject).to_not be_empty
73
+ end
74
+
75
+ end
76
+
77
+ describe 'unpack_regexps' do
78
+ let(:term) { Term.new(generate: 'some', matcher: /s/) }
79
+ let(:body) { [{a: [{b: term}], c:term, d: 1, e: 'blah'}] }
80
+ let(:expected) { [{:a=>[{:b=>/s/}], :c=>/s/, :d=>1, :e=>"blah"}] }
81
+
82
+ it "returns a structure with the Pact::Terms replaced by their regexps" do
83
+ expect(Term.unpack_regexps(body)).to eq expected
84
+ end
85
+
86
+ end
87
+
35
88
  end
36
89
  end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/request'
3
+ require 'pact/consumer_contract/request'
4
+
5
+ PACT_SPEC_DIR = "../pact-specification/testcases"
6
+ REQUEST_TEST_CASE_FOLDERS = Dir.glob("#{PACT_SPEC_DIR}/request/**")
7
+ REQUEST_TEST_CASE_FILES = Dir.glob("#{PACT_SPEC_DIR}/request/**/*.json")
8
+
9
+ TEST_DESCRIPTIONS = {true => "matches", false => "does not match"}
10
+
11
+ describe "Pact gem complicance with Pact Specification 1.0.0" do
12
+
13
+ directories = Dir.glob("#{PACT_SPEC_DIR}/*")
14
+
15
+ directories.each do | dir_name |
16
+
17
+ describe File.basename(dir_name) do
18
+
19
+ sub_directories = Dir.glob("#{dir_name}/*")
20
+
21
+ sub_directories.each do | sub_dir_name |
22
+
23
+ context File.basename(sub_dir_name) do
24
+ testcases = Dir.glob("#{sub_dir_name}/**/*.json")
25
+
26
+ testcases.each do | file_name |
27
+
28
+ context File.basename(file_name).chomp(".json") do
29
+
30
+ file_content = JSON.parse(File.read(file_name))
31
+ expected = Pact::Request::Expected.from_hash(file_content["expected"])
32
+ actual = Pact::Consumer::Request::Actual.from_hash(file_content["actual"])
33
+ expected_result = file_content.fetch("match")
34
+ comment = file_content["comment"]
35
+
36
+ it "#{TEST_DESCRIPTIONS[expected_result]} - #{comment}" do
37
+ expect(expected.matches?(actual)).to eq expected_result
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,22 @@
1
1
  require 'rspec'
2
+ require 'fakefs/spec_helpers'
3
+ require 'rspec'
2
4
  require 'pact'
3
5
  require 'webmock/rspec'
6
+ require 'support/factories'
7
+ require 'support/spec_support'
8
+ require 'pact/provider/rspec'
4
9
 
5
10
  WebMock.disable_net_connect!(allow_localhost: true)
11
+
12
+ require './spec/support/active_support_if_configured'
13
+
14
+ RSpec.configure do | config |
15
+ config.include(FakeFS::SpecHelpers, :fakefs => true)
16
+
17
+ config.extend Pact::Provider::RSpec::ClassMethods
18
+ config.include Pact::Provider::RSpec::InstanceMethods
19
+ config.include Pact::Provider::TestMethods
20
+ config.include Pact::SpecSupport
21
+ end
22
+
@@ -0,0 +1,55 @@
1
+ require 'pact/consumer/rspec'
2
+ require './spec/support/active_support_if_configured'
3
+
4
+ Pact.service_consumer "Standalone Consumer" do
5
+ has_pact_with "Standalone Provider" do
6
+ mock_service :standalone_service do
7
+ port 1238
8
+ end
9
+ end
10
+ end
11
+
12
+ class StandaloneClient
13
+
14
+ def initialize base_url
15
+ @base_url = base_url
16
+ end
17
+
18
+ def call
19
+ uri = URI("#{@base_url}/something")
20
+ post_req = Net::HTTP::Post.new(uri.path)
21
+ post_req['Content-Type'] = "application/json"
22
+ post_req.body = {a: "not matching body"}.to_json
23
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
24
+ http.request post_req
25
+ end
26
+ JSON.parse(response.body)
27
+ end
28
+
29
+ end
30
+
31
+ describe StandaloneClient, pact: true do
32
+
33
+ subject { StandaloneClient.new("http://localhost:1238") }
34
+
35
+ describe "call" do
36
+
37
+ let(:expected_body) { {a: "body"} }
38
+ let(:expected_headers) { {'Content-Type' => "application/hal+json"} }
39
+
40
+ before do
41
+ standalone_service.
42
+ upon_receiving("a request to create something").with(method: 'post', path: '/something', headers: expected_headers, body: expected_body).
43
+ will_respond_with(status: 200, headers: {}, body: {a: 'response body'})
44
+
45
+ standalone_service.
46
+ upon_receiving("a request to create something else").with(method: 'post', path: '/something-else', headers: expected_headers, body: expected_body).
47
+ will_respond_with(status: 200, headers: {}, body: {a: 'response body'})
48
+ end
49
+
50
+ it "will fail and display a helpful message" do
51
+ subject.call
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,51 @@
1
+ require 'pact/consumer/rspec'
2
+ require './spec/support/active_support_if_configured'
3
+
4
+ Pact.service_consumer "Standalone Consumer" do
5
+ has_pact_with "Standalone Provider" do
6
+ mock_service :standalone_service do
7
+ port 1237
8
+ end
9
+ end
10
+ end
11
+
12
+ class StandaloneClient
13
+
14
+ def initialize base_url
15
+ @base_url = base_url
16
+ end
17
+
18
+ def call
19
+ uri = URI("#{@base_url}/something")
20
+ post_req = Net::HTTP::Post.new(uri.path)
21
+ post_req['Content-Type'] = "application/json"
22
+ post_req.body = {a: "body"}.to_json
23
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
24
+ http.request post_req
25
+ end
26
+ response.body
27
+ end
28
+
29
+ end
30
+
31
+ describe StandaloneClient, pact: true do
32
+
33
+ subject { StandaloneClient.new("http://localhost:1237") }
34
+
35
+ describe "call" do
36
+
37
+ let(:expected_body) { {a: "body"} }
38
+ let(:response_body) { {a: 'response body'} }
39
+
40
+ before do
41
+ standalone_service.
42
+ upon_receiving("a request to create something").with(method: 'post', path: '/something', body: expected_body).
43
+ will_respond_with(status: 200, headers: {}, body: response_body)
44
+ end
45
+
46
+ it "will pass" do
47
+ expect(subject.call).to eq response_body.to_json
48
+ end
49
+ end
50
+
51
+ end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "producer": {
3
- "name": "a producer"
3
+ "name": "an old producer"
4
4
  },
5
5
  "consumer": {
6
6
  "name": "a consumer"
@@ -27,8 +27,6 @@
27
27
  }
28
28
  ],
29
29
  "metadata": {
30
- "pact_gem": {
31
- "version": "0.1.24"
32
- }
30
+ "pactSpecificationVersion": "1.0"
33
31
  }
34
32
  }
@@ -0,0 +1,32 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ },
17
+ "provider_state": "state one"
18
+ },
19
+ {
20
+ "description": "request two",
21
+ "request": {
22
+ "method": "get",
23
+ "path": "/path_two"
24
+ },
25
+ "response": {
26
+ }
27
+ }
28
+ ],
29
+ "metadata": {
30
+ "pactSpecificationVersion": "1.0"
31
+ }
32
+ }
@@ -0,0 +1,6 @@
1
+ if ENV['LOAD_ACTIVE_SUPPORT']
2
+ puts 'LOADING ACTIVE SUPPORT!!!! Hopefully it all still works'
3
+ require 'active_support/all'
4
+ require 'active_support'
5
+ require 'active_support/json'
6
+ end
@@ -0,0 +1,4 @@
1
+ class AppForConfigRu
2
+ def call env
3
+ end
4
+ end
@@ -0,0 +1,24 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "request one",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path_one"
14
+ },
15
+ "response": {
16
+ "status" : 200
17
+ },
18
+ "provider_state": "state one"
19
+ }
20
+ ],
21
+ "metadata": {
22
+ "pactSpecificationVersion": "1.0"
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ def global_method
2
+ "I'm global"
3
+ end
4
+
5
+ def global_app
6
+ "I'm a global app"
7
+ end
@@ -0,0 +1,82 @@
1
+ require 'hashie'
2
+ require 'hashie/extensions/key_conversion'
3
+
4
+ module Pact
5
+ module HashUtils
6
+
7
+ class Converter < Hash
8
+ include Hashie::Extensions::KeyConversion
9
+ include Hashie::Extensions::DeepMerge
10
+ end
11
+
12
+ def symbolize_keys hash
13
+ Hash[Converter[hash].symbolize_keys]
14
+ end
15
+
16
+ def stringify_keys hash
17
+ Hash[Converter[hash].stringify_keys]
18
+ end
19
+
20
+ def deep_merge hash1, hash2
21
+ Converter[hash1].deep_merge(Converter[hash2])
22
+ end
23
+ end
24
+ end
25
+
26
+ class InteractionFactory
27
+
28
+ extend Pact::HashUtils
29
+
30
+ def self.create hash = {}
31
+ defaults = {
32
+ 'description' => 'a description',
33
+ 'provider_state' => 'a thing exists',
34
+ 'request' => {
35
+ 'path' => '/path',
36
+ 'method' => 'get',
37
+ },
38
+ 'response' => {
39
+ 'status' => 200,
40
+ 'body' => {a: 'response body'}
41
+ }
42
+ }
43
+ Pact::Interaction.from_hash(stringify_keys(deep_merge(defaults, stringify_keys(hash))))
44
+ end
45
+ end
46
+
47
+
48
+ class ConsumerContractFactory
49
+ extend Pact::HashUtils
50
+ DEFAULTS = {:consumer_name => 'consumer',
51
+ :provider_name => 'provider',
52
+ :interactions => [InteractionFactory.create]}
53
+
54
+ def self.create overrides = {}
55
+ options = deep_merge(symbolize_keys(DEFAULTS), symbolize_keys(overrides))
56
+ Pact::ConsumerContract.new({:consumer => Pact::ServiceConsumer.new(name: options[:consumer_name]),
57
+ :provider => Pact::ServiceProvider.new(name: options[:provider_name]),
58
+ :interactions => options[:interactions]})
59
+ end
60
+ end
61
+
62
+
63
+
64
+ class ResponseFactory
65
+ extend Pact::HashUtils
66
+ DEFAULTS = {:status => 200, :body => {a: 'body'}}.freeze
67
+ def self.create_hash overrides = {}
68
+ deep_merge(DEFAULTS, overrides)
69
+ end
70
+ end
71
+
72
+ class RequestFactory
73
+ extend Pact::HashUtils
74
+ DEFAULTS = {:path => '/path', :method => 'get', :query => 'query', :headers => {}}.freeze
75
+ def self.create_hash overrides = {}
76
+ deep_merge(DEFAULTS, overrides)
77
+ end
78
+
79
+ def self.create_actual overrides = {}
80
+ Pact::Consumer::Request::Actual.from_hash(create_hash(overrides))
81
+ end
82
+ end
@@ -0,0 +1,4 @@
1
+ ### Pacts for Some Consumer
2
+
3
+ * [Some Provider](Some Provider.md)
4
+ * [Some other provider](Some other provider.md)
@@ -0,0 +1,55 @@
1
+ ### A pact between Some Consumer and Some Provider
2
+
3
+ #### Requests from Some Consumer to Some Provider
4
+
5
+ * [A request for alligators](#a_request_for_alligators_given_alligators_exist) given alligators exist
6
+
7
+ * [A request for polar bears](#a_request_for_polar_bears)
8
+
9
+ #### Interactions
10
+
11
+ <a name="a_request_for_alligators_given_alligators_exist"></a>
12
+ Given **alligators exist**, upon receiving **a request for alligators** from Some Consumer, with
13
+ ```json
14
+ {
15
+ "method": "get",
16
+ "path": "/alligators"
17
+ }
18
+ ```
19
+ Some Provider will respond with:
20
+ ```json
21
+ {
22
+ "status": 200,
23
+ "headers": {
24
+ "Content-Type": "application/json"
25
+ },
26
+ "body": {
27
+ "alligators": [
28
+ {
29
+ "name": "Bob",
30
+ "phoneNumber": "12345678"
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+ <a name="a_request_for_polar_bears"></a>
37
+ Upon receiving **a request for polar bears** from Some Consumer, with
38
+ ```json
39
+ {
40
+ "method": "get",
41
+ "path": "/polar-bears"
42
+ }
43
+ ```
44
+ Some Provider will respond with:
45
+ ```json
46
+ {
47
+ "status": 404,
48
+ "headers": {
49
+ "Content-Type": "application/json"
50
+ },
51
+ "body": {
52
+ "message": "Sorry, due to climate change, the polar bears are currently unavailable."
53
+ }
54
+ }
55
+ ```
@@ -0,0 +1,63 @@
1
+ {
2
+ "provider": {
3
+ "name": "a provider"
4
+ },
5
+ "consumer": {
6
+ "name": "a consumer"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "a request with a body and headers",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/path",
14
+ "query": "some=thing",
15
+ "headers": {
16
+ "key": "a header"
17
+ },
18
+ "body": {
19
+ "key": "a body"
20
+ }
21
+ },
22
+ "response": {}
23
+ },
24
+ {
25
+ "description": "a request with an empty body and empty headers",
26
+ "request": {
27
+ "method": "get",
28
+ "path": "/",
29
+ "headers": {},
30
+ "body": {}
31
+ },
32
+ "response": {}
33
+ },
34
+ {
35
+ "description": "a response with a body and headers",
36
+ "request": {
37
+ "method": "get",
38
+ "path": "/"
39
+ },
40
+ "response": {
41
+ "headers": {
42
+ "key": "a header"
43
+ },
44
+ "body": {
45
+ "key": "a body"
46
+ },
47
+ "status": 200
48
+ }
49
+ },
50
+ {
51
+ "description": "a response with an empty body and empty headers",
52
+ "request": {
53
+ "method": "get",
54
+ "path": "/"
55
+ },
56
+ "response": {
57
+ "status": 200,
58
+ "headers": {},
59
+ "body": {}
60
+ }
61
+ }
62
+ ]
63
+ }