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,166 @@
1
+ # Configuration
2
+
3
+ ## Menu
4
+
5
+ #### Consumer and Provider configuration options
6
+ * [diff_formatter](#diff_formatter)
7
+ * [log_dir](#log_dir)
8
+ * [logger](#logger)
9
+ * [logger.level](#loggerlevel)
10
+
11
+ #### Consumer only configuration options
12
+ * [pact_dir](#pact_dir)
13
+ * [doc_dir](#doc_dir)
14
+ * [doc_generator](#doc_generator)
15
+ * [pactfile_write_mode](#pactfile_write_mode)
16
+
17
+ #### Provider only configuration options
18
+ * [include](#include)
19
+
20
+ ## Consumer and Provider
21
+
22
+ ### log_dir
23
+
24
+ ```ruby
25
+ Pact.configure do | config |
26
+ config.log_dir = './log'
27
+ end
28
+ ```
29
+
30
+ Default value: `./log`
31
+
32
+ ### logger
33
+
34
+ ```ruby
35
+ Pact.configure do | config |
36
+ config.logger = Logger.new
37
+ end
38
+ ```
39
+
40
+ Default value: file logger to the configured log_dir.
41
+
42
+ ### logger.level
43
+
44
+ ```ruby
45
+ Pact.configure do | config |
46
+ config.logger.level = Logger::INFO
47
+ end
48
+ ```
49
+
50
+ Default value: `Logger::DEBUG`
51
+
52
+ ### diff_formatter
53
+
54
+ ```ruby
55
+ Pact.configure do | config |
56
+ config.diff_formatter = :list
57
+ end
58
+ ```
59
+
60
+ Default value: [:list](#list)
61
+
62
+ Options: [:unix](#unix), [:list](#list), [:embedded](#embedded), [Custom Diff Formatter](#custom-diff-formatter)
63
+
64
+
65
+ #### :unix
66
+ <img src="diff_formatter_unix.png" width="700">
67
+
68
+ #### :list
69
+
70
+ <img src="diff_formatter_list.png" width="700">
71
+
72
+ #### :embedded
73
+
74
+ <img src="diff_formatter_embedded.png" width="700">
75
+
76
+
77
+ #### Custom Diff Formatter
78
+
79
+ Any object can be used that responds to `call`, accepting the argument `diff`.
80
+
81
+ ```ruby
82
+ class MyCustomDiffFormatter
83
+
84
+ def self.call diff
85
+ ### Do stuff here
86
+ end
87
+
88
+ end
89
+
90
+ Pact.configure do | config |
91
+ config.diff_formatter = MyCustomDiffFormatter
92
+ end
93
+ ```
94
+
95
+
96
+ ## Consumer
97
+
98
+ ### pact_dir
99
+
100
+ ```ruby
101
+ Pact.configure do | config |
102
+ config.pact_dir = `./spec/pacts`
103
+ end
104
+ ```
105
+
106
+ Default value: `./spec/pacts`
107
+
108
+ ### doc_generator
109
+
110
+ ```ruby
111
+ Pact.configure do | config |
112
+ config.doc_generator = :markdown
113
+ end
114
+ ```
115
+
116
+ Default value: none
117
+
118
+ Options: [:markdown](#markdown), [Custom Doc Generator](#custom-doc-generator)
119
+
120
+ #### :markdown
121
+
122
+ Generates Markdown documentation based on the contents of the pact files created in this consumer. Files are created in `${Pact.configuration.doc_dir}/markdown`.
123
+
124
+ #### Custom Doc Generator
125
+
126
+ Any object can be used that responds to `call`, accepting the arguments `pact_dir` and `doc_dir`.
127
+
128
+ ```ruby
129
+ Pact.configure do | config |
130
+ config.doc_generator = lambda{ | pact_dir, doc_dir | generate_some_docs(pact_dir, doc_dir) }
131
+ end
132
+
133
+ ```
134
+
135
+ #### doc_dir
136
+
137
+ ```ruby
138
+ Pact.configure do | config |
139
+ config.doc_dir = './doc'
140
+ end
141
+ ```
142
+
143
+ Default value: `./doc`
144
+
145
+
146
+ ### pactfile_write_mode
147
+
148
+ Default value: `:overwrite`
149
+ Options: `:overwrite`, `:update`, `:smart`
150
+
151
+ By default, the pact file will be overwritten (started from scratch) every time any rspec runs any spec using pacts. This means that if there are interactions that haven't been executed in the most recent rspec run, they are effectively removed from the pact file. If you have long running pact specs (e.g. they are generated using the browser with Capybara) and you are developing both consumer and provider in parallel, or trying to fix a broken interaction, it can be tedious to run all the specs at once. In this scenario, you can set the pactfile_write_mode to :update. This will keep all existing interactions, and update only the changed ones, identified by description and provider state. The down side of this is that if either of those fields change, the old interactions will not be removed from the pact file. As a middle path, you can set pactfile_write_mode to :smart. This will use :overwrite mode when running rake (as determined by a call to system using 'ps') and :update when running an individual spec.
152
+
153
+ ## Provider
154
+
155
+ Pact uses RSpec and Rack::Test to create dynamic specs based on the pact files. RSpec configuration can be used to modify test behaviour if there is not an appropriate Pact feature. If you wish to use the same spec_helper.rb file as your unit tests, require it in the pact_helper.rb, but remember that the RSpec configurations for your unit tests may or may not be what you want for your pact verification tests.
156
+
157
+ ### include
158
+
159
+ ```ruby
160
+ Pact.configure do | config |
161
+ config.include MyTestHelperMethods
162
+ end
163
+ ```
164
+
165
+ To make modules available in the provider state set_up and tear_down blocks, include them in the configuration as shown below. One common use of this to include factory methods for setting up data so that the provider states file doesn't get too bloated.
166
+
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'rspec'
5
+ gem 'pact', path: '../../'
6
+ gem 'pry'
7
+ end
8
+
9
+ gem 'rake'
10
+ gem 'rack', '~>1.5.2'
11
+ gem 'json', '~>1.6'
12
+ gem 'sqlite3'
13
+ gem 'sequel'
14
+ gem 'sinatra'
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: ../../
3
+ specs:
4
+ pact (1.1.0.rc2)
5
+ awesome_print (~> 1.1)
6
+ find_a_port (~> 1.0.1)
7
+ json
8
+ rack-test (~> 0.6.2)
9
+ randexp (~> 0.1.7)
10
+ rspec (~> 2.12)
11
+ term-ansicolor (~> 1.0)
12
+ thor
13
+ webrick
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ awesome_print (1.2.0)
19
+ coderay (1.0.9)
20
+ diff-lcs (1.2.4)
21
+ find_a_port (1.0.1)
22
+ json (1.6.8)
23
+ method_source (0.8.2)
24
+ pry (0.9.12.2)
25
+ coderay (~> 1.0.5)
26
+ method_source (~> 0.8)
27
+ slop (~> 3.4)
28
+ rack (1.5.2)
29
+ rack-protection (1.5.1)
30
+ rack
31
+ rack-test (0.6.2)
32
+ rack (>= 1.0)
33
+ rake (10.1.0)
34
+ randexp (0.1.7)
35
+ rspec (2.14.1)
36
+ rspec-core (~> 2.14.0)
37
+ rspec-expectations (~> 2.14.0)
38
+ rspec-mocks (~> 2.14.0)
39
+ rspec-core (2.14.5)
40
+ rspec-expectations (2.14.2)
41
+ diff-lcs (>= 1.1.3, < 2.0)
42
+ rspec-mocks (2.14.3)
43
+ sequel (4.5.0)
44
+ sinatra (1.4.4)
45
+ rack (~> 1.4)
46
+ rack-protection (~> 1.4)
47
+ tilt (~> 1.3, >= 1.3.4)
48
+ slop (3.4.6)
49
+ sqlite3 (1.3.8)
50
+ term-ansicolor (1.3.0)
51
+ tins (~> 1.0)
52
+ thor (0.19.1)
53
+ tilt (1.4.1)
54
+ tins (1.1.0)
55
+ webrick (1.3.1)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ json (~> 1.6)
62
+ pact!
63
+ pry
64
+ rack (~> 1.5.2)
65
+ rake
66
+ rspec
67
+ sequel
68
+ sinatra
69
+ sqlite3
@@ -0,0 +1,5 @@
1
+ $: << File.join(File.dirname(__FILE__), "lib")
2
+
3
+ require 'pact/tasks'
4
+
5
+ task :default => 'pact:verify'
@@ -0,0 +1,3 @@
1
+ require File.dirname(__FILE__) + '/lib/animal_service/api'
2
+
3
+ run AnimalService::Api
@@ -0,0 +1,12 @@
1
+ require 'sequel'
2
+ require_relative 'db'
3
+
4
+ module AnimalService
5
+ class AnimalRepository
6
+
7
+ def self.find_alligator_by_name name
8
+ DATABASE[:animals].where(name: name).single_record
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ require 'sinatra/base'
2
+ require_relative 'animal_repository'
3
+
4
+ module AnimalService
5
+
6
+ class Api < Sinatra::Base
7
+
8
+ set :raise_errors, false
9
+ set :show_exceptions, false
10
+
11
+ error do
12
+ e = env['sinatra.error']
13
+ content_type :json
14
+ status 500
15
+ {error: e.message, backtrace: e.backtrace}.to_json
16
+ end
17
+
18
+ get '/alligators/:name' do
19
+ if (alligator = AnimalRepository.find_alligator_by_name(params[:name]))
20
+ content_type :json
21
+ alligator.to_json
22
+ else
23
+ status 404
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ require 'sequel'
2
+
3
+ module AnimalService
4
+ DATABASE ||= Sequel.connect(adapter: 'sqlite', database: './db/animal_db.sqlite3')
5
+ end
@@ -0,0 +1,11 @@
1
+ require 'pact/provider/rspec'
2
+
3
+ require "./spec/service_consumers/provider_states_for_zoo_app"
4
+
5
+ Pact.service_provider 'Animal Service' do
6
+
7
+ honours_pact_with "Zoo App" do
8
+ pact_uri '../zoo-app/spec/pacts/zoo_app-animal_service.json'
9
+ end
10
+
11
+ end
@@ -0,0 +1,26 @@
1
+ require 'sequel'
2
+ require 'animal_service/db'
3
+ require 'animal_service/animal_repository'
4
+
5
+ Pact.provider_states_for "Zoo App" do
6
+
7
+ set_up do
8
+ AnimalService::DATABASE[:animals].truncate
9
+ end
10
+
11
+ provider_state "there is an alligator named Mary" do
12
+ set_up do
13
+ AnimalService::DATABASE[:animals].insert(name: 'Mary')
14
+ end
15
+ end
16
+
17
+ provider_state "there is not an alligator named Mary" do
18
+ no_op
19
+ end
20
+
21
+ provider_state "an error occurs retrieving an alligator" do
22
+ set_up do
23
+ allow(AnimalService::AnimalRepository).to receive(:find_alligator_by_name).and_raise("Argh!!!")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ gem 'rspec'
5
+ gem 'pact', path: '../../'
6
+ gem 'pry'
7
+ end
8
+
9
+ gem 'rake'
10
+ gem 'rack', '~>1.5.2'
11
+ gem 'json', '~>1.6.8'
12
+ gem 'httparty'
@@ -0,0 +1,63 @@
1
+ PATH
2
+ remote: ../../
3
+ specs:
4
+ pact (1.1.0.rc3)
5
+ awesome_print (~> 1.1)
6
+ find_a_port (~> 1.0.1)
7
+ json
8
+ rack-test (~> 0.6.2)
9
+ randexp (~> 0.1.7)
10
+ rspec (~> 2.12)
11
+ term-ansicolor (~> 1.0)
12
+ thor
13
+ webrick
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ awesome_print (1.2.0)
19
+ coderay (1.0.9)
20
+ diff-lcs (1.2.4)
21
+ find_a_port (1.0.1)
22
+ httparty (0.11.0)
23
+ multi_json (~> 1.0)
24
+ multi_xml (>= 0.5.2)
25
+ json (1.6.8)
26
+ method_source (0.8.2)
27
+ multi_json (1.7.9)
28
+ multi_xml (0.5.5)
29
+ pry (0.9.12.2)
30
+ coderay (~> 1.0.5)
31
+ method_source (~> 0.8)
32
+ slop (~> 3.4)
33
+ rack (1.5.2)
34
+ rack-test (0.6.2)
35
+ rack (>= 1.0)
36
+ rake (10.1.0)
37
+ randexp (0.1.7)
38
+ rspec (2.14.1)
39
+ rspec-core (~> 2.14.0)
40
+ rspec-expectations (~> 2.14.0)
41
+ rspec-mocks (~> 2.14.0)
42
+ rspec-core (2.14.5)
43
+ rspec-expectations (2.14.2)
44
+ diff-lcs (>= 1.1.3, < 2.0)
45
+ rspec-mocks (2.14.3)
46
+ slop (3.4.6)
47
+ term-ansicolor (1.3.0)
48
+ tins (~> 1.0)
49
+ thor (0.19.1)
50
+ tins (1.1.0)
51
+ webrick (1.3.1)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ httparty
58
+ json (~> 1.6.8)
59
+ pact!
60
+ pry
61
+ rack (~> 1.5.2)
62
+ rake
63
+ rspec
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ ### Pacts for Zoo App
2
+
3
+ * [Animal Service](Zoo App - Animal Service.md)
@@ -0,0 +1,75 @@
1
+ ### A pact between Zoo App and Animal Service
2
+
3
+ #### Requests from Zoo App to Animal Service
4
+
5
+ * [A request for an alligator](#a_request_for_an_alligator_given_there_is_an_alligator_named_Mary) given there is an alligator named Mary
6
+
7
+ * [A request for an alligator](#a_request_for_an_alligator_given_there_is_not_an_alligator_named_Mary) given there is not an alligator named Mary
8
+
9
+ * [A request for an alligator](#a_request_for_an_alligator_given_an_error_occurs_retrieving_an_alligator) given an error occurs retrieving an alligator
10
+
11
+ #### Interactions
12
+
13
+ <a name="a_request_for_an_alligator_given_there_is_an_alligator_named_Mary"></a>
14
+ Given **there is an alligator named Mary**, upon receiving **a request for an alligator** from Zoo App, with
15
+ ```json
16
+ {
17
+ "method": "get",
18
+ "path": "/alligators/Mary",
19
+ "headers": {
20
+ "Accept": "application/json"
21
+ }
22
+ }
23
+ ```
24
+ Animal Service will respond with:
25
+ ```json
26
+ {
27
+ "status": 200,
28
+ "headers": {
29
+ "Content-Type": "application/json;charset=utf-8"
30
+ },
31
+ "body": {
32
+ "name": "Mary"
33
+ }
34
+ }
35
+ ```
36
+ <a name="a_request_for_an_alligator_given_there_is_not_an_alligator_named_Mary"></a>
37
+ Given **there is not an alligator named Mary**, upon receiving **a request for an alligator** from Zoo App, with
38
+ ```json
39
+ {
40
+ "method": "get",
41
+ "path": "/alligators/Mary",
42
+ "headers": {
43
+ "Accept": "application/json"
44
+ }
45
+ }
46
+ ```
47
+ Animal Service will respond with:
48
+ ```json
49
+ {
50
+ "status": 404
51
+ }
52
+ ```
53
+ <a name="a_request_for_an_alligator_given_an_error_occurs_retrieving_an_alligator"></a>
54
+ Given **an error occurs retrieving an alligator**, upon receiving **a request for an alligator** from Zoo App, with
55
+ ```json
56
+ {
57
+ "method": "get",
58
+ "path": "/alligators/Mary",
59
+ "headers": {
60
+ "Accept": "application/json"
61
+ }
62
+ }
63
+ ```
64
+ Animal Service will respond with:
65
+ ```json
66
+ {
67
+ "status": 500,
68
+ "headers": {
69
+ "Content-Type": "application/json;charset=utf-8"
70
+ },
71
+ "body": {
72
+ "error": "Argh!!!"
73
+ }
74
+ }
75
+ ```
@@ -0,0 +1,40 @@
1
+ require 'httparty'
2
+ require 'zoo_app/models/alligator'
3
+
4
+ module ZooApp
5
+ class AnimalServiceClient
6
+
7
+ include HTTParty
8
+ base_uri 'animal-service.com'
9
+
10
+ def self.find_alligators
11
+ response = get("/alligators", :headers => {'Accept' => 'application/json'})
12
+ handle_response response do
13
+ parse_body(response).collect do | hash |
14
+ ZooApp::Animals::Alligator.new(hash)
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.find_alligator_by_name name
20
+ response = get("/alligators/#{name}", :headers => {'Accept' => 'application/json'})
21
+ when_successful(response) do
22
+ ZooApp::Animals::Alligator.new(parse_body(response))
23
+ end
24
+ end
25
+
26
+ def self.when_successful response
27
+ if response.success?
28
+ yield
29
+ elsif response.code == 404
30
+ nil
31
+ else
32
+ raise response.body
33
+ end
34
+ end
35
+
36
+ def self.parse_body response
37
+ JSON.parse(response.body, {:symbolize_names => true})
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ module ZooApp
2
+ module Animals
3
+ class Alligator
4
+ attr_reader :name
5
+ def initialize attributes
6
+ @name = attributes[:name]
7
+ end
8
+
9
+ def == other
10
+ other.is_a?(Alligator) && other.name == self.name
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,67 @@
1
+ {
2
+ "provider": {
3
+ "name": "Animal Service"
4
+ },
5
+ "consumer": {
6
+ "name": "Zoo App"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "a request for an alligator",
11
+ "provider_state": "there is an alligator named Mary",
12
+ "request": {
13
+ "method": "get",
14
+ "path": "/alligators/Mary",
15
+ "headers": {
16
+ "Accept": "application/json"
17
+ }
18
+ },
19
+ "response": {
20
+ "status": 200,
21
+ "headers": {
22
+ "Content-Type": "application/json;charset=utf-8"
23
+ },
24
+ "body": {
25
+ "name": "Mary"
26
+ }
27
+ }
28
+ },
29
+ {
30
+ "description": "a request for an alligator",
31
+ "provider_state": "there is not an alligator named Mary",
32
+ "request": {
33
+ "method": "get",
34
+ "path": "/alligators/Mary",
35
+ "headers": {
36
+ "Accept": "application/json"
37
+ }
38
+ },
39
+ "response": {
40
+ "status": 404
41
+ }
42
+ },
43
+ {
44
+ "description": "a request for an alligator",
45
+ "provider_state": "an error occurs retrieving an alligator",
46
+ "request": {
47
+ "method": "get",
48
+ "path": "/alligators/Mary",
49
+ "headers": {
50
+ "Accept": "application/json"
51
+ }
52
+ },
53
+ "response": {
54
+ "status": 500,
55
+ "headers": {
56
+ "Content-Type": "application/json;charset=utf-8"
57
+ },
58
+ "body": {
59
+ "error": "Argh!!!"
60
+ }
61
+ }
62
+ }
63
+ ],
64
+ "metadata": {
65
+ "pactSpecificationVersion": "1.0.0"
66
+ }
67
+ }