pacto 0.3.0.pre → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.rubocop-todo.yml +0 -27
  4. data/.rubocop.yml +9 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +4 -5
  8. data/CONTRIBUTING.md +112 -0
  9. data/Gemfile +5 -0
  10. data/Guardfile +18 -13
  11. data/README.md +157 -101
  12. data/Rakefile +3 -3
  13. data/features/configuration/strict_matchers.feature +97 -0
  14. data/features/evolve/README.md +11 -0
  15. data/features/evolve/existing_services.feature +82 -0
  16. data/features/generate/README.md +5 -0
  17. data/features/generate/generation.feature +28 -0
  18. data/features/steps/pacto_steps.rb +75 -0
  19. data/features/stub/README.md +2 -0
  20. data/features/stub/templates.feature +46 -0
  21. data/features/support/env.rb +11 -5
  22. data/features/validate/README.md +1 -0
  23. data/features/validate/body_only.feature +85 -0
  24. data/features/{journeys/validation.feature → validate/meta_validation.feature} +41 -24
  25. data/features/validate/validation.feature +36 -0
  26. data/lib/pacto.rb +61 -33
  27. data/lib/pacto/contract.rb +18 -15
  28. data/lib/pacto/contract_factory.rb +14 -11
  29. data/lib/pacto/contract_files.rb +17 -0
  30. data/lib/pacto/contract_list.rb +17 -0
  31. data/lib/pacto/contract_validator.rb +29 -0
  32. data/lib/pacto/core/configuration.rb +19 -17
  33. data/lib/pacto/core/contract_registry.rb +43 -0
  34. data/lib/pacto/core/{callback.rb → hook.rb} +3 -3
  35. data/lib/pacto/core/modes.rb +33 -0
  36. data/lib/pacto/core/validation_registry.rb +45 -0
  37. data/lib/pacto/erb_processor.rb +0 -1
  38. data/lib/pacto/extensions.rb +18 -4
  39. data/lib/pacto/generator.rb +34 -49
  40. data/lib/pacto/generator/filters.rb +41 -0
  41. data/lib/pacto/hooks/erb_hook.rb +4 -3
  42. data/lib/pacto/logger.rb +4 -2
  43. data/lib/pacto/meta_schema.rb +4 -2
  44. data/lib/pacto/rake_task.rb +28 -25
  45. data/lib/pacto/request_clause.rb +43 -0
  46. data/lib/pacto/request_pattern.rb +8 -0
  47. data/lib/pacto/response_clause.rb +15 -0
  48. data/lib/pacto/rspec.rb +102 -0
  49. data/lib/pacto/stubs/uri_pattern.rb +23 -0
  50. data/lib/pacto/stubs/webmock_adapter.rb +69 -0
  51. data/lib/pacto/stubs/webmock_helper.rb +71 -0
  52. data/lib/pacto/ui.rb +7 -0
  53. data/lib/pacto/uri.rb +9 -0
  54. data/lib/pacto/validation.rb +57 -0
  55. data/lib/pacto/validators/body_validator.rb +41 -0
  56. data/lib/pacto/validators/request_body_validator.rb +23 -0
  57. data/lib/pacto/validators/response_body_validator.rb +23 -0
  58. data/lib/pacto/validators/response_header_validator.rb +49 -0
  59. data/lib/pacto/validators/response_status_validator.rb +24 -0
  60. data/lib/pacto/version.rb +1 -1
  61. data/pacto.gemspec +33 -29
  62. data/resources/contract_schema.json +8 -176
  63. data/resources/draft-03.json +174 -0
  64. data/spec/integration/data/strict_contract.json +2 -2
  65. data/spec/integration/e2e_spec.rb +22 -31
  66. data/spec/integration/rspec_spec.rb +94 -0
  67. data/spec/integration/templating_spec.rb +9 -12
  68. data/{lib → spec}/pacto/server.rb +0 -0
  69. data/{lib → spec}/pacto/server/dummy.rb +11 -8
  70. data/{lib → spec}/pacto/server/playback_servlet.rb +1 -1
  71. data/spec/spec_helper.rb +2 -0
  72. data/spec/unit/hooks/erb_hook_spec.rb +15 -15
  73. data/spec/unit/pacto/configuration_spec.rb +2 -10
  74. data/spec/unit/pacto/contract_factory_spec.rb +16 -13
  75. data/spec/unit/pacto/contract_files_spec.rb +42 -0
  76. data/spec/unit/pacto/contract_list_spec.rb +35 -0
  77. data/spec/unit/pacto/contract_spec.rb +43 -44
  78. data/spec/unit/pacto/contract_validator_spec.rb +85 -0
  79. data/spec/unit/pacto/core/configuration_spec.rb +4 -11
  80. data/spec/unit/pacto/core/contract_registry_spec.rb +119 -0
  81. data/spec/unit/pacto/core/modes_spec.rb +18 -0
  82. data/spec/unit/pacto/core/validation_registry_spec.rb +76 -0
  83. data/spec/unit/pacto/core/validation_spec.rb +60 -0
  84. data/spec/unit/pacto/extensions_spec.rb +14 -23
  85. data/spec/unit/pacto/generator/filters_spec.rb +99 -0
  86. data/spec/unit/pacto/generator_spec.rb +34 -73
  87. data/spec/unit/pacto/meta_schema_spec.rb +46 -6
  88. data/spec/unit/pacto/pacto_spec.rb +17 -15
  89. data/spec/unit/pacto/{request_spec.rb → request_clause_spec.rb} +32 -44
  90. data/spec/unit/pacto/request_pattern_spec.rb +22 -0
  91. data/spec/unit/pacto/response_clause_spec.rb +54 -0
  92. data/spec/unit/pacto/stubs/uri_pattern_spec.rb +28 -0
  93. data/spec/unit/pacto/stubs/webmock_adapter_spec.rb +205 -0
  94. data/spec/unit/pacto/stubs/webmock_helper_spec.rb +20 -0
  95. data/spec/unit/pacto/uri_spec.rb +20 -0
  96. data/spec/unit/pacto/validators/body_validator_spec.rb +105 -0
  97. data/spec/unit/pacto/validators/response_header_validator_spec.rb +94 -0
  98. data/spec/unit/pacto/validators/response_status_validator_spec.rb +20 -0
  99. metadata +230 -146
  100. data/features/generation/generation.feature +0 -25
  101. data/lib/pacto/core/contract_repository.rb +0 -44
  102. data/lib/pacto/hash_merge_processor.rb +0 -14
  103. data/lib/pacto/request.rb +0 -57
  104. data/lib/pacto/response.rb +0 -63
  105. data/lib/pacto/response_adapter.rb +0 -24
  106. data/lib/pacto/stubs/built_in.rb +0 -57
  107. data/spec/unit/pacto/core/contract_repository_spec.rb +0 -133
  108. data/spec/unit/pacto/hash_merge_processor_spec.rb +0 -20
  109. data/spec/unit/pacto/response_adapter_spec.rb +0 -25
  110. data/spec/unit/pacto/response_spec.rb +0 -201
  111. data/spec/unit/pacto/stubs/built_in_spec.rb +0 -168
@@ -21,8 +21,8 @@
21
21
  "items": {
22
22
  "type": "string",
23
23
  "required": true,
24
- "default": "/dev/<%= device_id %>",
25
- "pattern": "^/dev/[^/]+(/[^/]+)*$"
24
+ "default": "/dev/<%= values[:device_id].tap do values[:device_id] = values[:device_id] + 1 end %>",
25
+ "pattern": "^/dev/[\\d]+$"
26
26
  },
27
27
  "required": true,
28
28
  "uniqueItems": true
@@ -17,23 +17,18 @@ describe 'Pacto' do
17
17
  end
18
18
 
19
19
  it 'verifies the contract against a producer' do
20
- contract = Pacto.build_from_file(contract_path, 'http://localhost:8000')
21
- expect(contract.validate).to be_empty
20
+ contract = Pacto.load_contracts(contract_path, 'http://localhost:8000')
21
+ expect(contract.validate_all.flatten).to eq([])
22
22
  end
23
23
  end
24
24
 
25
- context 'Stub generation' do
26
- it 'generates a stub to be used by a consumer' do
27
- contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com')
28
- Pacto.register_contract(contract, 'my_tag')
29
- Pacto.use('my_tag')
30
- expect(response.keys).to eq ['message']
31
- expect(response['message']).to be_kind_of(String)
32
- end
25
+ context 'Stubbing a collection of contracts' do
26
+ 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
33
29
 
34
- let :response do
35
- raw_response = HTTParty.get('http://dummyprovider.com/hello', headers: {'Accept' => 'application/json' })
36
- MultiJson.load(raw_response.body)
30
+ response = get_json('http://dummyprovider.com/hello')
31
+ expect(response['message']).to eq 'bar'
37
32
  end
38
33
  end
39
34
 
@@ -41,31 +36,27 @@ describe 'Pacto' do
41
36
  it 'stubs multiple services with a single use' do
42
37
  Pacto.configure do |c|
43
38
  c.strict_matchers = false
44
- c.postprocessor = Pacto::ERBProcessor.new
45
- c.preprocessor = nil
46
- c.register_callback Pacto::Hooks::ERBHook.new
47
- end
48
-
49
- # Preprocessor must be off before building!
50
- login_contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com')
51
- contract = Pacto.build_from_file(strict_contract_path, 'http://dummyprovider.com')
52
- Pacto.configure do |c|
53
- c.register_contract login_contract, :default
54
- c.register_contract contract, :devices
39
+ c.register_hook Pacto::Hooks::ERBHook.new
55
40
  end
56
41
 
57
- Pacto.use(:devices, {:device_id => 42})
42
+ contracts = Pacto.load_contracts 'spec/integration/data/', 'http://dummyprovider.com'
43
+ contracts.stub_all(:device_id => 42)
58
44
 
59
- raw_response = HTTParty.get('http://dummyprovider.com/hello', headers: {'Accept' => 'application/json' })
60
- login_response = MultiJson.load(raw_response.body)
45
+ login_response = get_json('http://dummyprovider.com/hello')
61
46
  expect(login_response.keys).to eq ['message']
62
47
  expect(login_response['message']).to be_kind_of(String)
63
48
 
64
- devices_response = HTTParty.get('http://dummyprovider.com/strict', headers: {'Accept' => 'application/json' })
65
- devices_response = MultiJson.load(devices_response.body)
49
+ devices_response = get_json('http://dummyprovider.com/strict')
66
50
  expect(devices_response['devices']).to have(2).items
67
- expect(devices_response['devices'][0]).to eq '/dev/42'
68
- # devices_response['devices'][1].should == '/dev/43'
51
+ expect(devices_response['devices'][0]).to eq('/dev/42')
52
+ expect(devices_response['devices'][1]).to eq('/dev/43')
53
+ end
54
+ end
55
+
56
+ def get_json(url)
57
+ response = Faraday.get(url) do |req|
58
+ req.headers = {'Accept' => 'application/json' }
69
59
  end
60
+ MultiJson.load(response.body)
70
61
  end
71
62
  end
@@ -0,0 +1,94 @@
1
+ require 'pacto/rspec'
2
+
3
+ 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' }
6
+
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
15
+ end
16
+
17
+ def expect_to_raise(message_pattern = nil, &blk)
18
+ expect { blk.call }.to raise_error(RSpec::Expectations::ExpectationNotMetError, message_pattern)
19
+ end
20
+
21
+ def json_response(url)
22
+ response = Faraday.get(url) do |req|
23
+ req.headers = {'Accept' => 'application/json' }
24
+ end
25
+ MultiJson.load(response.body)
26
+ end
27
+
28
+ context 'successful validations' do
29
+ let(:contracts) do
30
+ Pacto.load_contracts 'spec/integration/data/', 'http://dummyprovider.com'
31
+ end
32
+
33
+ before(:each) do
34
+ Pacto.configure do |c|
35
+ c.strict_matchers = false
36
+ c.register_hook Pacto::Hooks::ERBHook.new
37
+ end
38
+
39
+ contracts.stub_all(:device_id => 42)
40
+ Pacto.validate!
41
+
42
+ Faraday.get('http://dummyprovider.com/hello') do |req|
43
+ req.headers = {'Accept' => 'application/json' }
44
+ end
45
+ end
46
+
47
+ it 'performs successful assertions' do
48
+ # High level assertions
49
+ expect(Pacto).to_not have_unmatched_requests
50
+ expect(Pacto).to_not have_failed_validations
51
+
52
+ # Increasingly strict assertions
53
+ expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello')
54
+ expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with(:headers => {'Accept' => 'application/json'})
55
+ expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').against_contract(/simple_contract.json/)
56
+ end
57
+
58
+ it 'supports negative assertions' do
59
+ expect(Pacto).to_not have_validated(:get, 'http://dummyprovider.com/strict')
60
+ Faraday.get('http://dummyprovider.com/strict') do |req|
61
+ req.headers = {'Accept' => 'application/json' }
62
+ end
63
+ expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict')
64
+ end
65
+
66
+ it 'raises useful error messages' do
67
+ # High level error messages
68
+ 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 }
69
+ expect_to_raise(/Expected Pacto to have found validation problems, but none were found/) { expect(Pacto).to have_failed_validations }
70
+
71
+ unmatched_url = 'http://localhost:8000/404'
72
+ Faraday.get unmatched_url
73
+ expect_to_raise(/the following requests were not matched.*#{Regexp.quote unmatched_url}/m) { expect(Pacto).to_not have_unmatched_requests }
74
+
75
+ # Expected failures
76
+ expect_to_raise(/no matching request was received/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with(:headers => {'Accept' => 'text/plain'}) }
77
+ # No support for with accepting a block
78
+ # expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').with { |req| req.body == "abc" }
79
+ expect_to_raise(/but it was validated against/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').against_contract(/strict_contract.json/) }
80
+ expect_to_raise(/but it was validated against/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/hello').against_contract('simple_contract.json') }
81
+ expect_to_raise(/but no matching request was received/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict') }
82
+ end
83
+
84
+ it 'displays Contract validation problems' do
85
+ contracts.stub_all(:device_id => 1.5)
86
+ Faraday.get('http://dummyprovider.com/strict') do |req|
87
+ req.headers = {'Accept' => 'application/json' }
88
+ end
89
+ expect_to_raise(/validation errors were found:/) { expect(Pacto).to have_validated(:get, 'http://dummyprovider.com/strict') }
90
+
91
+ expect_to_raise(/but the following issues were found:/) { expect(Pacto).to_not have_failed_validations }
92
+ end
93
+ end
94
+ end
@@ -1,36 +1,34 @@
1
1
  require 'securerandom'
2
- require 'pacto/erb_processor'
3
2
 
4
3
  describe 'Templating' do
5
4
  let(:contract_path) { 'spec/integration/data/templating_contract.json' }
5
+ let(:contracts) { Pacto.load_contracts(contract_path, 'http://dummyprovider.com') }
6
6
 
7
7
  let(:key) { SecureRandom.hex }
8
8
  let(:auth_token) { SecureRandom.hex }
9
+
9
10
  let :response do
10
- contract = Pacto.build_from_file(contract_path, 'http://dummyprovider.com')
11
- Pacto.register_contract(contract, 'my_contract')
12
- Pacto.use('my_contract', {:key => key, :auth_token => auth_token})
11
+ contracts.stub_all(:key => key, :auth_token => auth_token)
13
12
 
14
- raw_response = HTTParty.get('http://dummyprovider.com/echo', headers: {
13
+ raw_response = Faraday.get('http://dummyprovider.com/echo') do |req|
14
+ req.headers = {
15
15
  'Accept' => 'application/json',
16
16
  'Custom-Auth-Token' => "#{auth_token}",
17
17
  'X-Message' => "#{key}"
18
18
  }
19
- )
19
+ end
20
20
  MultiJson.load(raw_response.body)
21
21
  end
22
22
 
23
23
  before :each do
24
- Pacto.unregister_all!
24
+ Pacto.clear!
25
25
  end
26
26
 
27
27
  context 'No processing' do
28
28
  it 'does not proccess erb tag' do
29
29
  Pacto.configure do |c|
30
- c.preprocessor = nil
31
- c.postprocessor = nil
32
30
  c.strict_matchers = false
33
- c.register_callback do |contracts, req, res|
31
+ c.register_hook do |contracts, req, res|
34
32
  res
35
33
  end
36
34
  end
@@ -43,9 +41,8 @@ describe 'Templating' do
43
41
  context 'Post processing' do
44
42
  it 'processes erb on each request' do
45
43
  Pacto.configure do |c|
46
- c.preprocessor = nil
47
44
  c.strict_matchers = false
48
- c.postprocessor = Pacto::ERBProcessor.new
45
+ c.register_hook Pacto::Hooks::ERBHook.new
49
46
  end
50
47
 
51
48
  expect(response.keys).to eq ['message']
File without changes
@@ -6,25 +6,25 @@ module Pacto
6
6
  class Servlet < WEBrick::HTTPServlet::AbstractServlet
7
7
  extend Forwardable
8
8
 
9
- def initialize server, json
9
+ def initialize(server, json)
10
10
  super(server)
11
11
 
12
- @doer = PlaybackServlet.new({
12
+ @doer = PlaybackServlet.new(
13
13
  status: 200,
14
- headers: {'Content-Type' => 'application/json'},
14
+ headers: {'Content-Type' => 'application/json', 'Vary' => 'Accept'},
15
15
  body: json
16
- })
16
+ )
17
17
  end
18
18
 
19
- def_delegator :@doer, :do_GET
19
+ def_delegator :@doer, :do_GET # rubocop:disable SymbolName
20
20
  end
21
21
 
22
22
  class Dummy
23
- def initialize port, path, response
23
+ def initialize(port, path, response)
24
24
  params = {
25
25
  :Port => port,
26
26
  :AccessLog => [],
27
- :Logger => WEBrick::Log::new('/dev/null', 7)
27
+ :Logger => WEBrick::Log.new('/dev/null', 7)
28
28
  }
29
29
  @server = WEBrick::HTTPServer.new params
30
30
  @server.mount path, Servlet, response
@@ -32,12 +32,15 @@ module Pacto
32
32
 
33
33
  def start
34
34
  @pid = Thread.new do
35
- trap 'INT' do @server.shutdown end
35
+ trap 'INT' do
36
+ @server.shutdown
37
+ end
36
38
  @server.start
37
39
  end
38
40
  end
39
41
 
40
42
  def terminate
43
+ @server.shutdown
41
44
  @pid.kill
42
45
  end
43
46
  end
@@ -9,7 +9,7 @@ module Pacto
9
9
  @body = attributes.fetch(:body, nil)
10
10
  end
11
11
 
12
- def do_GET(request, response)
12
+ def do_GET(request, response) # rubocop:disable MethodName
13
13
  response.status = status
14
14
  headers.each do |key, value|
15
15
  response[key] = value
@@ -1,7 +1,9 @@
1
1
  require 'coveralls_helper'
2
+ require 'webmock/rspec'
2
3
  require 'pacto'
3
4
  require 'pacto/server'
4
5
  require 'stringio'
6
+ require 'rspec'
5
7
  require 'should_not/rspec'
6
8
 
7
9
  RSpec.configure do |config|
@@ -1,14 +1,14 @@
1
1
  describe Pacto::Hooks::ERBHook do
2
2
  describe '#process' do
3
- let(:req) {
4
- OpenStruct.new({:headers => {'User-Agent' => 'abcd'}})
5
- }
6
- let(:converted_req) {
3
+ let(:req) do
4
+ OpenStruct.new(:headers => {'User-Agent' => 'abcd'})
5
+ end
6
+ let(:converted_req) do
7
7
  {'HEADERS' => {'User-Agent' => 'abcd'}}
8
- }
9
- let(:res) {
10
- OpenStruct.new({:body => 'before'})
11
- }
8
+ end
9
+ let(:res) do
10
+ OpenStruct.new(:body => 'before')
11
+ end
12
12
 
13
13
  before do
14
14
  end
@@ -16,7 +16,7 @@ describe Pacto::Hooks::ERBHook do
16
16
  context 'no matching contracts' do
17
17
  it 'binds the request' do
18
18
  contracts = Set.new
19
- mock_erb({ :req => converted_req })
19
+ mock_erb(:req => converted_req)
20
20
  described_class.new.process contracts, req, res
21
21
  expect(res.body).to eq('after')
22
22
  end
@@ -24,9 +24,9 @@ describe Pacto::Hooks::ERBHook do
24
24
 
25
25
  context 'one matching contract' do
26
26
  it 'binds the request and the contract\'s values' do
27
- contract = OpenStruct.new({:values => {:max => 'test'}})
27
+ contract = OpenStruct.new(:values => {:max => 'test'})
28
28
  contracts = Set.new([contract])
29
- mock_erb({ :req => converted_req, :max => 'test'})
29
+ mock_erb(:req => converted_req, :max => 'test')
30
30
  described_class.new.process contracts, req, res
31
31
  expect(res.body).to eq('after')
32
32
  end
@@ -34,10 +34,10 @@ describe Pacto::Hooks::ERBHook do
34
34
 
35
35
  context 'multiple matching contracts' do
36
36
  it 'binds the request and the first contract\'s values' do
37
- contract1 = OpenStruct.new({:values => {:max => 'test'}})
38
- contract2 = OpenStruct.new({:values => {:mob => 'team'}})
39
- res = OpenStruct.new({:body => 'before'})
40
- mock_erb({ :req => converted_req, :max => 'test'})
37
+ contract1 = OpenStruct.new(:values => {:max => 'test'})
38
+ contract2 = OpenStruct.new(:values => {:mob => 'team'})
39
+ res = OpenStruct.new(:body => 'before')
40
+ mock_erb(:req => converted_req, :max => 'test')
41
41
  contracts = Set.new([contract1, contract2])
42
42
  described_class.new.process contracts, req, res
43
43
  expect(res.body).to eq('after')
@@ -3,16 +3,8 @@ module Pacto
3
3
  subject(:configuration) { Configuration.new }
4
4
  let(:contracts_path) { 'path_to_contracts' }
5
5
 
6
- it 'sets the preprocessor by default to ERBProcessor' do
7
- expect(configuration.preprocessor).to be_kind_of ERBProcessor
8
- end
9
-
10
- it 'sets the postprocessor by default to HashMergeProcessor' do
11
- expect(configuration.postprocessor).to be_kind_of HashMergeProcessor
12
- end
13
-
14
- it 'sets the stub provider by default to BuiltIn' do
15
- expect(configuration.provider).to be_kind_of Stubs::BuiltIn
6
+ it 'sets the stub provider by default to WebMockAdapter' do
7
+ expect(configuration.provider).to be_kind_of Stubs::WebMockAdapter
16
8
  end
17
9
 
18
10
  it 'sets strict matchers by default to true' do
@@ -1,20 +1,23 @@
1
+ require 'spec_helper'
2
+
1
3
  module Pacto
2
4
  describe ContractFactory do
3
- let(:host) { 'http://localhost' }
4
- let(:contract_name) { 'contract' }
5
- let(:contract_path) { File.join('spec', 'unit', 'data', "#{contract_name}.json") }
6
- let(:file_pre_processor) { double('file_pre_processor') }
7
- let(:file_content) { File.read(contract_path) }
5
+ let(:host) { 'http://localhost' }
6
+ let(:contract_name) { 'contract' }
7
+ let(:contracts_path) { %w(spec unit data) }
8
+ let(:contract_path) { File.join(contracts_path, "#{contract_name}.json") }
9
+ subject(:contract_factory) { ContractFactory.new }
8
10
 
9
- describe '.build_from_file' do
10
- it 'builds a contract given a JSON file path and a host' do
11
- file_pre_processor.stub(:process).and_return(file_content)
12
- expect(described_class.build_from_file(contract_path, host, file_pre_processor)).to be_a_kind_of(Pacto::Contract)
13
- end
11
+ it 'builds a contract given a JSON file path and a host' do
12
+ contract = contract_factory.build_from_file(contract_path, host)
13
+ expect(contract).to be_a(Contract)
14
+ end
14
15
 
15
- it 'processes files using File Pre Processor module' do
16
- file_pre_processor.should_receive(:process).with(file_content).and_return(file_content)
17
- described_class.build_from_file(contract_path, host, file_pre_processor)
16
+ it 'builds contracts from a list of file paths and a host' do
17
+ contract_files = [contract_path, contract_path]
18
+ contracts = contract_factory.build(contract_files, host)
19
+ contracts.each do |contract|
20
+ expect(contract).to be_a(Contract)
18
21
  end
19
22
  end
20
23
  end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+ module Pacto
5
+ describe ContractFiles do
6
+ let(:test_dir) { File.join(File.dirname(__FILE__), 'temp') }
7
+ let(:contract_1) { Pathname.new(File.join(test_dir, 'contract_1.json')) }
8
+ let(:contract_2) { Pathname.new(File.join(test_dir, 'contract_2.json')) }
9
+ let(:contract_3) { Pathname.new(File.join(test_dir, 'nested', 'contract_3.json')) }
10
+
11
+ before do
12
+ Dir.mkdir(test_dir)
13
+ Dir.chdir(test_dir) do
14
+ Dir.mkdir('nested')
15
+ ['contract_1.json', 'contract_2.json', 'not_a_contract', 'nested/contract_3.json'].each do |file|
16
+ FileUtils.touch file
17
+ end
18
+ end
19
+ end
20
+
21
+ after do
22
+ FileUtils.rm_rf(test_dir)
23
+ end
24
+
25
+ describe 'for a dir' do
26
+ it 'returns a list with the full path of all json found recursively in that dir' do
27
+ files = ContractFiles.for(test_dir)
28
+ expect(files.size).to eq(3)
29
+ expect(files).to include(contract_1)
30
+ expect(files).to include(contract_2)
31
+ expect(files).to include(contract_3)
32
+ end
33
+ end
34
+
35
+ describe 'for a file' do
36
+ it 'returns a list containing only that file' do
37
+ files = ContractFiles.for(File.join(test_dir, 'contract_1.json'))
38
+ expect(files).to eq [contract_1]
39
+ end
40
+ end
41
+ end
42
+ end