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
@@ -19,17 +19,279 @@ describe Pact do
19
19
  expect(Pact.configuration.send(key)).to eql(value)
20
20
  end
21
21
  end
22
+
22
23
  end
23
24
 
24
- describe "configuration" do
25
- it "should have a default pact_dir" do
26
- expect(Pact.configuration.pact_dir).to eql File.expand_path('./spec/pacts')
25
+ describe Pact::Configuration do
26
+ let(:configuration) { Pact::Configuration.new }
27
+
28
+ describe "log_dir" do
29
+ it "sets the location of the logs" do
30
+ expect(Logger).to receive(:new).with("./tmp/logs/pact.log").and_call_original
31
+ Pact.configure do | config |
32
+ config.log_dir = "./tmp/logs"
33
+ end
34
+ Pact.configuration.logger
35
+ end
27
36
  end
28
- it "should have a default log_dir" do
29
- expect(Pact.configuration.log_dir).to eql File.expand_path('./log')
37
+
38
+ describe "logger" do
39
+ it "sets the location of the logs to log_dir by default" do
40
+ expect(Logger).to receive(:new).with(File.expand_path("./log/pact.log")).and_call_original
41
+ Pact.configuration.logger
42
+ end
43
+ it "defaults to DEBUG" do
44
+ expect(Pact.configuration.logger.level).to eq Logger::DEBUG
45
+ end
30
46
  end
31
- it "should have a default logger configured" do
32
- expect(Pact.configuration.logger).to be_instance_of Logger
47
+
48
+ describe "doc_dir" do
49
+ it "defaults to ./doc/pacts" do
50
+ expect(Pact.configuration.doc_dir).to eq File.expand_path("./doc/pacts")
51
+ end
52
+
53
+ it "can be changed" do
54
+ Pact.configuration.doc_dir = "newdir"
55
+ expect(Pact.configuration.doc_dir).to eq "newdir"
56
+ end
57
+ end
58
+
59
+ describe "doc_generator" do
60
+
61
+ context "with a symbol" do
62
+ it "allows configuration of a doc_generator" do
63
+ Pact.configuration.doc_generator = :markdown
64
+ expect(Pact.configuration.doc_generators).to eq [Pact::Doc::Markdown::Generator]
65
+ end
66
+ end
67
+
68
+ context "with anything that responds to 'call'" do
69
+
70
+ it "allows configuration of a doc_generator" do
71
+ Pact.configuration.doc_generator = lambda { | pact_dir, doc_dir | "doc" }
72
+ expect(Pact.configuration.doc_generators.size).to be 1
73
+ expect(Pact.configuration.doc_generators.first.call('doc','pacts')).to eq ("doc")
74
+ end
75
+
76
+ end
77
+
78
+ context "with something that does not respond to call and doesn't have a matching doc_generator" do
79
+ it "raises an error" do
80
+ expect { Pact.configuration.doc_generator = Object.new }.to raise_error "Pact.configuration.doc_generator needs to respond to call, or be in the preconfigured list: [:markdown]"
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ describe "#diff_formatter_for_content_type" do
87
+
88
+ let(:subject) { Pact::Configuration.new }
89
+
90
+ it "returns the Pact::Matchers::UnixDiffFormatter by default" do
91
+ expect(subject.diff_formatter_for_content_type 'anything').to eq(Pact::Matchers::UnixDiffFormatter)
92
+ end
93
+
94
+ Pact::Configuration::DIFF_FORMATTERS.each_pair do | key, diff_formatter |
95
+
96
+ context "when set to :#{key}" do
97
+
98
+ before do
99
+ subject.diff_formatter = key
100
+ end
101
+
102
+ it "sets the diff_formatter to #{diff_formatter}" do
103
+ expect(subject.diff_formatter_for_content_type nil).to be diff_formatter
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ context "when set to an object that responds to call" do
110
+
111
+ let(:diff_formatter) { lambda{ | diff| } }
112
+
113
+ before do
114
+ subject.diff_formatter = diff_formatter
115
+ end
116
+
117
+ it "sets the diff_formatter to the object" do
118
+ expect(subject.diff_formatter_for_content_type nil).to be diff_formatter
119
+ end
120
+ end
121
+
122
+ context "when set to an object that does not respond to call and isn't a known default option" do
123
+ it "raises an error" do
124
+ expect { subject.diff_formatter = Object.new }.to raise_error "Pact diff_formatter needs to respond to call, or be in the preconfigured list: [:embedded, :unix, :list]"
125
+ expect { subject.diff_formatter = Object.new }.to raise_error "Pact diff_formatter needs to respond to call, or be in the preconfigured list: [:embedded, :unix, :list]"
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ describe "diff_formatter_for_content_type" do
132
+ let(:diff_formatter) { lambda { |expected, actual| }}
133
+ context "with the default configuration" do
134
+ context "when the content type is nil" do
135
+ it "returns the UnixDiffFormatter" do
136
+ expect(Pact.configuration.diff_formatter_for_content_type nil).to eq Pact::Matchers::UnixDiffFormatter
137
+ end
138
+ end
139
+ context "when the content type is application/json" do
140
+ it "returns the UnixDiffFormatter" do
141
+ expect(Pact.configuration.diff_formatter_for_content_type nil).to eq Pact::Matchers::UnixDiffFormatter
142
+ end
143
+ end
144
+ context "when the content type is text/plain" do
145
+ it "returns the UnixDiffFormatter" do
146
+ expect(Pact.configuration.diff_formatter_for_content_type nil).to eq Pact::Matchers::UnixDiffFormatter
147
+ end
148
+ end
149
+ end
150
+ context "with a custom diff_formatter registered for nil content type" do
151
+ context "when the content_type is nil" do
152
+ it "returns the custom diff_formatter" do
153
+ Pact.configuration.register_diff_formatter nil, diff_formatter
154
+ expect(Pact.configuration.diff_formatter_for_content_type nil).to eq diff_formatter
155
+ end
156
+ end
157
+ end
158
+ context "with a custom diff_formatter registered for json content type" do
159
+ context "when the content_type is application/json" do
160
+ it "returns the custom diff_formatter" do
161
+ Pact.configuration.register_diff_formatter /json/, diff_formatter
162
+ expect(Pact.configuration.diff_formatter_for_content_type 'application/json').to eq diff_formatter
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ describe "register_body_differ" do
169
+
170
+ let(:differ) { lambda{ |expected, actual| } }
171
+
172
+ context "with a string for a content type" do
173
+ it "configures the differ for the given content type" do
174
+ Pact.configure do | config |
175
+ config.register_body_differ 'application/xml', differ
176
+ end
177
+
178
+ expect(Pact.configuration.body_differ_for_content_type 'application/xml').to be differ
179
+ end
180
+ end
181
+
182
+ context "with a regexp for a content type" do
183
+ it "returns a matching differ" do
184
+ Pact.configuration.register_body_differ /application\/.*xml/, differ
185
+ expect(Pact.configuration.body_differ_for_content_type 'application/hal+xml').to be differ
186
+ end
187
+ end
188
+
189
+ context "when a non string or regexp is used to register a differ" do
190
+ it "raises an error" do
191
+ expect { Pact.configuration.register_body_differ 1, differ }.to raise_error /Invalid/
192
+ end
193
+ end
194
+
195
+ context "when something that does not respond to call is sumbitted as a differ" do
196
+ it "raises an error" do
197
+ expect { Pact.configuration.register_body_differ 'thing', Object.new }.to raise_error /responds to call/
198
+ end
199
+ end
200
+
201
+ context "when a nil content type is registered for responses without a content type header" do
202
+ it "returns that differ if the differ for a nil content type is requested" do
203
+ Pact.configuration.register_body_differ nil, differ
204
+ expect(Pact.configuration.body_differ_for_content_type(nil)).to be differ
205
+ end
206
+ end
207
+
208
+ end
209
+
210
+ describe "body_differ_for_content_type" do
211
+
212
+ let(:differ) { lambda { |expected, actual| }}
213
+
214
+ context "when 2 potentially matching content types have a differ registered" do
215
+ let(:differ_1) { lambda{ |expected, actual| } }
216
+ let(:differ_2) { lambda{ |expected, actual| } }
217
+
218
+ it "returns the differ that was configured first" do
219
+ Pact.configuration.register_body_differ /application\/.*xml/, differ_2
220
+ Pact.configuration.register_body_differ /application\/hal\+xml/, differ_1
221
+ expect(Pact.configuration.body_differ_for_content_type 'application/hal+xml').to be differ_2
222
+ end
223
+ end
224
+
225
+ context "when a nil content type is given" do
226
+ it "returns the text differ" do
227
+ expect(Pact.configuration.body_differ_for_content_type nil).to be Pact::TextDiffer
228
+ end
229
+ end
230
+
231
+ context "when no matching content type is found" do
232
+ it "returns the text differ" do
233
+ expect(Pact.configuration.body_differ_for_content_type 'blah').to be Pact::TextDiffer
234
+ end
235
+ end
236
+
237
+ context "when the nil content type has a custom differ configured" do
238
+ it "returns the custom differ" do
239
+ Pact.configuration.register_body_differ nil, differ
240
+ expect(Pact.configuration.body_differ_for_content_type(nil)).to be differ
241
+ end
242
+ end
243
+
244
+ context "when a custom differ is registered for a content type that has a default differ" do
245
+ it "returns the custom differ" do
246
+ Pact.configuration.register_body_differ /application\/json/, differ
247
+ expect(Pact.configuration.body_differ_for_content_type 'application/json').to be differ
248
+ end
249
+ end
250
+ end
251
+
252
+ describe "pactfile_write_mode" do
253
+ context "when @pactfile_write_mode is :overwrite" do
254
+ it 'returns :overwrite' do
255
+ configuration.pactfile_write_mode = :overwrite
256
+ expect(configuration.pactfile_write_mode).to eq :overwrite
257
+ end
258
+ end
259
+ context "when @pactfile_write_mode is :update" do
260
+ it 'returns :overwrite' do
261
+ configuration.pactfile_write_mode = :update
262
+ expect(configuration.pactfile_write_mode).to eq :update
263
+ end
264
+ end
265
+ context "when @pactfile_write_mode is :smart" do
266
+ before do
267
+ configuration.pactfile_write_mode = :smart
268
+ expect(configuration).to receive(:is_rake_running?).and_return(is_rake_running)
269
+ end
270
+ context "when rake is running" do
271
+ let(:is_rake_running) { true }
272
+ it "returns :overwrite" do
273
+ expect(configuration.pactfile_write_mode).to eq :overwrite
274
+ end
275
+ end
276
+ context "when rake is not running" do
277
+ let(:is_rake_running) { false }
278
+ it "returns :update" do
279
+ expect(configuration.pactfile_write_mode).to eq :update
280
+ end
281
+ end
282
+ end
33
283
  end
34
284
  end
285
+ describe "default_configuration" do
286
+ it "should have a default pact_dir" do
287
+ expect(Pact.configuration.pact_dir).to eql File.expand_path('./spec/pacts')
288
+ end
289
+ it "should have a default log_dir" do
290
+ expect(Pact.configuration.log_dir).to eql File.expand_path('./log')
291
+ end
292
+ it "should have a default logger configured" do
293
+ expect(Pact.configuration.logger).to be_instance_of Logger
294
+ end
295
+ end
296
+
35
297
  end
@@ -8,20 +8,20 @@ module Pact::Consumer
8
8
 
9
9
  describe "start_service_for" do
10
10
  before do
11
- AppRegistration.any_instance.stub(:spawn) # Don't want process actually spawning during the tests
11
+ allow_any_instance_of(AppRegistration).to receive(:spawn) # Don't want process actually spawning during the tests
12
12
  end
13
13
  let(:name) { 'some_service'}
14
14
  context "for http://localhost" do
15
15
  let(:url) { 'http://localhost:1234'}
16
16
  it "starts a mock service at the given port on localhost" do
17
- AppRegistration.any_instance.should_receive(:spawn)
17
+ expect_any_instance_of(AppRegistration).to receive(:spawn)
18
18
  AppManager.instance.register_mock_service_for name, url
19
19
  AppManager.instance.spawn_all
20
20
  end
21
21
 
22
22
  it "registers the mock service as running on the given port" do
23
23
  AppManager.instance.register_mock_service_for name, url
24
- AppManager.instance.app_registered_on?(1234).should be_true
24
+ expect(AppManager.instance.app_registered_on?(1234)).to eq true
25
25
  end
26
26
  end
27
27
  context "for https://" do
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/configuration'
3
+
4
+ module Pact::Consumer::Configuration
5
+
6
+ describe MockService do
7
+
8
+ let(:world) { Pact::Consumer::World.new }
9
+ before do
10
+ Pact.clear_configuration
11
+ allow(Pact::Consumer::AppManager.instance).to receive(:register_mock_service_for)
12
+ allow(Pact).to receive(:consumer_world).and_return(world)
13
+ end
14
+
15
+ describe "configure_consumer_contract_builder" do
16
+ let(:consumer_name) {'consumer'}
17
+ subject {
18
+ MockService.build :mock_service, consumer_name, provider_name do
19
+ port 1234
20
+ standalone true
21
+ verify true
22
+ end
23
+ }
24
+
25
+ let(:provider_name) { 'Mock Provider' }
26
+ let(:consumer_contract_builder) { instance_double('Pact::Consumer::ConsumerContractBuilder') }
27
+ let(:url) { "http://localhost:1234" }
28
+
29
+ it "adds a verification to the Pact configuration" do
30
+ allow(Pact::Consumer::ConsumerContractBuilder).to receive(:new).and_return(consumer_contract_builder)
31
+ subject.finalize
32
+ expect(consumer_contract_builder).to receive(:verify)
33
+ Pact.configuration.provider_verifications.first.call
34
+ end
35
+
36
+ context "when standalone" do
37
+ it "does not register the app with the AppManager" do
38
+ expect(Pact::Consumer::AppManager.instance).to_not receive(:register_mock_service_for)
39
+ subject.finalize
40
+ end
41
+ end
42
+ context "when not standalone" do
43
+ subject {
44
+ MockService.build :mock_service, consumer_name, provider_name do
45
+ port 1234
46
+ standalone false
47
+ verify true
48
+ end
49
+ }
50
+ it "registers the app with the AppManager" do
51
+ expect(Pact::Consumer::AppManager.instance).to receive(:register_mock_service_for).with(provider_name, url)
52
+ subject.finalize
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -3,85 +3,67 @@ require 'fileutils'
3
3
  require 'pathname'
4
4
 
5
5
  module Pact
6
- module Consumer
7
- describe ConsumerContractBuilder do
6
+ module Consumer
7
+ describe ConsumerContractBuilder do
8
8
 
9
- describe "initialize" do
10
- before do
11
- Pact.clear_configuration
12
- Pact.configuration.stub(:pact_dir).and_return(File.expand_path(tmp_pact_dir))
13
- FileUtils.rm_rf tmp_pact_dir
14
- FileUtils.mkdir_p tmp_pact_dir
15
- FileUtils.cp './spec/support/a_consumer-a_producer.json', "#{tmp_pact_dir}/a_consumer-a_producer.json"
16
- end
9
+ let(:consumer_name) { 'a consumer' }
10
+ let(:provider_name) { 'a provider' }
17
11
 
18
- let(:tmp_pact_dir) {"./tmp/pacts"}
12
+ describe "handle_interaction_fully_defined" do
19
13
 
20
- let(:consumer_name) { 'a consumer' }
21
- let(:producer_name) { 'a producer' }
22
- let(:consumer_contract_builder) {
23
- Pact::Consumer::ConsumerContractBuilder.new(
24
- :pactfile_write_mode => pactfile_write_mode,
25
- :consumer_name => consumer_name,
26
- :producer_name => producer_name,
27
- :port => 1234)}
14
+ subject {
15
+ Pact::Consumer::ConsumerContractBuilder.new(:consumer_name => 'blah', :provider_name => 'blah', :port => 2222)
16
+ }
28
17
 
29
- context "when overwriting pact" do
30
- let(:pactfile_write_mode) {:overwrite}
31
- it "it overwrites the existing pact file" do
32
- expect(consumer_contract_builder.consumer_contract.interactions).to eq []
33
- end
34
- end
18
+ let(:interaction_hash) {
19
+ {
20
+ description: 'Test request',
21
+ request: {
22
+ method: 'post',
23
+ path: '/foo',
24
+ body: Term.new(generate: 'waffle', matcher: /ffl/),
25
+ headers: { 'Content-Type' => 'application/json' },
26
+ query: "",
27
+ },
28
+ response: {
29
+ baz: 'qux',
30
+ wiffle: 'wiffle'
31
+ }
32
+ }
33
+ }
35
34
 
36
- context "when updating pact" do
37
- let(:pactfile_write_mode) {:update}
38
- it "updates the existing pact file" do
39
- expect(consumer_contract_builder.consumer_contract.interactions.size).to eq 2
40
- end
41
- end
42
- end
35
+ let(:interaction_json) { {} }
43
36
 
44
- describe "handle_interaction_fully_defined" do
37
+ let(:interaction) { Pact::Interaction.from_hash(JSON.load(interaction_hash.to_json)) }
45
38
 
46
- subject {
47
- Pact::Consumer::ConsumerContractBuilder.new({:consumer_name => 'blah', :producer_name => 'blah', :port => 2222})
48
- }
39
+ before do
40
+ stub_request(:post, 'localhost:2222/interactions')
41
+ end
49
42
 
50
- let(:interaction_hash) {
51
- {
52
- description: 'Test request',
53
- request: {
54
- method: 'post',
55
- path: '/foo',
56
- body: Term.new(generate: 'waffle', matcher: /ffl/),
57
- headers: { 'Content-Type' => 'application/json' },
58
- query: "",
59
- },
60
- response: {
61
- baz: 'qux',
62
- wiffle: 'wiffle'
63
- }
64
- }
65
- }
43
+ it "posts the interaction with generated response to the mock service" do
44
+ subject.handle_interaction_fully_defined interaction
45
+ expect(WebMock).to have_requested(:post, 'localhost:2222/interactions').with(body: interaction_json)
46
+ end
66
47
 
67
- let(:interaction_json) { JSON.dump(interaction_hash) }
48
+ it "resets the interaction_builder to nil" do
49
+ expect(subject).to receive(:interaction_builder=).with(nil)
50
+ subject.handle_interaction_fully_defined interaction
51
+ end
52
+ end
68
53
 
69
- let(:interaction) { Pact::Consumer::Interaction.from_hash(JSON.parse(interaction_json)) }
54
+ describe "#mock_service_base_url" do
70
55
 
71
- before do
72
- stub_request(:post, 'localhost:2222/interactions')
73
- end
56
+ subject {
57
+ ConsumerContractBuilder.new(
58
+ :pactfile_write_mode => :overwrite,
59
+ :consumer_name => consumer_name,
60
+ :provider_name => provider_name,
61
+ :port => 1234) }
74
62
 
75
- it "posts the interaction with generated response to the mock service" do
76
- subject.handle_interaction_fully_defined interaction
77
- WebMock.should have_requested(:post, 'localhost:2222/interactions').with(body: interaction_json)
78
- end
79
-
80
- it "updates the Producer's Pactfile" do
81
- subject.consumer_contract.should_receive(:update_pactfile)
82
- subject.handle_interaction_fully_defined interaction
83
- end
84
- end
85
- end
86
- end
87
- end
63
+ it "returns the mock service base URL" do
64
+ expect(subject.mock_service_base_url).to eq("http://localhost:1234")
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/interaction_builder'
3
+
4
+ module Pact
5
+ module Consumer
6
+ describe InteractionBuilder do
7
+
8
+ subject { InteractionBuilder.new }
9
+ let(:interaction) { double('Interaction').as_null_object}
10
+
11
+ before do
12
+ expect(Interaction).to receive(:new).and_return(interaction)
13
+ end
14
+
15
+ describe "given" do
16
+ context "with a string provider state" do
17
+ it "sets the provider_state on the interaction" do
18
+ expect(interaction).to receive(:provider_state=).with('blah')
19
+ subject.given('blah')
20
+ end
21
+ end
22
+
23
+ context "with a symbol provider state" do
24
+ it "sets the provider_state on the interaction as a string" do
25
+ expect(interaction).to receive(:provider_state=).with('some_symbol')
26
+ subject.given(:some_symbol)
27
+ end
28
+ end
29
+
30
+ it "returns itself" do
31
+ expect(subject.given(nil)).to be(subject)
32
+ end
33
+ end
34
+
35
+ describe "upon_receiving" do
36
+ it "sets the description on the interaction" do
37
+ expect(interaction).to receive(:description=).with('blah')
38
+ subject.upon_receiving('blah')
39
+ end
40
+
41
+ it "returns itself" do
42
+ expect(subject.given(nil)).to be(subject)
43
+ end
44
+ end
45
+
46
+ describe "with" do
47
+
48
+ let(:request) { {a: 'request'} }
49
+ let(:expected_request) { {an: 'expected_request'} }
50
+
51
+ it "sets the request on the interaction as a instance of Request::Expected" do
52
+ expect(Pact::Request::Expected).to receive(:from_hash).with(request).and_return(expected_request)
53
+ expect(interaction).to receive(:request=).with(expected_request)
54
+ subject.with(request)
55
+ end
56
+
57
+ it "returns itself" do
58
+ expect(subject.given(nil)).to be(subject)
59
+ end
60
+ end
61
+
62
+ describe "will_respond_with" do
63
+ let(:response) { {a: 'response'} }
64
+
65
+ let(:provider) do
66
+ double(callback: nil)
67
+ end
68
+
69
+ before do
70
+ subject.on_interaction_fully_defined do | interaction |
71
+ provider.callback interaction
72
+ end
73
+ end
74
+
75
+ it "sets the response on the interaction" do
76
+ expect(interaction).to receive(:response=).with(response)
77
+ subject.will_respond_with(response)
78
+ end
79
+
80
+ it "returns itself" do
81
+ expect(subject.given(nil)).to be(subject)
82
+ end
83
+
84
+ it "invokes the 'on_interaction_fully_defined' callback" do
85
+ expect(provider).to receive(:callback).with(interaction)
86
+ subject.will_respond_with response
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'pact/consumer/interactions_filter'
3
+
4
+ module Pact::Consumer
5
+
6
+ describe 'Interactions' do
7
+ let(:interaction) { InteractionFactory.create }
8
+ let(:indentical_interaction) { InteractionFactory.create }
9
+ let(:interaction_with_diff_request) { InteractionFactory.create :request => {:path => '/different'} }
10
+ let(:interaction_with_diff_description) { InteractionFactory.create :description => 'blah' }
11
+ let(:interaction_with_diff_provider_state) { InteractionFactory.create :provider_state => 'blah' }
12
+ let(:interactions) { [interaction] }
13
+
14
+ shared_examples_for 'interactions' do
15
+
16
+ subject { described_class.new(interactions) }
17
+
18
+ describe "<<" do
19
+ context "when an interaction with the same provider state and description is not already included" do
20
+ it "adds the interaction" do
21
+ subject << interaction_with_diff_description
22
+ expect(interactions).to eq [interaction, interaction_with_diff_description]
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ describe UpdatableInteractionsFilter do
29
+ context "which, by default, is used when running rspec" do
30
+ include_examples 'interactions'
31
+ describe "<<" do
32
+ context "when an interaction with the same provider state and description is already included" do
33
+ it "overwrites the existing interaction, as the user has most likely just updated a test, and is rerunning the one spec" do
34
+ subject << interaction_with_diff_request
35
+ expect(interactions).to eq [interaction_with_diff_request]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ describe DistinctInteractionsFilter do
43
+ context "which, by default, this is used when running rake" do
44
+ include_examples 'interactions'
45
+ describe "<<" do
46
+ context "when an interaction with the same provider state and description is already included" do
47
+ context "when the interactions are not equal" do
48
+ it "raises an error as the user has most likely copy/pasted an existing interaction and forgotten to update the description or provider state" do
49
+ expect{ subject << interaction_with_diff_request }.to raise_error 'Interaction with same description (a description) and provider state (a thing exists) already exists'
50
+ end
51
+ end
52
+ context "when the interactions are equal" do
53
+ it "does not add the interaction as it already exists" do
54
+ subject << indentical_interaction
55
+ expect(interactions).to eq [interaction]
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ end