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
@@ -1,31 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
let(:
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
describe Pacto do
|
3
|
+
let(:contract_path) { 'spec/fixtures/contracts/simple_contract.json' }
|
4
|
+
let(:strict_contract_path) { 'spec/fixtures/contracts/strict_contract.json' }
|
4
5
|
|
5
6
|
before :all do
|
6
7
|
WebMock.allow_net_connect!
|
7
8
|
end
|
8
9
|
|
9
|
-
context 'Contract
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
after :all do
|
16
|
-
@server.terminate
|
10
|
+
context 'Contract investigation' do
|
11
|
+
around :each do |example|
|
12
|
+
run_pacto do
|
13
|
+
example.run
|
14
|
+
end
|
17
15
|
end
|
18
16
|
|
19
17
|
it 'verifies the contract against a producer' do
|
20
|
-
|
21
|
-
|
18
|
+
# FIXME: Does this really test what it says it does??
|
19
|
+
contract = described_class.load_contracts(contract_path, 'http://localhost:8000')
|
20
|
+
expect(contract.simulate_consumers.map(&:successful?).uniq).to eq([true])
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
24
|
context 'Stubbing a collection of contracts' do
|
26
25
|
it 'generates a server that stubs the contract for consumers' do
|
27
|
-
contracts =
|
28
|
-
contracts.
|
26
|
+
contracts = described_class.load_contracts(contract_path, 'http://dummyprovider.com')
|
27
|
+
contracts.stub_providers
|
29
28
|
|
30
29
|
response = get_json('http://dummyprovider.com/hello')
|
31
30
|
expect(response['message']).to eq 'bar'
|
@@ -34,20 +33,20 @@ describe 'Pacto' do
|
|
34
33
|
|
35
34
|
context 'Journey' do
|
36
35
|
it 'stubs multiple services with a single use' do
|
37
|
-
|
36
|
+
described_class.configure do |c|
|
38
37
|
c.strict_matchers = false
|
39
38
|
c.register_hook Pacto::Hooks::ERBHook.new
|
40
39
|
end
|
41
40
|
|
42
|
-
contracts =
|
43
|
-
contracts.
|
41
|
+
contracts = described_class.load_contracts 'spec/fixtures/contracts/', 'http://dummyprovider.com'
|
42
|
+
contracts.stub_providers(device_id: 42)
|
44
43
|
|
45
44
|
login_response = get_json('http://dummyprovider.com/hello')
|
46
45
|
expect(login_response.keys).to eq ['message']
|
47
46
|
expect(login_response['message']).to be_kind_of(String)
|
48
47
|
|
49
48
|
devices_response = get_json('http://dummyprovider.com/strict')
|
50
|
-
expect(devices_response['devices']).to
|
49
|
+
expect(devices_response['devices'].size).to eq(2)
|
51
50
|
expect(devices_response['devices'][0]).to eq('/dev/42')
|
52
51
|
expect(devices_response['devices'][1]).to eq('/dev/43')
|
53
52
|
end
|
@@ -55,7 +54,7 @@ describe 'Pacto' do
|
|
55
54
|
|
56
55
|
def get_json(url)
|
57
56
|
response = Faraday.get(url) do |req|
|
58
|
-
req.headers = {'Accept' => 'application/json' }
|
57
|
+
req.headers = { 'Accept' => 'application/json' }
|
59
58
|
end
|
60
59
|
MultiJson.load(response.body)
|
61
60
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'pacto/rspec'
|
3
|
+
|
4
|
+
module Pacto
|
5
|
+
describe '#have_investigated' do
|
6
|
+
let(:contract_path) { 'spec/fixtures/contracts/simple_contract.json' }
|
7
|
+
let(:strict_contract_path) { 'spec/fixtures/contracts/strict_contract.json' }
|
8
|
+
|
9
|
+
around :each do |example|
|
10
|
+
run_pacto do
|
11
|
+
example.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def expect_to_raise(message_pattern = nil, &blk)
|
16
|
+
expect { blk.call }.to raise_error(RSpec::Expectations::ExpectationNotMetError, message_pattern)
|
17
|
+
end
|
18
|
+
|
19
|
+
def json_response(url)
|
20
|
+
response = Faraday.get(url) do |req|
|
21
|
+
req.headers = { 'Accept' => 'application/json' }
|
22
|
+
end
|
23
|
+
MultiJson.load(response.body)
|
24
|
+
end
|
25
|
+
|
26
|
+
def play_bad_response
|
27
|
+
contracts.stub_providers(device_id: 1.5)
|
28
|
+
Faraday.get('http://dummyprovider.com/strict') do |req|
|
29
|
+
req.headers = { 'Accept' => 'application/json' }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'successful investigations' do
|
34
|
+
let(:contracts) do
|
35
|
+
Pacto.load_contracts 'spec/fixtures/contracts/', 'http://dummyprovider.com'
|
36
|
+
end
|
37
|
+
|
38
|
+
before(:each) do
|
39
|
+
Pacto.configure do |c|
|
40
|
+
c.strict_matchers = false
|
41
|
+
c.register_hook Pacto::Hooks::ERBHook.new
|
42
|
+
end
|
43
|
+
|
44
|
+
contracts.stub_providers(device_id: 42)
|
45
|
+
Pacto.validate!
|
46
|
+
|
47
|
+
Faraday.get('http://dummyprovider.com/hello') do |req|
|
48
|
+
req.headers = { 'Accept' => 'application/json' }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'performs successful assertions' do
|
53
|
+
# High level assertions
|
54
|
+
expect(Pacto).to_not have_unmatched_requests
|
55
|
+
expect(Pacto).to_not have_failed_investigations
|
56
|
+
|
57
|
+
# Increasingly strict assertions
|
58
|
+
expect(Pacto).to have_investigated('Simple Contract')
|
59
|
+
expect(Pacto).to have_investigated('Simple Contract').with_request(headers: hash_including('Accept' => 'application/json'))
|
60
|
+
expect(Pacto).to have_investigated('Simple Contract').with_request(http_method: :get, url: 'http://dummyprovider.com/hello')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'supports negative assertions' do
|
64
|
+
expect(Pacto).to_not have_investigated('Strict Contract')
|
65
|
+
Faraday.get('http://dummyprovider.com/strict') do |req|
|
66
|
+
req.headers = { 'Accept' => 'application/json' }
|
67
|
+
end
|
68
|
+
expect(Pacto).to have_investigated('Strict Contract')
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'raises useful error messages' do
|
72
|
+
# Expected failures
|
73
|
+
header_matcher = hash_including('Accept' => 'text/plain')
|
74
|
+
matcher_description = Regexp.quote(header_matcher.description)
|
75
|
+
expect_to_raise(/but no requests matched headers #{matcher_description}/) { expect(Pacto).to have_investigated('Simple Contract').with_request(headers: header_matcher) }
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'displays Contract investigation problems' do
|
79
|
+
play_bad_response
|
80
|
+
expect_to_raise(/investigation errors were found:/) { expect(Pacto).to have_investigated('Strict Contract') }
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'displays the Contract file' do
|
84
|
+
play_bad_response
|
85
|
+
schema_file_uri = Addressable::URI.convert_path(File.absolute_path strict_contract_path).to_s
|
86
|
+
expect_to_raise(/in schema #{schema_file_uri}/) { expect(Pacto).to have_investigated('Strict Contract') }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -1,17 +1,14 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'pacto/rspec'
|
2
3
|
|
3
4
|
describe 'pacto/rspec' do
|
4
|
-
let(:contract_path) { 'spec/
|
5
|
-
let(:strict_contract_path) { 'spec/
|
5
|
+
let(:contract_path) { 'spec/fixtures/contracts/simple_contract.json' }
|
6
|
+
let(:strict_contract_path) { 'spec/fixtures/contracts/strict_contract.json' }
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
after :all do
|
14
|
-
@server.terminate
|
8
|
+
around :each do |example|
|
9
|
+
run_pacto do
|
10
|
+
example.run
|
11
|
+
end
|
15
12
|
end
|
16
13
|
|
17
14
|
def expect_to_raise(message_pattern = nil, &blk)
|
@@ -20,21 +17,21 @@ describe 'pacto/rspec' do
|
|
20
17
|
|
21
18
|
def json_response(url)
|
22
19
|
response = Faraday.get(url) do |req|
|
23
|
-
req.headers = {'Accept' => 'application/json' }
|
20
|
+
req.headers = { 'Accept' => 'application/json' }
|
24
21
|
end
|
25
22
|
MultiJson.load(response.body)
|
26
23
|
end
|
27
24
|
|
28
25
|
def play_bad_response
|
29
|
-
contracts.
|
26
|
+
contracts.stub_providers(device_id: 1.5)
|
30
27
|
Faraday.get('http://dummyprovider.com/strict') do |req|
|
31
|
-
req.headers = {'Accept' => 'application/json' }
|
28
|
+
req.headers = { 'Accept' => 'application/json' }
|
32
29
|
end
|
33
30
|
end
|
34
31
|
|
35
|
-
context 'successful
|
32
|
+
context 'successful investigations' do
|
36
33
|
let(:contracts) do
|
37
|
-
Pacto.load_contracts 'spec/
|
34
|
+
Pacto.load_contracts 'spec/fixtures/contracts/', 'http://dummyprovider.com'
|
38
35
|
end
|
39
36
|
|
40
37
|
before(:each) do
|
@@ -43,29 +40,29 @@ describe 'pacto/rspec' do
|
|
43
40
|
c.register_hook Pacto::Hooks::ERBHook.new
|
44
41
|
end
|
45
42
|
|
46
|
-
contracts.
|
43
|
+
contracts.stub_providers(device_id: 42)
|
47
44
|
Pacto.validate!
|
48
45
|
|
49
46
|
Faraday.get('http://dummyprovider.com/hello') do |req|
|
50
|
-
req.headers = {'Accept' => 'application/json' }
|
47
|
+
req.headers = { 'Accept' => 'application/json' }
|
51
48
|
end
|
52
49
|
end
|
53
50
|
|
54
51
|
it 'performs successful assertions' do
|
55
52
|
# High level assertions
|
56
53
|
expect(Pacto).to_not have_unmatched_requests
|
57
|
-
expect(Pacto).to_not
|
54
|
+
expect(Pacto).to_not have_failed_investigations
|
58
55
|
|
59
56
|
# Increasingly strict assertions
|
60
57
|
expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello')
|
61
|
-
expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with(:
|
58
|
+
expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with(headers: { 'Accept' => 'application/json' })
|
62
59
|
expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').against_contract(/simple_contract.json/)
|
63
60
|
end
|
64
61
|
|
65
62
|
it 'supports negative assertions' do
|
66
63
|
expect(Pacto).to_not have_validated(:get, 'http://dummyprovider.com/strict')
|
67
64
|
Faraday.get('http://dummyprovider.com/strict') do |req|
|
68
|
-
req.headers = {'Accept' => 'application/json' }
|
65
|
+
req.headers = { 'Accept' => 'application/json' }
|
69
66
|
end
|
70
67
|
expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict')
|
71
68
|
end
|
@@ -73,14 +70,14 @@ describe 'pacto/rspec' do
|
|
73
70
|
it 'raises useful error messages' do
|
74
71
|
# High level error messages
|
75
72
|
expect_to_raise(/Expected Pacto to have not matched all requests to a Contract, but all requests were matched/) { expect(Pacto).to have_unmatched_requests }
|
76
|
-
expect_to_raise(/Expected Pacto to have found
|
73
|
+
expect_to_raise(/Expected Pacto to have found investigation problems, but none were found/) { expect(Pacto).to have_failed_investigations }
|
77
74
|
|
78
75
|
unmatched_url = 'http://localhost:8000/404'
|
79
76
|
Faraday.get unmatched_url
|
80
77
|
expect_to_raise(/the following requests were not matched.*#{Regexp.quote unmatched_url}/m) { expect(Pacto).to_not have_unmatched_requests }
|
81
78
|
|
82
79
|
# Expected failures
|
83
|
-
expect_to_raise(/no matching request was received/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with(:
|
80
|
+
expect_to_raise(/no matching request was received/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with(headers: { 'Accept' => 'text/plain' }) }
|
84
81
|
# No support for with accepting a block
|
85
82
|
# expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with { |req| req.body == "abc" }
|
86
83
|
expect_to_raise(/but it was validated against/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').against_contract(/strict_contract.json/) }
|
@@ -88,10 +85,10 @@ describe 'pacto/rspec' do
|
|
88
85
|
expect_to_raise(/but no matching request was received/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict') }
|
89
86
|
end
|
90
87
|
|
91
|
-
it 'displays Contract
|
88
|
+
it 'displays Contract investigation problems' do
|
92
89
|
play_bad_response
|
93
|
-
expect_to_raise(/
|
94
|
-
expect_to_raise(/but the following issues were found:/) { expect(Pacto).to_not
|
90
|
+
expect_to_raise(/investigation errors were found:/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict') }
|
91
|
+
expect_to_raise(/but the following issues were found:/) { expect(Pacto).to_not have_failed_investigations }
|
95
92
|
end
|
96
93
|
|
97
94
|
it 'displays the Contract file' do
|
@@ -1,20 +1,21 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'securerandom'
|
2
3
|
|
3
4
|
describe 'Templating' do
|
4
|
-
let(:contract_path) { 'spec/
|
5
|
+
let(:contract_path) { 'spec/fixtures/contracts/templating_contract.json' }
|
5
6
|
let(:contracts) { Pacto.load_contracts(contract_path, 'http://dummyprovider.com') }
|
6
7
|
|
7
8
|
let(:key) { SecureRandom.hex }
|
8
9
|
let(:auth_token) { SecureRandom.hex }
|
9
10
|
|
10
11
|
let :response do
|
11
|
-
contracts.
|
12
|
+
contracts.stub_providers(key: key, auth_token: auth_token)
|
12
13
|
|
13
14
|
raw_response = Faraday.get('http://dummyprovider.com/echo') do |req|
|
14
15
|
req.headers = {
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
'Accept' => 'application/json',
|
17
|
+
'Custom-Auth-Token' => "#{auth_token}",
|
18
|
+
'X-Message' => "#{key}"
|
18
19
|
}
|
19
20
|
end
|
20
21
|
MultiJson.load(raw_response.body)
|
@@ -28,7 +29,7 @@ describe 'Templating' do
|
|
28
29
|
it 'does not proccess erb tag' do
|
29
30
|
Pacto.configure do |c|
|
30
31
|
c.strict_matchers = false
|
31
|
-
c.register_hook do |
|
32
|
+
c.register_hook do |_contracts, _req, res|
|
32
33
|
res
|
33
34
|
end
|
34
35
|
end
|
@@ -1,9 +1,10 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'webrick'
|
2
3
|
require 'forwardable'
|
3
4
|
require 'tempfile'
|
4
5
|
|
5
6
|
module Pacto
|
6
|
-
module
|
7
|
+
module DummyServer
|
7
8
|
class Servlet < WEBrick::HTTPServlet::AbstractServlet
|
8
9
|
extend Forwardable
|
9
10
|
|
@@ -12,7 +13,7 @@ module Pacto
|
|
12
13
|
|
13
14
|
@doer = PlaybackServlet.new(
|
14
15
|
status: 200,
|
15
|
-
headers: {'Content-Type' => 'application/json', 'Vary' => 'Accept'},
|
16
|
+
headers: { 'Content-Type' => 'application/json', 'Vary' => 'Accept' },
|
16
17
|
body: json
|
17
18
|
)
|
18
19
|
end
|
@@ -22,11 +23,11 @@ module Pacto
|
|
22
23
|
|
23
24
|
class Dummy
|
24
25
|
def initialize(port, path, response)
|
25
|
-
log_file = File.
|
26
|
+
log_file = File.exist?('/dev/null') ? '/dev/null' : Tempfile.new('log') # So tests run on Windows
|
26
27
|
params = {
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
28
|
+
Port: port,
|
29
|
+
AccessLog: [],
|
30
|
+
Logger: WEBrick::Log.new(log_file, 7)
|
30
31
|
}
|
31
32
|
@server = WEBrick::HTTPServer.new params
|
32
33
|
@server.mount path, Servlet, response
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module DummyServer
|
4
|
+
module JRubyWorkaroundHelper
|
5
|
+
include Pacto::TestHelper
|
6
|
+
|
7
|
+
def run_pacto
|
8
|
+
WebMock.allow_net_connect!
|
9
|
+
# There are issues with EventMachine on JRuby, so it can't currently us with_pacto
|
10
|
+
if RUBY_PLATFORM == 'java'
|
11
|
+
@server = Pacto::DummyServer::Dummy.new 8000, '/hello', '{"message": "Hello World!"}'
|
12
|
+
@server.start
|
13
|
+
yield
|
14
|
+
@server.terminate
|
15
|
+
else
|
16
|
+
with_pacto(port: 8000, strip_port: true) do
|
17
|
+
yield
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
module Pacto
|
2
|
-
module
|
3
|
+
module DummyServer
|
3
4
|
class PlaybackServlet
|
4
5
|
attr_reader :status, :headers, :body
|
5
6
|
|
@@ -9,7 +10,7 @@ module Pacto
|
|
9
10
|
@body = attributes.fetch(:body, nil)
|
10
11
|
end
|
11
12
|
|
12
|
-
def do_GET(
|
13
|
+
def do_GET(_request, response) # rubocop:disable MethodName
|
13
14
|
response.status = status
|
14
15
|
headers.each do |key, value|
|
15
16
|
response[key] = value
|
data/spec/spec_helper.rb
CHANGED
@@ -1,20 +1,29 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'coveralls_helper'
|
2
3
|
require 'webmock/rspec'
|
3
4
|
require 'pacto'
|
4
|
-
require 'pacto/
|
5
|
+
require 'pacto/test_helper'
|
6
|
+
require 'pacto/dummy_server'
|
7
|
+
require 'fabrication'
|
5
8
|
require 'stringio'
|
6
9
|
require 'rspec'
|
7
|
-
|
10
|
+
|
11
|
+
# Pre-load shared examples
|
12
|
+
require_relative 'unit/pacto/actor_spec.rb'
|
8
13
|
|
9
14
|
RSpec.configure do |config|
|
15
|
+
config.raise_errors_for_deprecations!
|
16
|
+
config.include Pacto::TestHelper
|
17
|
+
config.include Pacto::DummyServer::JRubyWorkaroundHelper
|
10
18
|
config.expect_with :rspec do |c|
|
11
19
|
c.syntax = :expect
|
12
20
|
end
|
13
|
-
config.
|
14
|
-
provider = Pacto.configuration.provider
|
15
|
-
unless provider.respond_to? :reset!
|
16
|
-
provider.stub(:reset!)
|
17
|
-
end
|
21
|
+
config.after(:each) do
|
18
22
|
Pacto.clear!
|
19
23
|
end
|
20
24
|
end
|
25
|
+
|
26
|
+
def sample_contract
|
27
|
+
# Memoized for test speed
|
28
|
+
@sample_contract ||= Fabricate(:contract)
|
29
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Pacto
|
3
|
+
module Actors
|
4
|
+
describe FromExamples do
|
5
|
+
|
6
|
+
let(:fallback) { double('fallback') }
|
7
|
+
subject(:generator) { described_class.new fallback }
|
8
|
+
|
9
|
+
context 'a contract without examples' do
|
10
|
+
let(:contract) { Fabricate(:contract) }
|
11
|
+
|
12
|
+
it_behaves_like 'an actor' do
|
13
|
+
before(:each) do
|
14
|
+
allow(fallback).to receive(:build_request).with(contract, {}).and_return(Fabricate(:pacto_request))
|
15
|
+
allow(fallback).to receive(:build_response).with(contract, {}).and_return(Fabricate(:pacto_response))
|
16
|
+
end
|
17
|
+
let(:contract) { Fabricate(:contract) }
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'uses the fallback actor' do
|
21
|
+
expect(fallback).to receive(:build_request).with(contract, {})
|
22
|
+
expect(fallback).to receive(:build_response).with(contract, {})
|
23
|
+
generator.build_request contract
|
24
|
+
generator.build_response contract
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'a contract with examples' do
|
29
|
+
let(:contract) { Fabricate(:contract, example_count: 3) }
|
30
|
+
let(:request) { generator.build_request contract }
|
31
|
+
let(:response) { generator.build_response contract }
|
32
|
+
|
33
|
+
it_behaves_like 'an actor' do
|
34
|
+
let(:contract) { Fabricate(:contract, example_count: 3) }
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'no example specified' do
|
38
|
+
it 'uses the first example' do
|
39
|
+
expect(request.body).to eq(contract.examples.values.first.request.body)
|
40
|
+
expect(response.body).to eq(contract.examples.values.first.response.body)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'example specified' do
|
45
|
+
let(:name) { '1' }
|
46
|
+
subject(:generator) { described_class.new fallback, Pacto::Actors::NamedExampleSelector }
|
47
|
+
let(:request) { generator.build_request contract, example_name: name }
|
48
|
+
let(:response) { generator.build_response contract, example_name: name }
|
49
|
+
|
50
|
+
it 'uses the named example' do
|
51
|
+
expect(request.body).to eq(contract.examples[name].request.body)
|
52
|
+
expect(response.body).to eq(contract.examples[name].response.body)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with randomized behavior' do
|
57
|
+
subject(:generator) { described_class.new fallback, Pacto::Actors::RandomExampleSelector }
|
58
|
+
it 'returns a randomly selected example' do
|
59
|
+
examples_requests = contract.examples.values.map(&:request)
|
60
|
+
examples_responses = contract.examples.values.map(&:response)
|
61
|
+
request_bodies = examples_requests.map(&:body)
|
62
|
+
response_bodies = examples_responses.map(&:body)
|
63
|
+
expect(request_bodies).to include request.body
|
64
|
+
expect(response_bodies).to include response.body
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|