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
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module Pacto
|
5
|
+
module Observers
|
6
|
+
describe Stenographer do
|
7
|
+
let(:pacto_request) { Fabricate(:pacto_request) }
|
8
|
+
let(:pacto_response) { Fabricate(:pacto_response) }
|
9
|
+
let(:contract) { Fabricate(:contract) }
|
10
|
+
let(:citations) { %w(one two) }
|
11
|
+
let(:investigation) { Pacto::Investigation.new(pacto_request, pacto_response, contract, citations) }
|
12
|
+
|
13
|
+
subject(:stream) { StringIO.new }
|
14
|
+
|
15
|
+
subject { described_class.new stream }
|
16
|
+
|
17
|
+
it 'writes to the stenographer log stream' do
|
18
|
+
subject.log_investigation investigation
|
19
|
+
expected_log_line = "request #{contract.name.inspect}, values: {}, response: {status: #{pacto_response.status}} # #{citations.size} contract violations\n"
|
20
|
+
expect(stream.string).to eq expected_log_line
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when the stenographer log stream is nil' do
|
24
|
+
let(:stream) { nil }
|
25
|
+
|
26
|
+
it 'does nothing' do
|
27
|
+
# Would raise an error if it tried to write to stream
|
28
|
+
subject.log_investigation investigation
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,27 +1,55 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'spec_helper'
|
2
3
|
|
3
4
|
module Pacto
|
4
5
|
describe UriPattern do
|
5
6
|
context 'with non-strict matchers' do
|
6
|
-
|
7
|
+
before(:each) do
|
7
8
|
Pacto.configuration.strict_matchers = false
|
8
|
-
request = double(host: 'myhost.com', path: '/stuff')
|
9
|
-
expect(UriPattern.for(request).to_s).to eq(/myhost\.com\/stuff/.to_s)
|
10
9
|
end
|
11
10
|
|
12
|
-
it '
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
expect(UriPattern.for(request).
|
11
|
+
it 'appends host if path is an Addressable::Template' do
|
12
|
+
path_pattern = '/{account}/data{.format}{?page,per_page}'
|
13
|
+
path = Addressable::Template.new path_pattern
|
14
|
+
request = Fabricate(:request_clause, host: 'https://www.example.com', path: path)
|
15
|
+
expect(UriPattern.for(request).pattern).to include(Addressable::Template.new("https://www.example.com#{path_pattern}").pattern)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns a URITemplate containing the host and path and wildcard vars' do
|
19
|
+
request = Fabricate(:request_clause, host: 'myhost.com', path: '/stuff')
|
20
|
+
uri_pattern = UriPattern.for(request)
|
21
|
+
expect(uri_pattern.pattern).to eql('{scheme}://myhost.com/stuff{?anyvars*}')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'convers segments preceded by : into variables', :deprecated do
|
25
|
+
request = Fabricate(:request_clause, host: 'myhost.com', path: '/:id')
|
26
|
+
uri_pattern = UriPattern.for(request)
|
27
|
+
expect(uri_pattern.keys).to include('id')
|
28
|
+
expect(uri_pattern.pattern).to_not include(':id')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'creates a regex that does not allow additional path elements' do
|
32
|
+
request = Fabricate(:request_clause, host: 'myhost.com', path: '/:id')
|
33
|
+
pattern = UriPattern.for(request)
|
34
|
+
expect(pattern).to match('http://myhost.com/foo')
|
35
|
+
expect(pattern).to_not match('http://myhost.com/foo/bar')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'creates a regex that does allow query parameters', :deprecated do
|
39
|
+
request = Fabricate(:request_clause, host: 'myhost.com', path: '/:id')
|
40
|
+
pattern = UriPattern.for(request)
|
41
|
+
expect(pattern.match('http://myhost.com/foo?a=b')). to be_truthy
|
42
|
+
expect(pattern.match('http://myhost.com/foo?a=b&c=d')).to be_truthy
|
17
43
|
end
|
18
44
|
end
|
19
45
|
|
20
|
-
|
46
|
+
# Strict/relaxed matching should be done against the full URI or path only
|
47
|
+
context 'with strict matchers', deprecated: true do
|
21
48
|
it 'returns a string with the host and path' do
|
22
49
|
Pacto.configuration.strict_matchers = true
|
23
|
-
request =
|
24
|
-
|
50
|
+
request = Fabricate(:request_clause, host: 'myhost.com', path: '/stuff')
|
51
|
+
uri_pattern = UriPattern.for(request)
|
52
|
+
expect(uri_pattern.pattern).to eq('{scheme}://myhost.com/stuff')
|
25
53
|
end
|
26
54
|
end
|
27
55
|
end
|
@@ -1,89 +1,85 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
module Pacto
|
2
3
|
module Stubs
|
4
|
+
# FIXME: Review this test and see which requests are Pacto vs WebMock, then use Fabricate
|
3
5
|
describe WebMockAdapter do
|
6
|
+
let(:middleware) { double('middleware') }
|
7
|
+
|
4
8
|
let(:request) do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
Fabricate(:request_clause,
|
10
|
+
host: 'http://localhost',
|
11
|
+
http_method: http_method,
|
12
|
+
path: '/hello_world',
|
13
|
+
headers: { 'Accept' => 'application/json' },
|
14
|
+
params: { 'foo' => 'bar' }
|
11
15
|
)
|
12
16
|
end
|
13
17
|
|
14
|
-
let(:
|
18
|
+
let(:http_method) { :get }
|
15
19
|
|
16
20
|
let(:response) do
|
17
|
-
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
+
Fabricate(
|
22
|
+
:response_clause,
|
23
|
+
status: 200,
|
24
|
+
headers: {},
|
25
|
+
schema: {
|
26
|
+
type: 'object',
|
27
|
+
required: ['message'],
|
28
|
+
properties: {
|
29
|
+
message: {
|
30
|
+
type: 'string',
|
31
|
+
default: 'foo'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
21
35
|
)
|
22
36
|
end
|
23
37
|
|
38
|
+
let(:contract) do
|
39
|
+
Fabricate(:contract, request: request, response: response)
|
40
|
+
end
|
41
|
+
|
24
42
|
let(:body) do
|
25
|
-
{'message' => 'foo'}
|
43
|
+
{ 'message' => 'foo' }
|
26
44
|
end
|
27
45
|
|
28
46
|
let(:stubbed_request) do
|
29
47
|
{
|
30
|
-
:
|
48
|
+
path: nil
|
31
49
|
}
|
32
50
|
end
|
33
51
|
|
34
52
|
let(:request_pattern) { double('request_pattern') }
|
35
53
|
|
36
|
-
subject(:
|
54
|
+
subject(:adapter) { WebMockAdapter.new middleware }
|
37
55
|
|
38
56
|
before(:each) do
|
39
|
-
stubbed_request.
|
40
|
-
|
41
|
-
:headers => response.headers,
|
42
|
-
:body => response.body.to_json
|
43
|
-
)
|
44
|
-
stubbed_request.stub(:request_pattern).and_return request_pattern
|
57
|
+
allow(stubbed_request).to receive(:to_return).with(no_args)
|
58
|
+
allow(stubbed_request).to receive(:request_pattern).and_return request_pattern
|
45
59
|
end
|
46
60
|
|
47
61
|
describe '#initialize' do
|
48
62
|
it 'sets up a hook' do
|
49
|
-
WebMock.
|
50
|
-
expect(block.parameters).to
|
63
|
+
expect(WebMock).to receive(:after_request) do | _arg, &block |
|
64
|
+
expect(block.parameters.size).to eq(2)
|
51
65
|
end
|
52
66
|
|
53
|
-
# WebMockAdapter.new
|
54
|
-
Pacto.configuration.provider # this way the rpec after block doesn't create a second instance
|
67
|
+
Pacto.configuration.adapter # (rather than WebMockAdapter.new, to prevent rpec after block from creating a second instance
|
55
68
|
end
|
56
69
|
end
|
57
70
|
|
58
71
|
describe '#process_hooks' do
|
59
72
|
let(:request_signature) { double('request_signature') }
|
60
73
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
it 'calls the registered hook' do
|
66
|
-
Pacto.configuration.hook.should_receive(:process)
|
67
|
-
.with(anything, request_signature, response)
|
68
|
-
built_in.process_hooks request_signature, response
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'calls generate when generate is enabled' do
|
72
|
-
Pacto.generate!
|
73
|
-
WebMockHelper.should_receive(:generate).with(request_signature, response)
|
74
|
-
built_in.process_hooks request_signature, response
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'calls validate when validate mode is enabled' do
|
78
|
-
Pacto.validate!
|
79
|
-
WebMockHelper.should_receive(:validate).with(request_signature, response)
|
80
|
-
built_in.process_hooks request_signature, response
|
74
|
+
it 'calls the middleware for processing' do
|
75
|
+
expect(middleware).to receive(:process).with(a_kind_of(Pacto::PactoRequest), a_kind_of(Pacto::PactoResponse))
|
76
|
+
adapter.process_hooks request_signature, response
|
81
77
|
end
|
82
78
|
end
|
83
79
|
|
84
80
|
describe '#stub_request!' do
|
85
81
|
before(:each) do
|
86
|
-
WebMock.
|
82
|
+
expect(WebMock).to receive(:stub_request) do | _method, url |
|
87
83
|
stubbed_request[:path] = url
|
88
84
|
stubbed_request
|
89
85
|
end
|
@@ -91,112 +87,66 @@ module Pacto
|
|
91
87
|
|
92
88
|
context 'when the response body is an object' do
|
93
89
|
let(:body) do
|
94
|
-
{'message' => 'foo'}
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'stubs the response body with a json representation' do
|
98
|
-
stubbed_request.should_receive(:to_return).with(
|
99
|
-
:status => response.status,
|
100
|
-
:headers => response.headers,
|
101
|
-
:body => response.body.to_json
|
102
|
-
)
|
103
|
-
|
104
|
-
request_pattern.stub(:with)
|
105
|
-
|
106
|
-
built_in.stub_request! request, response
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'when the response body is an array' do
|
110
|
-
let(:body) do
|
111
|
-
[1, 2, 3]
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'stubs the response body with a json representation' do
|
115
|
-
stubbed_request.should_receive(:to_return).with(
|
116
|
-
:status => response.status,
|
117
|
-
:headers => response.headers,
|
118
|
-
:body => response.body.to_json
|
119
|
-
)
|
120
|
-
|
121
|
-
request_pattern.stub(:with)
|
122
|
-
|
123
|
-
built_in.stub_request! request, response
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context 'when the response body is not an object or an array' do
|
128
|
-
let(:body) { nil }
|
129
|
-
|
130
|
-
it 'stubs the response body with the original body' do
|
131
|
-
stubbed_request.should_receive(:to_return).with(
|
132
|
-
:status => response.status,
|
133
|
-
:headers => response.headers,
|
134
|
-
:body => response.body
|
135
|
-
)
|
136
|
-
|
137
|
-
request_pattern.stub(:with)
|
138
|
-
|
139
|
-
built_in.stub_request! request, response
|
140
|
-
end
|
90
|
+
{ 'message' => 'foo' }
|
141
91
|
end
|
142
92
|
|
143
93
|
context 'a GET request' do
|
144
|
-
let(:
|
94
|
+
let(:http_method) { :get }
|
145
95
|
|
146
96
|
it 'uses WebMock to stub the request' do
|
147
|
-
request_pattern.
|
148
|
-
with(:
|
97
|
+
expect(request_pattern).to receive(:with).
|
98
|
+
with(headers: request.headers, query: request.params).
|
149
99
|
and_return(stubbed_request)
|
150
|
-
|
100
|
+
adapter.stub_request! contract
|
151
101
|
end
|
152
102
|
end
|
153
103
|
|
154
104
|
context 'a POST request' do
|
155
|
-
let(:
|
105
|
+
let(:http_method) { :post }
|
156
106
|
|
157
107
|
it 'uses WebMock to stub the request' do
|
158
|
-
request_pattern.
|
159
|
-
with(:
|
108
|
+
expect(request_pattern).to receive(:with).
|
109
|
+
with(headers: request.headers, body: request.params).
|
160
110
|
and_return(stubbed_request)
|
161
|
-
|
111
|
+
adapter.stub_request! contract
|
162
112
|
end
|
163
113
|
end
|
164
114
|
|
165
115
|
context 'a request with no headers' do
|
166
116
|
let(:request) do
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
117
|
+
Fabricate(:request_clause,
|
118
|
+
host: 'http://localhost',
|
119
|
+
http_method: :get,
|
120
|
+
path: '/hello_world',
|
121
|
+
headers: {},
|
122
|
+
params: { 'foo' => 'bar' }
|
173
123
|
)
|
174
124
|
end
|
175
125
|
|
176
126
|
it 'uses WebMock to stub the request' do
|
177
|
-
request_pattern.
|
178
|
-
with(:
|
127
|
+
expect(request_pattern).to receive(:with).
|
128
|
+
with(query: request.params).
|
179
129
|
and_return(stubbed_request)
|
180
|
-
|
130
|
+
adapter.stub_request! contract
|
181
131
|
end
|
182
132
|
end
|
183
133
|
|
184
134
|
context 'a request with no params' do
|
185
135
|
let(:request) do
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
136
|
+
Fabricate(:request_clause,
|
137
|
+
host: 'http://localhost',
|
138
|
+
http_method: :get,
|
139
|
+
path: '/hello_world',
|
140
|
+
headers: {},
|
141
|
+
params: {}
|
192
142
|
)
|
193
143
|
end
|
194
144
|
|
195
145
|
it 'uses WebMock to stub the request' do
|
196
|
-
request_pattern.
|
146
|
+
expect(request_pattern).to receive(:with).
|
197
147
|
with({}).
|
198
148
|
and_return(stubbed_request)
|
199
|
-
|
149
|
+
adapter.stub_request! contract
|
200
150
|
end
|
201
151
|
end
|
202
152
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Generator
|
4
|
+
describe SwaggerContractFactory do
|
5
|
+
let(:swagger_file) { 'spec/fixtures/swagger/petstore.yaml' }
|
6
|
+
let(:expected_schema) do
|
7
|
+
{
|
8
|
+
'type' => 'array',
|
9
|
+
'items' => {
|
10
|
+
'required' => %w(id name),
|
11
|
+
'properties' => {
|
12
|
+
'id' => { 'type' => 'integer', 'format' => 'int64' },
|
13
|
+
'name' => { 'type' => 'string' },
|
14
|
+
'tag' => { 'type' => 'string' }
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
describe '#load_hints' do
|
20
|
+
it 'loads hints from Swagger' do
|
21
|
+
hints = subject.load_hints(swagger_file)
|
22
|
+
expect(hints.size).to eq(3) # number of API operations
|
23
|
+
hints.each do | hint |
|
24
|
+
expect(hint).to be_a_kind_of(Pacto::Generator::Hint)
|
25
|
+
expect(hint.host).to eq('petstore.swagger.wordnik.com')
|
26
|
+
expect([:get, :post]).to include(hint.http_method)
|
27
|
+
expect(hint.path).to match(/\/pets/)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#build_from_file' do
|
33
|
+
it 'loads Contracts from Swagger' do
|
34
|
+
contracts = subject.build_from_file(swagger_file)
|
35
|
+
expect(contracts.size).to eq(3) # number of API operations
|
36
|
+
contracts.each do | contract |
|
37
|
+
expect(contract).to be_a_kind_of(Pacto::Contract)
|
38
|
+
|
39
|
+
request_clause = contract.request
|
40
|
+
expect(request_clause.host).to eq('petstore.swagger.wordnik.com')
|
41
|
+
expect([:get, :post]).to include(request_clause.http_method)
|
42
|
+
expect(request_clause.path).to match(/\/pets/)
|
43
|
+
|
44
|
+
response_clause = contract.response
|
45
|
+
if request_clause.http_method == :get
|
46
|
+
expect(response_clause.status).to eq(200)
|
47
|
+
else
|
48
|
+
expect(response_clause.status).to eq(201)
|
49
|
+
end
|
50
|
+
expect(response_clause.schema).to eq(expected_schema) if response_clause.status == 200
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/spec/unit/pacto/uri_spec.rb
CHANGED
data/tasks/release.rake
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
def github
|
4
|
+
@client ||= Octokit::Client.new :access_token => ENV['GITHUB_TOKEN']
|
5
|
+
end
|
6
|
+
|
7
|
+
def release_tag
|
8
|
+
"v#{Pacto::VERSION}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def release
|
12
|
+
@release ||= github.list_releases('thoughtworks/pacto').find{|r| r.name == release_tag }
|
13
|
+
end
|
14
|
+
|
15
|
+
def changelog
|
16
|
+
changelog = File.read('changelog.md').split("\n\n\n", 2).first
|
17
|
+
confirm 'Does the CHANGELOG look correct? ', changelog
|
18
|
+
end
|
19
|
+
|
20
|
+
def confirm(question, data)
|
21
|
+
puts 'Please confirm...'
|
22
|
+
puts data
|
23
|
+
print question
|
24
|
+
abort 'Aborted' unless $stdin.gets.strip == 'y'
|
25
|
+
puts 'Confirmed'
|
26
|
+
data
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Tags and pushes the gem'
|
30
|
+
task :release_gem do
|
31
|
+
sh 'git', 'tag', '-m', changelog, "v#{Pacto::VERSION}"
|
32
|
+
sh 'git push origin master'
|
33
|
+
sh "git push origin v#{Pacto::VERSION}"
|
34
|
+
sh 'ls pkg/*.gem | xargs -n 1 gem push'
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Releases to RubyGems and GitHub'
|
38
|
+
task :release => [:build, :release_gem, :documentation, :package, :create_release, :upload_docs]
|
39
|
+
|
40
|
+
desc 'Preview the changelog'
|
41
|
+
task :changelog do
|
42
|
+
changelog
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'Create a release on GitHub'
|
46
|
+
task :create_release do
|
47
|
+
github.create_release 'thoughtworks/pacto', release_tag, {:name => release_tag, :body => changelog}
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'Upload docs to the GitHub release'
|
51
|
+
task :upload_docs do
|
52
|
+
Dir['pkg/pacto_docs*'].each do |file|
|
53
|
+
next if File.directory? file
|
54
|
+
puts "Uploading #{file}"
|
55
|
+
github.upload_asset release.url, file
|
56
|
+
end
|
57
|
+
end
|