pacto 0.3.1 → 0.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +29 -7
  4. data/.travis.yml +8 -1
  5. data/CONTRIBUTING.md +3 -6
  6. data/Gemfile +13 -2
  7. data/Guardfile +4 -4
  8. data/Procfile +1 -0
  9. data/README.md +47 -13
  10. data/Rakefile +66 -19
  11. data/TODO.md +33 -10
  12. data/bin/pacto +4 -0
  13. data/changelog.md +30 -0
  14. data/docs/configuration.md +69 -0
  15. data/docs/consumer.md +18 -0
  16. data/docs/cops.md +39 -0
  17. data/docs/forensics.md +66 -0
  18. data/docs/generation.md +65 -0
  19. data/docs/rake_tasks.md +10 -0
  20. data/docs/rspec.md +0 -0
  21. data/docs/samples.md +133 -0
  22. data/docs/server.md +34 -0
  23. data/docs/server_cli.md +18 -0
  24. data/docs/stenographer.md +20 -0
  25. data/features/configuration/strict_matchers.feature +10 -10
  26. data/features/evolve/existing_services.feature +12 -10
  27. data/features/generate/generation.feature +11 -11
  28. data/features/steps/pacto_steps.rb +17 -12
  29. data/features/stub/templates.feature +4 -4
  30. data/features/support/env.rb +21 -9
  31. data/features/validate/meta_validation.feature +9 -17
  32. data/features/validate/validation.feature +5 -6
  33. data/lib/pacto.rb +41 -33
  34. data/lib/pacto/actor.rb +5 -0
  35. data/lib/pacto/actors/from_examples.rb +67 -0
  36. data/lib/pacto/actors/json_generator.rb +20 -0
  37. data/lib/pacto/cli.rb +75 -0
  38. data/lib/pacto/cli/helpers.rb +20 -0
  39. data/lib/pacto/consumer.rb +80 -0
  40. data/lib/pacto/consumer/faraday_driver.rb +34 -0
  41. data/lib/pacto/contract.rb +48 -20
  42. data/lib/pacto/contract_builder.rb +125 -0
  43. data/lib/pacto/contract_factory.rb +31 -12
  44. data/lib/pacto/contract_files.rb +1 -0
  45. data/lib/pacto/contract_set.rb +12 -0
  46. data/lib/pacto/cops.rb +46 -0
  47. data/lib/pacto/cops/body_cop.rb +23 -0
  48. data/lib/pacto/cops/request_body_cop.rb +10 -0
  49. data/lib/pacto/cops/response_body_cop.rb +10 -0
  50. data/lib/pacto/{validators/response_header_validator.rb → cops/response_header_cop.rb} +9 -15
  51. data/lib/pacto/cops/response_status_cop.rb +18 -0
  52. data/lib/pacto/core/configuration.rb +16 -5
  53. data/lib/pacto/core/contract_registry.rb +13 -32
  54. data/lib/pacto/core/hook.rb +1 -0
  55. data/lib/pacto/core/http_middleware.rb +23 -0
  56. data/lib/pacto/core/investigation_registry.rb +60 -0
  57. data/lib/pacto/core/modes.rb +1 -0
  58. data/lib/pacto/core/pacto_request.rb +59 -0
  59. data/lib/pacto/core/pacto_response.rb +41 -0
  60. data/lib/pacto/dash.rb +9 -0
  61. data/lib/pacto/erb_processor.rb +1 -0
  62. data/lib/pacto/exceptions/invalid_contract.rb +1 -0
  63. data/lib/pacto/extensions.rb +3 -16
  64. data/lib/pacto/forensics/investigation_filter.rb +90 -0
  65. data/lib/pacto/forensics/investigation_matcher.rb +80 -0
  66. data/lib/pacto/generator.rb +31 -53
  67. data/lib/pacto/generator/filters.rb +8 -7
  68. data/lib/pacto/generator/hint.rb +26 -0
  69. data/lib/pacto/generator/native_contract_generator.rb +74 -0
  70. data/lib/pacto/hooks/erb_hook.rb +2 -1
  71. data/lib/pacto/investigation.rb +49 -0
  72. data/lib/pacto/logger.rb +1 -0
  73. data/lib/pacto/meta_schema.rb +12 -6
  74. data/lib/pacto/native_contract_factory.rb +60 -0
  75. data/lib/pacto/observers/stenographer.rb +42 -0
  76. data/lib/pacto/provider.rb +27 -0
  77. data/lib/pacto/rake_task.rb +25 -70
  78. data/lib/pacto/request_clause.rb +31 -29
  79. data/lib/pacto/request_pattern.rb +20 -3
  80. data/lib/pacto/resettable.rb +22 -0
  81. data/lib/pacto/response_clause.rb +5 -12
  82. data/lib/pacto/rspec.rb +38 -31
  83. data/lib/pacto/server.rb +4 -0
  84. data/lib/pacto/stubs/uri_pattern.rb +21 -11
  85. data/lib/pacto/stubs/webmock_adapter.rb +69 -34
  86. data/lib/pacto/swagger_contract_factory.rb +90 -0
  87. data/lib/pacto/test_helper.rb +37 -0
  88. data/lib/pacto/ui.rb +32 -2
  89. data/lib/pacto/uri.rb +2 -1
  90. data/lib/pacto/version.rb +2 -1
  91. data/pacto-server.gemspec +24 -0
  92. data/pacto.gemspec +13 -9
  93. data/resources/contract_schema.json +46 -18
  94. data/resources/draft-04.json +150 -0
  95. data/sample_apis/album/cover_api.rb +12 -0
  96. data/sample_apis/config.ru +25 -0
  97. data/sample_apis/echo_api.rb +26 -0
  98. data/sample_apis/files_api.rb +50 -0
  99. data/sample_apis/hello_api.rb +14 -0
  100. data/sample_apis/ping_api.rb +11 -0
  101. data/sample_apis/reverse_api.rb +20 -0
  102. data/samples/README.md +11 -0
  103. data/samples/Rakefile +2 -0
  104. data/samples/configuration.rb +33 -0
  105. data/samples/consumer.rb +15 -0
  106. data/samples/contracts/README.md +1 -0
  107. data/samples/contracts/contract.js +93 -0
  108. data/samples/contracts/get_album_cover.json +48 -0
  109. data/samples/contracts/localhost/api/echo.json +37 -0
  110. data/samples/contracts/localhost/api/ping.json +38 -0
  111. data/samples/cops.rb +30 -0
  112. data/samples/forensics.rb +54 -0
  113. data/samples/generation.rb +48 -0
  114. data/samples/rake_tasks.sh +7 -0
  115. data/samples/rspec.rb +1 -0
  116. data/samples/samples.rb +92 -0
  117. data/samples/scripts/bootstrap +2 -0
  118. data/samples/scripts/wrapper +11 -0
  119. data/samples/server.rb +24 -0
  120. data/samples/server_cli.sh +12 -0
  121. data/samples/stenographer.rb +17 -0
  122. data/spec/coveralls_helper.rb +1 -0
  123. data/spec/fabricators/contract_fabricator.rb +94 -0
  124. data/spec/fabricators/http_fabricator.rb +48 -0
  125. data/spec/fabricators/webmock_fabricator.rb +24 -0
  126. data/spec/{unit/data → fixtures/contracts}/contract.json +2 -2
  127. data/spec/fixtures/contracts/contract_with_examples.json +58 -0
  128. data/spec/{unit/data → fixtures/contracts}/simple_contract.json +5 -3
  129. data/spec/{integration/data → fixtures/contracts}/strict_contract.json +5 -3
  130. data/spec/{integration/data → fixtures/contracts}/templating_contract.json +3 -2
  131. data/spec/{integration/data/simple_contract.json → fixtures/deprecated_contracts/deprecated_contract.json} +2 -1
  132. data/spec/fixtures/swagger/petstore.yaml +101 -0
  133. data/spec/integration/e2e_spec.rb +19 -20
  134. data/spec/integration/forensics/integration_matcher_spec.rb +90 -0
  135. data/spec/integration/rspec_spec.rb +22 -25
  136. data/spec/integration/templating_spec.rb +7 -6
  137. data/spec/pacto/dummy_server.rb +4 -0
  138. data/spec/pacto/{server → dummy_server}/dummy.rb +7 -6
  139. data/spec/pacto/dummy_server/jruby_workaround_helper.rb +23 -0
  140. data/spec/pacto/{server → dummy_server}/playback_servlet.rb +3 -2
  141. data/spec/spec_helper.rb +16 -7
  142. data/spec/unit/actors/from_examples_spec.rb +70 -0
  143. data/spec/unit/actors/json_generator_spec.rb +105 -0
  144. data/spec/unit/pacto/actor_spec.rb +23 -0
  145. data/spec/unit/pacto/configuration_spec.rb +7 -6
  146. data/spec/unit/pacto/consumer/faraday_driver_spec.rb +40 -0
  147. data/spec/unit/pacto/contract_builder_spec.rb +89 -0
  148. data/spec/unit/pacto/contract_factory_spec.rb +62 -11
  149. data/spec/unit/pacto/contract_files_spec.rb +1 -0
  150. data/spec/unit/pacto/contract_set_spec.rb +36 -0
  151. data/spec/unit/pacto/contract_spec.rb +51 -39
  152. data/spec/unit/pacto/cops/body_cop_spec.rb +107 -0
  153. data/spec/unit/pacto/{validators/response_header_validator_spec.rb → cops/response_header_cop_spec.rb} +30 -19
  154. data/spec/unit/pacto/cops/response_status_cop_spec.rb +26 -0
  155. data/spec/unit/pacto/cops_spec.rb +75 -0
  156. data/spec/unit/pacto/core/configuration_spec.rb +6 -5
  157. data/spec/unit/pacto/core/contract_registry_spec.rb +16 -83
  158. data/spec/unit/pacto/core/http_middleware_spec.rb +36 -0
  159. data/spec/unit/pacto/core/investigation_spec.rb +62 -0
  160. data/spec/unit/pacto/core/modes_spec.rb +5 -4
  161. data/spec/unit/pacto/erb_processor_spec.rb +3 -2
  162. data/spec/unit/pacto/extensions_spec.rb +10 -20
  163. data/spec/unit/pacto/generator/filters_spec.rb +11 -10
  164. data/spec/unit/pacto/generator/native_contract_generator_spec.rb +171 -0
  165. data/spec/unit/{hooks → pacto/hooks}/erb_hook_spec.rb +18 -11
  166. data/spec/unit/pacto/investigation_registry_spec.rb +77 -0
  167. data/spec/unit/pacto/logger_spec.rb +6 -5
  168. data/spec/unit/pacto/meta_schema_spec.rb +5 -4
  169. data/spec/unit/pacto/native_contract_factory_spec.rb +26 -0
  170. data/spec/unit/pacto/pacto_spec.rb +13 -28
  171. data/spec/unit/pacto/request_clause_spec.rb +16 -51
  172. data/spec/unit/pacto/request_pattern_spec.rb +6 -5
  173. data/spec/unit/pacto/response_clause_spec.rb +6 -19
  174. data/spec/unit/pacto/server/playback_servlet_spec.rb +21 -18
  175. data/spec/unit/pacto/stubs/observers/stenographer_spec.rb +33 -0
  176. data/spec/unit/pacto/stubs/uri_pattern_spec.rb +39 -11
  177. data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +67 -117
  178. data/spec/unit/pacto/swagger_contract_factory_spec.rb +56 -0
  179. data/spec/unit/pacto/uri_spec.rb +1 -0
  180. data/tasks/release.rake +57 -0
  181. metadata +247 -76
  182. data/.rubocop-todo.yml +0 -24
  183. data/.ruby-gemset +0 -1
  184. data/.ruby-version +0 -1
  185. data/CHANGELOG +0 -12
  186. data/features/validate/body_only.feature +0 -85
  187. data/lib/pacto/contract_list.rb +0 -17
  188. data/lib/pacto/contract_validator.rb +0 -29
  189. data/lib/pacto/core/validation_registry.rb +0 -40
  190. data/lib/pacto/stubs/webmock_helper.rb +0 -69
  191. data/lib/pacto/validation.rb +0 -54
  192. data/lib/pacto/validators/body_validator.rb +0 -49
  193. data/lib/pacto/validators/request_body_validator.rb +0 -26
  194. data/lib/pacto/validators/response_body_validator.rb +0 -26
  195. data/lib/pacto/validators/response_status_validator.rb +0 -24
  196. data/spec/pacto/server.rb +0 -2
  197. data/spec/unit/pacto/contract_list_spec.rb +0 -35
  198. data/spec/unit/pacto/contract_validator_spec.rb +0 -85
  199. data/spec/unit/pacto/core/validation_registry_spec.rb +0 -76
  200. data/spec/unit/pacto/core/validation_spec.rb +0 -60
  201. data/spec/unit/pacto/generator_spec.rb +0 -132
  202. data/spec/unit/pacto/stubs/webmock_helper_spec.rb +0 -20
  203. data/spec/unit/pacto/validators/body_validator_spec.rb +0 -118
  204. data/spec/unit/pacto/validators/response_status_validator_spec.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 18ae0d545ae833247f073b842eb80cae0bfe15bd
4
- data.tar.gz: 7bbc42514d8b1efecaa5dd650d042f4135ead5da
3
+ metadata.gz: c6cc06d1907fec1501c7069081e958eaac9068d7
4
+ data.tar.gz: 4b6dcac0163d858ed9e085c345a3b956b9ad8621
5
5
  SHA512:
6
- metadata.gz: b3518a69c9f3d65f241f23ed2879349b6016f9411c2991e2bbed85a63ad0091959aedb5d829f7111f14c47a4596a158bf5b3294e8e8c8a951c45f63629cd374a
7
- data.tar.gz: 22d00ac297683e0233c7d002891f5a5f26e133dbc8f7590a3431b567b48200ddd5c0fc02750f9eb17dcd077480a8fe15a9846c8d885f84c51595c1c3cc290fbb
6
+ metadata.gz: e980441e1894a466b5818e099f49523cb0d61b5bc414389186ba57bfb143caf4ee59086aa480c8e9d7c78b3f53ceb4a43c2e91ca55cbf76c04a4b696e459659c
7
+ data.tar.gz: 3611106a78d817d26c98ac7769ac88766f9d0db0f793016066b87e255194466e51340bde66e3509f779e25d92b01e3f9b6d2d2d3b793775ada0f232297438529
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  *.gem
2
+ *.log
3
+ *.pid
2
4
  *.rbc
3
5
  .bundle
4
6
  .config
@@ -22,3 +24,4 @@ tmp
22
24
  .sublime*
23
25
  tags
24
26
  pacto.log
27
+ .polytrix/
@@ -1,10 +1,32 @@
1
- inherit_from: .rubocop-todo.yml
1
+ require: rubocop-rspec
2
+
3
+ Documentation:
4
+ Enabled: false
5
+
6
+ DotPosition:
7
+ Enabled: false
8
+
9
+ LineLength:
10
+ Enabled: false
11
+
12
+ MethodLength:
13
+ Max: 15
14
+
15
+ Style/Encoding:
16
+ EnforcedStyle: when_needed
2
17
 
3
18
  AllCops:
4
- Includes:
19
+ Include:
5
20
  - Guardfile
6
- - Rakefile
7
- - pacto.gemspec
8
- Excludes:
9
- - bin/**
10
- - tmp/**
21
+ - '**/Rakefile'
22
+ - pacto*.gemspec
23
+ Exclude:
24
+ - bin/**/*
25
+ - tmp/**/*
26
+ RSpec/DescribeClass:
27
+ Exclude:
28
+ - samples/**/*
29
+ - spec/integration/**/*
30
+ RSpec/MultipleDescribes:
31
+ Exclude:
32
+ - samples/**/*
@@ -1,8 +1,15 @@
1
1
  language: ruby
2
- before_install: gem update --remote bundler
3
2
  rvm:
4
3
  - 2.1.0
5
4
  - 2.0.0
6
5
  - 1.9.3
6
+ # There is a bug in jruby-1.7.15
7
+ # that is blocking testing
7
8
  - jruby
9
+ before_script:
10
+ - gem install foreman
11
+ - foreman start &
12
+ matrix:
13
+ allow_failures:
14
+ - rvm: jruby
8
15
 
@@ -63,10 +63,7 @@ the analyzer just run:
63
63
 
64
64
  Pacto unit tests and integration test are written in RSpec and the user journey
65
65
  tests are written in Cucumber. For the RSpec tests we suggest to follow the
66
- [Better Specs](http://betterspecs.org/) guideline. For Cucumber test keep in
67
- mind that those will be published on
68
- [Relish](https://www.relishapp.com/maxlinc/pacto/docs), so try to make them
69
- Relish friendly ;).
66
+ [Better Specs](http://betterspecs.org/) guideline.
70
67
 
71
68
  ## <a name="run-tests"></a>Running tests
72
69
 
@@ -75,7 +72,7 @@ tasks:
75
72
 
76
73
  - Unit tests (`bundle exec rake unit`).
77
74
  - Integration tests (`bundle exec rake integration`).
78
- - User journey tests (`bundle exec rake journey`).
75
+ - User journey tests (`bundle exec rake journeys`).
79
76
 
80
77
  It is also possible run specific tests:
81
78
 
@@ -110,7 +107,7 @@ details what Pacto is doing behind the scenes.
110
107
  ### Gemfile.lock
111
108
 
112
109
  Because Pacto is a gem we don't include the Gemfile.lock into the repository
113
- ([here is the reason])(http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/).
110
+ ([here is the reason](http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/)).
114
111
  This could lead to some problems in your daily job as contributor specially
115
112
  when there is an upgrade in any of the gems that Pacto depends upon. That is
116
113
  why we recomend you to remove the Gemfile.lock and generate it
data/Gemfile CHANGED
@@ -1,14 +1,25 @@
1
1
  source 'https://rubygems.org'
2
+ PACTO_HOME = File.expand_path '..', __FILE__
2
3
 
3
4
  # Specify your gem's dependencies in pacto.gemspec
4
5
  gemspec :name => 'pacto'
5
6
 
6
- Dir['pacto-*.gemspec'].each do |gemspec|
7
+ Dir["#{PACTO_HOME}/pacto-*.gemspec"].each do |gemspec|
7
8
  plugin = gemspec.scan(/pacto-(.*)\.gemspec/).flatten.first
8
- gemspec(:name => "pacto-#{plugin}", :development_group => plugin)
9
+ gemspec(:name => "pacto-#{plugin}", :path => PACTO_HOME, :development_group => plugin)
9
10
  end
10
11
 
11
12
  # This is only used by Relish tests. Putting it here let's travis
12
13
  # pre-install so we can speed up the test with `bundle install --local`,
13
14
  # avoiding Aruba timeouts.
14
15
  gem 'excon'
16
+ gem 'octokit'
17
+
18
+ group :samples do
19
+ gem 'grape'
20
+ gem 'grape-swagger'
21
+ gem 'puma'
22
+ gem 'rake'
23
+ gem 'pry'
24
+ gem 'rack'
25
+ end
data/Guardfile CHANGED
@@ -10,10 +10,10 @@ guard :rubocop, all_on_start: false do
10
10
  end
11
11
 
12
12
  group :tests, halt_on_fail: true do
13
- guard :rspec do
13
+ guard :rspec, cmd: 'bundle exec rspec' do
14
14
  # Unit tests
15
15
  watch(%r{^spec/unit/.+_spec\.rb$})
16
- watch(/^lib\/(.+)\.rb$/) { |m| 'spec/unit/#{m[1]}_spec.rb' }
16
+ watch(/^lib\/(.+)\.rb$/) { |_m| 'spec/unit/#{m[1]}_spec.rb' }
17
17
  watch('spec/spec_helper.rb') { 'spec/unit' }
18
18
  watch('spec/unit/spec_helper.rb') { 'spec/unit' }
19
19
  watch(%r{^spec/unit/data/.+\.json$}) { 'spec/unit' }
@@ -27,9 +27,9 @@ group :tests, halt_on_fail: true do
27
27
  watch(%r{^spec/integration/data/.+\.json$}) { 'spec/integration' }
28
28
  end
29
29
 
30
- guard :cucumber, all_on_start: false do
30
+ guard :cucumber, cmd: 'bundle exec cucumber', all_on_start: false do
31
31
  watch(/^features\/.+\.feature$/)
32
32
  watch(%r{^features/support/.+$}) { 'features' }
33
- watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join('**/#{m[1]}.feature')][0] || 'features' }
33
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |_m| Dir[File.join('**/#{m[1]}.feature')][0] || 'features' }
34
34
  end
35
35
  end
@@ -0,0 +1 @@
1
+ sample_apis: sh -c 'bundle exec rackup -s puma -o localhost -p $PORT sample_apis/config.ru'
data/README.md CHANGED
@@ -48,9 +48,11 @@ Pacto can provide a [**contract writer**](#generating) that tries to strike a ba
48
48
 
49
49
  Pacto can perform three activities: generating, validating, or stubbing services. You can do each of these activities against either live or stubbed services.
50
50
 
51
+ You can also use [Pacto Server](#pacto-server-non-ruby-usage) if you are working with non-Ruby projects.
52
+
51
53
  ### Configuration
52
54
 
53
- In order to start with Pacto, you just need to require it and optionally customize the default [Configuration](https://www.relishapp.com/maxlinc/pacto/docs/configuration). For example:
55
+ In order to start with Pacto, you just need to require it and optionally customize the default [Configuration](docs/configuration.md). For example:
54
56
 
55
57
  ```ruby
56
58
  require 'pacto'
@@ -75,7 +77,7 @@ We know we cannot generate perfect Contracts, especially if we only have one sam
75
77
 
76
78
  ### Contract Lists
77
79
 
78
- In order to stub or validate or stub a group of contracts you need to create a ContractList.
80
+ In order to stub or validate a group of contracts you need to create a ContractList.
79
81
  A ContractList represent a collection of endpoints attached to the same host.
80
82
 
81
83
  ```ruby
@@ -92,7 +94,7 @@ Once you have a ContractList, you can validate all the contracts against the liv
92
94
 
93
95
  ```ruby
94
96
  contracts = Pacto.load_contracts('contracts/services', 'http://example.com')
95
- contracts.validate_all
97
+ contracts.simulate_consumers
96
98
  ```
97
99
 
98
100
  This method will hit the real endpoint, with a request created based on the request part of the contract.
@@ -108,36 +110,68 @@ To generate stubs based on a ContractList you can run:
108
110
 
109
111
  ```ruby
110
112
  contracts = Pacto.load_contracts('contracts/services', 'http://example.com')
111
- contracts.stub_all
113
+ contracts.stub_providers
112
114
  ```
113
115
 
114
116
  This method uses webmock to ensure that whenever you make a request against one of contracts you actually get a stubbed response,
115
117
  based on the default values specified on the contract, instead of hitting the real provider.
116
118
 
117
- You can override any default value on the contracts by providing a hash of optional values to the stub_all method. This
119
+ You can override any default value on the contracts by providing a hash of optional values to the stub_providers method. This
118
120
  will override the keys for every contract in the list
119
121
 
120
122
  ```ruby
121
123
  contracts = Pacto.load_contracts('contracts/services', 'http://example.com')
122
- contracts.stub_all(request_id: 14, name: "Marcos")
124
+ contracts.stub_providers(request_id: 14, name: "Marcos")
123
125
  ```
124
126
 
125
127
  ## Pacto Server (non-Ruby usage)
126
128
 
127
129
  **See also: http://thoughtworks.github.io/pacto/patterns/polyglot/**
128
130
 
129
- It is really easy to embed Pacto inside a small server. We haven't bundled a server inside of Pacto, but check out [pacto-demo](https://github.com/thoughtworks/pacto-demo) to see how easily you can expose Pacto via server.
131
+ We've bundled a small server that embeds pacto so you can use it for non-Ruby projects. If you want to take advantage of the full features, you'll still need to use Ruby (usually rspec) to drive your API testing. You can run just the server in order to stub or to write validation issues to a log, but you won't have access to the full API fail your tests if there were validation problems.
132
+
133
+ ### Command-line
134
+
135
+ The command-line version of the server will show you all the options. These same options are used when you launch the server from within rspec. In order to see the options:
136
+ `bundle exec pacto-server --help`
130
137
 
131
- That demo lets you easily run a server in several modes:
138
+ Some examples:
132
139
  ```sh
133
- $ bundle exec ruby pacto_server.rb -sv --generate
140
+ $ bundle exec pacto-server -sv --generate
134
141
  # Runs a server that will generate Contracts for each request received
135
- $ bundle exec ruby pacto_server.rb -sv --validate
142
+ $ bundle exec pacto-server -sv --stub --validate
136
143
  # Runs the server that provides stubs and checks them against Contracts
137
- $ bundle exec ruby pacto_server.rb -sv --validate --host http://example.com
144
+ $ bundle exec pacto-server -sv --live --validate --host
138
145
  # Runs the server that acts as a proxy to http://example.com, validating each request/response against a Contract
139
146
  ```
140
147
 
148
+ ### RSpec test helper
149
+
150
+ You can also launch a server from within an rspec test. The server does start up an external port and runs asynchronously so it doens't block your main test thread from kicking off your consumer code. This gives you an externally accessable server that non-Ruby clients can hit, but still gives you the full Pacto API in order to validate and spy on HTTP interactions.
151
+
152
+ Example usage of the rspec test helper:
153
+ ```ruby
154
+ require 'rspec'
155
+ require 'pacto/rspec'
156
+ require 'pacto/test_helper'
157
+
158
+ describe 'my consumer' do
159
+ include Pacto::TestHelper
160
+
161
+ it 'calls a service' do
162
+ with_pacto(
163
+ :port => 5000,
164
+ :directory => '../spec/integration/data',
165
+ :stub => true) do |pacto_endpoint|
166
+ # call your code
167
+ system "curl #{pacto_endpoint}/echo"
168
+ # check results
169
+ expect(Pacto).to have_validated(:get, 'https://localhost/echo')
170
+ end
171
+ end
172
+ end
173
+ ```
174
+
141
175
  ## Rake Tasks
142
176
 
143
177
  Pacto includes a few Rake tasks to help with common tasks. If you want to use these tasks, just add this top your Rakefile:
@@ -153,7 +187,7 @@ rake pacto:meta_validate[dir] # Validates a directory of contr
153
187
  rake pacto:validate[host,dir] # Validates all contracts in a given directory against a given host
154
188
  ```
155
189
 
156
- The pacto:generate task will take partially defined Contracts and generate the missing pieces. See [Generate](https://www.relishapp.com/maxlinc/pacto/docs/generate) for more details.
190
+ The pacto:generate task will take partially defined Contracts and generate the missing pieces. See [Generate](docs/generation.md) for more details.
157
191
 
158
192
  The pacto:meta_validate task makes sure that your Contracts are valid. It only checks the Contracts, not the services that implement them.
159
193
 
@@ -216,4 +250,4 @@ to the /hello_world endpoint of a provider:
216
250
 
217
251
  ## Contributing
218
252
 
219
- Read the CONTRIBUTING.md file.
253
+ Read the [CONTRIBUTING.md](CONTRIBUTING.md) file.
data/Rakefile CHANGED
@@ -1,15 +1,17 @@
1
1
  require 'rspec/core/rake_task'
2
- require 'pacto/rake_task'
3
2
  require 'cucumber'
4
3
  require 'cucumber/rake/task'
5
4
  require 'coveralls/rake/task'
6
5
  require 'rubocop/rake_task'
7
6
  require 'rake/notes/rake_task'
8
-
7
+ require 'rake/packagetask'
8
+ Dir.glob('tasks/*.rake').each { |r| import r }
9
9
  Coveralls::RakeTask.new
10
10
 
11
- Rubocop::RakeTask.new(:rubocop) do |task|
12
- # abort rake on failure
11
+ require 'pacto/rake_task' # FIXME: This require turns on WebMock
12
+ WebMock.allow_net_connect!
13
+
14
+ RuboCop::RakeTask.new(:rubocop) do |task|
13
15
  task.fail_on_error = true
14
16
  end
15
17
 
@@ -25,7 +27,23 @@ RSpec::Core::RakeTask.new(:integration) do |t|
25
27
  t.pattern = 'spec/integration/**/*_spec.rb'
26
28
  end
27
29
 
28
- task :default => [:unit, :integration, :journeys, :rubocop, 'coveralls:push']
30
+ task default: [:unit, :integration, :journeys, :samples, :rubocop, 'coveralls:push']
31
+
32
+ %w(unit integration journeys samples).each do |taskname|
33
+ task taskname => 'smoke_test_services'
34
+ end
35
+
36
+ desc 'Run the samples'
37
+ task :samples do
38
+ FileUtils.rm_rf('samples/tmp')
39
+ sh 'bundle exec polytrix exec --solo=samples --solo-glob="*.{rb,sh}"'
40
+ sh 'bundle exec polytrix generate code2doc --solo=samples --solo-glob="*.{rb,sh}"'
41
+ end
42
+
43
+ desc 'Build the documentation from the samples'
44
+ task :documentation do
45
+ sh "docco -t #{Dir.pwd}/docco_embeddable_layout/docco.jst samples/*"
46
+ end
29
47
 
30
48
  desc 'Build gems into the pkg directory'
31
49
  task :build do
@@ -37,28 +55,57 @@ task :build do
37
55
  FileUtils.mv(Dir['*.gem'], 'pkg')
38
56
  end
39
57
 
40
- desc 'Tags version, pushes to remote, and pushes gems'
41
- task :release => :build do
42
- sh 'git', 'tag', '-m', changelog, "v#{Pacto::VERSION}"
43
- sh 'git push origin master'
44
- sh "git push origin v#{Pacto::VERSION}"
45
- sh 'ls pkg/*.gem | xargs -n 1 gem push'
46
- end
47
-
48
- task :changelog do
49
- changelog
58
+ Rake::PackageTask.new('pacto_docs', Pacto::VERSION) do |p|
59
+ p.need_zip = true
60
+ p.need_tar = true
61
+ p.package_files.include('docs/**/*')
50
62
  end
51
63
 
52
64
  def changelog
53
65
  changelog = File.read('CHANGELOG').split("\n\n\n", 2).first
54
- confirm "Does the CHANGELOG look correct? ", changelog
66
+ confirm 'Does the CHANGELOG look correct? ', changelog
55
67
  end
56
68
 
57
69
  def confirm(question, data)
58
- puts "Please confirm..."
70
+ puts 'Please confirm...'
59
71
  puts data
60
72
  print question
61
- abort "Aborted" unless $stdin.gets.strip == 'y'
62
- puts "Confirmed"
73
+ abort 'Aborted' unless $stdin.gets.strip == 'y'
74
+ puts 'Confirmed'
63
75
  data
64
76
  end
77
+
78
+ desc 'Make sure the sample services are running'
79
+ task :smoke_test_services do
80
+ require 'faraday'
81
+ begin
82
+ retryable(tries: 5, sleep: 1) do
83
+ Faraday.get('http://localhost:5000/api/ping')
84
+ end
85
+ rescue
86
+ abort 'Could not connect to the demo services, please start them with `foreman start`'
87
+ end
88
+ end
89
+
90
+ # Retries a given block a specified number of times in the
91
+ # event the specified exception is raised. If the retries
92
+ # run out, the final exception is raised.
93
+ #
94
+ # This code is slightly adapted from https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/retryable.rb,
95
+ # which is in turn adapted slightly from the following blog post:
96
+ # http://blog.codefront.net/2008/01/14/retrying-code-blocks-in-ruby-on-exceptions-whatever/
97
+ def retryable(opts = nil)
98
+ opts = { tries: 1, on: Exception }.merge(opts || {})
99
+
100
+ begin
101
+ return yield
102
+ rescue *opts[:on] => e
103
+ if (opts[:tries] -= 1) > 0
104
+ $stderr.puts("Retryable exception raised: #{e.inspect}")
105
+
106
+ sleep opts[:sleep].to_f if opts[:sleep]
107
+ retry
108
+ end
109
+ raise
110
+ end
111
+ end
data/TODO.md CHANGED
@@ -1,19 +1,42 @@
1
1
  # TODO
2
2
 
3
+ # v0.4
4
+
5
+ ## Thor
6
+ - Kill rake tasks, replace w/ pacto binary
7
+ - Split Pacto server to separate repo??
8
+
9
+ ## Swagger converter
10
+ - Legacy contracts -> Swagger
11
+
12
+ ## Swagger concepts not yet supported by Pacto
13
+ - Support schemes (multiple)
14
+ - Support multiple report types
15
+ - Validate parameters
16
+ - Support Swagger formats/serializations
17
+ - Support Swagger examples, or extension for examples
18
+
19
+ ## Documentation
20
+
21
+ - Polytrix samples -> docs
22
+
23
+ # v0.5
24
+
25
+ ## Swagger
26
+ - Support multiple media types (not just JSON)
27
+ - Extension: templates for more advanced stubbing
28
+ - Patterns: detect creation, auto-delete
29
+ - Configure multiple producers: pacto server w/ multiple ports
30
+
31
+ # v0.6
32
+
3
33
  ## Nice to have
4
34
 
5
- - Cucumber Tests as docs (see https://relishapp.com/cucumber/cucumber/docs/);
6
- - Fake Server (sinatra app generating fake responses based on the contracts);
7
- - Optional "require" format for JSON Schema: # 'required': ['id', 'categorias', 'titulo', ...];
8
- - Contract variables for easy writing. Such as: 'path': '/member/{id}';
9
- - Add JSHint rake task to validate contracts syntax;
35
+
36
+ # Someday
37
+
10
38
  - Pretty output for hash difference (using something like [hashdiff](https://github.com/liufengyun/hashdiff)).
11
39
  - A default header in the response marking the response as "mocked"
12
- - Parameter matcher should use an idea of "subset" instead of matching all the parameters
13
- - 'default' value to be used when it is present with an array of types
14
- - Support 'null' attribute type
15
- - Validate contract structure in a rake task. Then assume all contracts are valid.
16
- - When a request is not OK (200), the body may not be a json. Add support to ignore the body.
17
40
 
18
41
  ## Assumptions
19
42