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
@@ -1,31 +1,30 @@
1
- describe 'Pacto' do
2
- let(:contract_path) { 'spec/integration/data/simple_contract.json' }
3
- let(:strict_contract_path) { 'spec/integration/data/strict_contract.json' }
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 validation' do
10
- before :all do
11
- @server = Pacto::Server::Dummy.new 8000, '/hello', '{"message": "Hello World!"}'
12
- @server.start
13
- end
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
- contract = Pacto.load_contracts(contract_path, 'http://localhost:8000')
21
- expect(contract.validate_all.flatten).to eq([])
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 = Pacto.load_contracts(contract_path, 'http://dummyprovider.com')
28
- contracts.stub_all
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
- Pacto.configure do |c|
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 = Pacto.load_contracts 'spec/integration/data/', 'http://dummyprovider.com'
43
- contracts.stub_all(:device_id => 42)
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 have(2).items
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/integration/data/simple_contract.json' }
5
- let(:strict_contract_path) { 'spec/integration/data/strict_contract.json' }
5
+ let(:contract_path) { 'spec/fixtures/contracts/simple_contract.json' }
6
+ let(:strict_contract_path) { 'spec/fixtures/contracts/strict_contract.json' }
6
7
 
7
- before :all do
8
- WebMock.allow_net_connect!
9
- @server = Pacto::Server::Dummy.new 8000, '/hello', '{"message": "Hello World!"}'
10
- @server.start
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.stub_all(:device_id => 1.5)
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 validations' do
32
+ context 'successful investigations' do
36
33
  let(:contracts) do
37
- Pacto.load_contracts 'spec/integration/data/', 'http://dummyprovider.com'
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.stub_all(:device_id => 42)
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 have_failed_validations
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(:headers => {'Accept' => 'application/json'})
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 validation problems, but none were found/) { expect(Pacto).to have_failed_validations }
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(:headers => {'Accept' => 'text/plain'}) }
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 validation problems' do
88
+ it 'displays Contract investigation problems' do
92
89
  play_bad_response
93
- expect_to_raise(/validation errors were found:/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict') }
94
- expect_to_raise(/but the following issues were found:/) { expect(Pacto).to_not have_failed_validations }
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/integration/data/templating_contract.json' }
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.stub_all(:key => key, :auth_token => auth_token)
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
- 'Accept' => 'application/json',
16
- 'Custom-Auth-Token' => "#{auth_token}",
17
- 'X-Message' => "#{key}"
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 |contracts, req, res|
32
+ c.register_hook do |_contracts, _req, res|
32
33
  res
33
34
  end
34
35
  end
@@ -0,0 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require_relative 'dummy_server/dummy'
3
+ require_relative 'dummy_server/playback_servlet'
4
+ require_relative 'dummy_server/jruby_workaround_helper'
@@ -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 Server
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.exists?('/dev/null') ? '/dev/null' : Tempfile.new('log') # So tests run on Windows
26
+ log_file = File.exist?('/dev/null') ? '/dev/null' : Tempfile.new('log') # So tests run on Windows
26
27
  params = {
27
- :Port => port,
28
- :AccessLog => [],
29
- :Logger => WEBrick::Log.new(log_file, 7)
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 Server
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(request, response) # rubocop:disable MethodName
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
@@ -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/server'
5
+ require 'pacto/test_helper'
6
+ require 'pacto/dummy_server'
7
+ require 'fabrication'
5
8
  require 'stringio'
6
9
  require 'rspec'
7
- require 'should_not/rspec'
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.before(:each) do
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