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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +29 -7
- data/.travis.yml +8 -1
- data/CONTRIBUTING.md +3 -6
- data/Gemfile +13 -2
- data/Guardfile +4 -4
- data/Procfile +1 -0
- data/README.md +47 -13
- data/Rakefile +66 -19
- data/TODO.md +33 -10
- data/bin/pacto +4 -0
- data/changelog.md +30 -0
- data/docs/configuration.md +69 -0
- data/docs/consumer.md +18 -0
- data/docs/cops.md +39 -0
- data/docs/forensics.md +66 -0
- data/docs/generation.md +65 -0
- data/docs/rake_tasks.md +10 -0
- data/docs/rspec.md +0 -0
- data/docs/samples.md +133 -0
- data/docs/server.md +34 -0
- data/docs/server_cli.md +18 -0
- data/docs/stenographer.md +20 -0
- data/features/configuration/strict_matchers.feature +10 -10
- data/features/evolve/existing_services.feature +12 -10
- data/features/generate/generation.feature +11 -11
- data/features/steps/pacto_steps.rb +17 -12
- data/features/stub/templates.feature +4 -4
- data/features/support/env.rb +21 -9
- data/features/validate/meta_validation.feature +9 -17
- data/features/validate/validation.feature +5 -6
- data/lib/pacto.rb +41 -33
- data/lib/pacto/actor.rb +5 -0
- data/lib/pacto/actors/from_examples.rb +67 -0
- data/lib/pacto/actors/json_generator.rb +20 -0
- data/lib/pacto/cli.rb +75 -0
- data/lib/pacto/cli/helpers.rb +20 -0
- data/lib/pacto/consumer.rb +80 -0
- data/lib/pacto/consumer/faraday_driver.rb +34 -0
- data/lib/pacto/contract.rb +48 -20
- data/lib/pacto/contract_builder.rb +125 -0
- data/lib/pacto/contract_factory.rb +31 -12
- data/lib/pacto/contract_files.rb +1 -0
- data/lib/pacto/contract_set.rb +12 -0
- data/lib/pacto/cops.rb +46 -0
- data/lib/pacto/cops/body_cop.rb +23 -0
- data/lib/pacto/cops/request_body_cop.rb +10 -0
- data/lib/pacto/cops/response_body_cop.rb +10 -0
- data/lib/pacto/{validators/response_header_validator.rb → cops/response_header_cop.rb} +9 -15
- data/lib/pacto/cops/response_status_cop.rb +18 -0
- data/lib/pacto/core/configuration.rb +16 -5
- data/lib/pacto/core/contract_registry.rb +13 -32
- data/lib/pacto/core/hook.rb +1 -0
- data/lib/pacto/core/http_middleware.rb +23 -0
- data/lib/pacto/core/investigation_registry.rb +60 -0
- data/lib/pacto/core/modes.rb +1 -0
- data/lib/pacto/core/pacto_request.rb +59 -0
- data/lib/pacto/core/pacto_response.rb +41 -0
- data/lib/pacto/dash.rb +9 -0
- data/lib/pacto/erb_processor.rb +1 -0
- data/lib/pacto/exceptions/invalid_contract.rb +1 -0
- data/lib/pacto/extensions.rb +3 -16
- data/lib/pacto/forensics/investigation_filter.rb +90 -0
- data/lib/pacto/forensics/investigation_matcher.rb +80 -0
- data/lib/pacto/generator.rb +31 -53
- data/lib/pacto/generator/filters.rb +8 -7
- data/lib/pacto/generator/hint.rb +26 -0
- data/lib/pacto/generator/native_contract_generator.rb +74 -0
- data/lib/pacto/hooks/erb_hook.rb +2 -1
- data/lib/pacto/investigation.rb +49 -0
- data/lib/pacto/logger.rb +1 -0
- data/lib/pacto/meta_schema.rb +12 -6
- data/lib/pacto/native_contract_factory.rb +60 -0
- data/lib/pacto/observers/stenographer.rb +42 -0
- data/lib/pacto/provider.rb +27 -0
- data/lib/pacto/rake_task.rb +25 -70
- data/lib/pacto/request_clause.rb +31 -29
- data/lib/pacto/request_pattern.rb +20 -3
- data/lib/pacto/resettable.rb +22 -0
- data/lib/pacto/response_clause.rb +5 -12
- data/lib/pacto/rspec.rb +38 -31
- data/lib/pacto/server.rb +4 -0
- data/lib/pacto/stubs/uri_pattern.rb +21 -11
- data/lib/pacto/stubs/webmock_adapter.rb +69 -34
- data/lib/pacto/swagger_contract_factory.rb +90 -0
- data/lib/pacto/test_helper.rb +37 -0
- data/lib/pacto/ui.rb +32 -2
- data/lib/pacto/uri.rb +2 -1
- data/lib/pacto/version.rb +2 -1
- data/pacto-server.gemspec +24 -0
- data/pacto.gemspec +13 -9
- data/resources/contract_schema.json +46 -18
- data/resources/draft-04.json +150 -0
- data/sample_apis/album/cover_api.rb +12 -0
- data/sample_apis/config.ru +25 -0
- data/sample_apis/echo_api.rb +26 -0
- data/sample_apis/files_api.rb +50 -0
- data/sample_apis/hello_api.rb +14 -0
- data/sample_apis/ping_api.rb +11 -0
- data/sample_apis/reverse_api.rb +20 -0
- data/samples/README.md +11 -0
- data/samples/Rakefile +2 -0
- data/samples/configuration.rb +33 -0
- data/samples/consumer.rb +15 -0
- data/samples/contracts/README.md +1 -0
- data/samples/contracts/contract.js +93 -0
- data/samples/contracts/get_album_cover.json +48 -0
- data/samples/contracts/localhost/api/echo.json +37 -0
- data/samples/contracts/localhost/api/ping.json +38 -0
- data/samples/cops.rb +30 -0
- data/samples/forensics.rb +54 -0
- data/samples/generation.rb +48 -0
- data/samples/rake_tasks.sh +7 -0
- data/samples/rspec.rb +1 -0
- data/samples/samples.rb +92 -0
- data/samples/scripts/bootstrap +2 -0
- data/samples/scripts/wrapper +11 -0
- data/samples/server.rb +24 -0
- data/samples/server_cli.sh +12 -0
- data/samples/stenographer.rb +17 -0
- data/spec/coveralls_helper.rb +1 -0
- data/spec/fabricators/contract_fabricator.rb +94 -0
- data/spec/fabricators/http_fabricator.rb +48 -0
- data/spec/fabricators/webmock_fabricator.rb +24 -0
- data/spec/{unit/data → fixtures/contracts}/contract.json +2 -2
- data/spec/fixtures/contracts/contract_with_examples.json +58 -0
- data/spec/{unit/data → fixtures/contracts}/simple_contract.json +5 -3
- data/spec/{integration/data → fixtures/contracts}/strict_contract.json +5 -3
- data/spec/{integration/data → fixtures/contracts}/templating_contract.json +3 -2
- data/spec/{integration/data/simple_contract.json → fixtures/deprecated_contracts/deprecated_contract.json} +2 -1
- data/spec/fixtures/swagger/petstore.yaml +101 -0
- data/spec/integration/e2e_spec.rb +19 -20
- data/spec/integration/forensics/integration_matcher_spec.rb +90 -0
- data/spec/integration/rspec_spec.rb +22 -25
- data/spec/integration/templating_spec.rb +7 -6
- data/spec/pacto/dummy_server.rb +4 -0
- data/spec/pacto/{server → dummy_server}/dummy.rb +7 -6
- data/spec/pacto/dummy_server/jruby_workaround_helper.rb +23 -0
- data/spec/pacto/{server → dummy_server}/playback_servlet.rb +3 -2
- data/spec/spec_helper.rb +16 -7
- data/spec/unit/actors/from_examples_spec.rb +70 -0
- data/spec/unit/actors/json_generator_spec.rb +105 -0
- data/spec/unit/pacto/actor_spec.rb +23 -0
- data/spec/unit/pacto/configuration_spec.rb +7 -6
- data/spec/unit/pacto/consumer/faraday_driver_spec.rb +40 -0
- data/spec/unit/pacto/contract_builder_spec.rb +89 -0
- data/spec/unit/pacto/contract_factory_spec.rb +62 -11
- data/spec/unit/pacto/contract_files_spec.rb +1 -0
- data/spec/unit/pacto/contract_set_spec.rb +36 -0
- data/spec/unit/pacto/contract_spec.rb +51 -39
- data/spec/unit/pacto/cops/body_cop_spec.rb +107 -0
- data/spec/unit/pacto/{validators/response_header_validator_spec.rb → cops/response_header_cop_spec.rb} +30 -19
- data/spec/unit/pacto/cops/response_status_cop_spec.rb +26 -0
- data/spec/unit/pacto/cops_spec.rb +75 -0
- data/spec/unit/pacto/core/configuration_spec.rb +6 -5
- data/spec/unit/pacto/core/contract_registry_spec.rb +16 -83
- data/spec/unit/pacto/core/http_middleware_spec.rb +36 -0
- data/spec/unit/pacto/core/investigation_spec.rb +62 -0
- data/spec/unit/pacto/core/modes_spec.rb +5 -4
- data/spec/unit/pacto/erb_processor_spec.rb +3 -2
- data/spec/unit/pacto/extensions_spec.rb +10 -20
- data/spec/unit/pacto/generator/filters_spec.rb +11 -10
- data/spec/unit/pacto/generator/native_contract_generator_spec.rb +171 -0
- data/spec/unit/{hooks → pacto/hooks}/erb_hook_spec.rb +18 -11
- data/spec/unit/pacto/investigation_registry_spec.rb +77 -0
- data/spec/unit/pacto/logger_spec.rb +6 -5
- data/spec/unit/pacto/meta_schema_spec.rb +5 -4
- data/spec/unit/pacto/native_contract_factory_spec.rb +26 -0
- data/spec/unit/pacto/pacto_spec.rb +13 -28
- data/spec/unit/pacto/request_clause_spec.rb +16 -51
- data/spec/unit/pacto/request_pattern_spec.rb +6 -5
- data/spec/unit/pacto/response_clause_spec.rb +6 -19
- data/spec/unit/pacto/server/playback_servlet_spec.rb +21 -18
- data/spec/unit/pacto/stubs/observers/stenographer_spec.rb +33 -0
- data/spec/unit/pacto/stubs/uri_pattern_spec.rb +39 -11
- data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +67 -117
- data/spec/unit/pacto/swagger_contract_factory_spec.rb +56 -0
- data/spec/unit/pacto/uri_spec.rb +1 -0
- data/tasks/release.rake +57 -0
- metadata +247 -76
- data/.rubocop-todo.yml +0 -24
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/CHANGELOG +0 -12
- data/features/validate/body_only.feature +0 -85
- data/lib/pacto/contract_list.rb +0 -17
- data/lib/pacto/contract_validator.rb +0 -29
- data/lib/pacto/core/validation_registry.rb +0 -40
- data/lib/pacto/stubs/webmock_helper.rb +0 -69
- data/lib/pacto/validation.rb +0 -54
- data/lib/pacto/validators/body_validator.rb +0 -49
- data/lib/pacto/validators/request_body_validator.rb +0 -26
- data/lib/pacto/validators/response_body_validator.rb +0 -26
- data/lib/pacto/validators/response_status_validator.rb +0 -24
- data/spec/pacto/server.rb +0 -2
- data/spec/unit/pacto/contract_list_spec.rb +0 -35
- data/spec/unit/pacto/contract_validator_spec.rb +0 -85
- data/spec/unit/pacto/core/validation_registry_spec.rb +0 -76
- data/spec/unit/pacto/core/validation_spec.rb +0 -60
- data/spec/unit/pacto/generator_spec.rb +0 -132
- data/spec/unit/pacto/stubs/webmock_helper_spec.rb +0 -20
- data/spec/unit/pacto/validators/body_validator_spec.rb +0 -118
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6cc06d1907fec1501c7069081e958eaac9068d7
|
4
|
+
data.tar.gz: 4b6dcac0163d858ed9e085c345a3b956b9ad8621
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e980441e1894a466b5818e099f49523cb0d61b5bc414389186ba57bfb143caf4ee59086aa480c8e9d7c78b3f53ceb4a43c2e91ca55cbf76c04a4b696e459659c
|
7
|
+
data.tar.gz: 3611106a78d817d26c98ac7769ac88766f9d0db0f793016066b87e255194466e51340bde66e3509f779e25d92b01e3f9b6d2d2d3b793775ada0f232297438529
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,10 +1,32 @@
|
|
1
|
-
|
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
|
-
|
19
|
+
Include:
|
5
20
|
- Guardfile
|
6
|
-
- Rakefile
|
7
|
-
- pacto
|
8
|
-
|
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/**/*
|
data/.travis.yml
CHANGED
@@ -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
|
|
data/CONTRIBUTING.md
CHANGED
@@ -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.
|
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
|
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]
|
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[
|
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$/) { |
|
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$}) { |
|
33
|
+
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |_m| Dir[File.join('**/#{m[1]}.feature')][0] || 'features' }
|
34
34
|
end
|
35
35
|
end
|
data/Procfile
ADDED
@@ -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](
|
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
|
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.
|
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.
|
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
|
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.
|
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
|
-
|
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
|
-
|
138
|
+
Some examples:
|
132
139
|
```sh
|
133
|
-
$ bundle exec
|
140
|
+
$ bundle exec pacto-server -sv --generate
|
134
141
|
# Runs a server that will generate Contracts for each request received
|
135
|
-
$ bundle exec
|
142
|
+
$ bundle exec pacto-server -sv --stub --validate
|
136
143
|
# Runs the server that provides stubs and checks them against Contracts
|
137
|
-
$ bundle exec
|
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](
|
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
|
-
|
12
|
-
|
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 :
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
66
|
+
confirm 'Does the CHANGELOG look correct? ', changelog
|
55
67
|
end
|
56
68
|
|
57
69
|
def confirm(question, data)
|
58
|
-
puts
|
70
|
+
puts 'Please confirm...'
|
59
71
|
puts data
|
60
72
|
print question
|
61
|
-
abort
|
62
|
-
puts
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
|