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
@@ -0,0 +1,60 @@
1
+ module Pacto
2
+ describe Validation do
3
+ let(:request) { double('request') }
4
+ let(:response) { double('response') }
5
+ let(:contract) { double('contract') }
6
+ let(:validation_results) { double('validation_results') }
7
+
8
+ before(:each) do
9
+ allow(contract).to receive(:validate_consumer)
10
+ end
11
+
12
+ it 'stores the request, response and contract' do
13
+ validation = Pacto::Validation.new request, response, contract
14
+ expect(validation.request).to eq request
15
+ expect(validation.response).to eq response
16
+ end
17
+
18
+ it 'generates and stores the results' do
19
+ expect(contract).to receive(:validate_consumer).with(request, response).and_return(validation_results)
20
+ validation = Pacto::Validation.new request, response, contract
21
+ expect(validation.results).to eq validation_results
22
+ end
23
+
24
+ describe '#successful?' do
25
+ subject(:validation) do
26
+ Pacto::Validation.new request, response, contract
27
+ end
28
+
29
+ it 'returns true if there were no validation errors' do
30
+ expect(validation.successful?).to be_true
31
+ end
32
+
33
+ it 'returns false if there were validation errors' do
34
+ expect(validation.successful?).to be_true
35
+ end
36
+ end
37
+
38
+ describe '#against_contract?' do
39
+ it 'returns nil if there was no contract' do
40
+ validation = Pacto::Validation.new request, response, nil
41
+ expect(validation.against_contract? 'a').to be_nil
42
+ end
43
+
44
+ it 'returns the contract with an exact string name match' do
45
+ allow(contract).to receive(:file).and_return('foo')
46
+ validation = Pacto::Validation.new request, response, contract
47
+ expect(validation.against_contract? 'foo').to eq(contract)
48
+ expect(validation.against_contract? 'bar').to be_nil
49
+ end
50
+
51
+ it 'returns the contract if there is a regex match' do
52
+ allow(contract).to receive(:file).and_return 'foobar'
53
+ validation = Pacto::Validation.new request, response, contract
54
+ expect(validation.against_contract?(/foo/)).to eq(contract)
55
+ expect(validation.against_contract?(/bar/)).to eq(contract)
56
+ expect(validation.against_contract?(/baz/)).to be_nil
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,32 +1,23 @@
1
1
  module Pacto
2
2
  module Extensions
3
3
  describe HashSubsetOf do
4
- describe '#subset_of?' do
5
- context 'when the other hash is the same' do
6
- it 'returns true' do
7
- expect({:a => 'a'}).to be_subset_of({:a => 'a'})
8
- end
9
- end
10
-
11
- context 'when the other hash is a subset' do
12
- it 'returns true' do
13
- expect({:a => 'a'}).to be_subset_of({:a => 'a', :b => 'b'})
14
- end
15
- end
16
-
17
- context 'when the other hash is not a subset' do
18
- it 'returns false' do
19
- expect({:a => 'a'}.subset_of?({:a => 'b'})).to be_false
20
- end
4
+ describe '#normalize_keys' do
5
+ it 'turns keys into downcased strings' do
6
+ expect({:A => 'a'}.normalize_keys).to eq('a' => 'a')
7
+ expect({:a => 'a'}.normalize_keys).to eq('a' => 'a')
8
+ expect({'A' => 'a'}.normalize_keys).to eq('a' => 'a')
9
+ expect({'a' => 'a'}.normalize_keys).to eq('a' => 'a')
21
10
  end
22
11
  end
23
12
 
24
- describe '#normalize_keys' do
25
- it 'turns keys into downcased strings' do
26
- expect({:A => 'a'}.normalize_keys).to eq({'a' => 'a'})
27
- expect({:a => 'a'}.normalize_keys).to eq({'a' => 'a'})
28
- expect({'A' => 'a'}.normalize_keys).to eq({'a' => 'a'})
29
- expect({'a' => 'a'}.normalize_keys).to eq({'a' => 'a'})
13
+ describe '#normalize_header_keys' do
14
+ it 'matches headers to the style in the RFC documentation' do
15
+ expect(Pacto::Extensions.normalize_header_keys(:'user-agent' => 'a')).to eq('User-Agent' => 'a') # rubocop:disable SymbolName
16
+ expect(Pacto::Extensions.normalize_header_keys(:user_agent => 'a')).to eq('User-Agent' => 'a')
17
+ expect(Pacto::Extensions.normalize_header_keys('User-Agent' => 'a')).to eq('User-Agent' => 'a')
18
+ expect(Pacto::Extensions.normalize_header_keys('user-agent' => 'a')).to eq('User-Agent' => 'a')
19
+ expect(Pacto::Extensions.normalize_header_keys('user_agent' => 'a')).to eq('User-Agent' => 'a')
20
+ expect(Pacto::Extensions.normalize_header_keys('USER_AGENT' => 'a')).to eq('User-Agent' => 'a')
30
21
  end
31
22
  end
32
23
  end
@@ -0,0 +1,99 @@
1
+ module Pacto
2
+ class Generator
3
+ describe Filters do
4
+ let(:record_host) do
5
+ 'http://example.com'
6
+ end
7
+ let(:request) do
8
+ RequestClause.new(
9
+ record_host,
10
+ 'method' => 'GET',
11
+ 'path' => '/abcd',
12
+ 'headers' => {
13
+ 'Server' => ['example.com'],
14
+ 'Connection' => ['Close'],
15
+ 'Content-Length' => [1234],
16
+ 'Via' => ['Some Proxy'],
17
+ 'User-Agent' => ['rspec']
18
+ },
19
+ 'params' => {
20
+ 'apikey' => "<%= ENV['MY_API_KEY'] %>"
21
+ }
22
+ )
23
+ end
24
+ let(:varies) { ['User-Agent'] }
25
+ let(:response) do
26
+ Faraday::Response.new(
27
+ :status => 200,
28
+ :response_headers => {
29
+ 'Date' => Time.now.rfc2822,
30
+ 'Last-Modified' => Time.now.rfc2822,
31
+ 'ETag' => 'abc123',
32
+ 'Server' => ['Fake Server'],
33
+ 'Content-Type' => ['application/json'],
34
+ 'Vary' => varies
35
+ },
36
+ :body => double('dummy body')
37
+ )
38
+ end
39
+
40
+ describe '#filter_request_headers' do
41
+ subject(:filtered_request_headers) { described_class.new.filter_request_headers(request, response).keys.map(&:downcase) }
42
+ it 'keeps important request headers' do
43
+ expect(filtered_request_headers).to include 'user-agent'
44
+ end
45
+
46
+ it 'filters informational request headers' do
47
+ expect(filtered_request_headers).not_to include 'via'
48
+ expect(filtered_request_headers).not_to include 'date'
49
+ expect(filtered_request_headers).not_to include 'server'
50
+ expect(filtered_request_headers).not_to include 'content-length'
51
+ expect(filtered_request_headers).not_to include 'connection'
52
+ end
53
+
54
+ context 'multiple Vary elements' do
55
+ context 'as a single string' do
56
+ let(:varies) do
57
+ ['User-Agent,Via']
58
+ end
59
+ it 'keeps each header' do
60
+ expect(filtered_request_headers).to include 'user-agent'
61
+ expect(filtered_request_headers).to include 'via'
62
+ end
63
+ end
64
+ context 'as multiple items' do
65
+ let(:varies) do
66
+ %w{User-Agent Via}
67
+ end
68
+ it 'keeps each header' do
69
+ expect(filtered_request_headers).to include 'user-agent'
70
+ expect(filtered_request_headers).to include 'via'
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ describe '#filter_response_headers' do
77
+ subject(:filtered_response_headers) { described_class.new.filter_response_headers(request, response).keys.map(&:downcase) }
78
+ it 'keeps important response headers' do
79
+ expect(filtered_response_headers).to include 'content-type'
80
+ end
81
+
82
+ it 'filters connection control headers' do
83
+ expect(filtered_response_headers).not_to include 'content-length'
84
+ expect(filtered_response_headers).not_to include 'via'
85
+ end
86
+
87
+ it 'filters freshness headers' do
88
+ expect(filtered_response_headers).not_to include 'date'
89
+ expect(filtered_response_headers).not_to include 'last-modified'
90
+ expect(filtered_response_headers).not_to include 'eTag'
91
+ end
92
+
93
+ it 'filters x-* headers' do
94
+ expect(filtered_response_headers).not_to include 'x-men'
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,73 +1,53 @@
1
1
  module Pacto
2
2
  describe Generator do
3
- let(:record_host) {
3
+ let(:record_host) do
4
4
  'http://example.com'
5
- }
5
+ end
6
+
6
7
  let(:request) do
7
- Pacto::Request.new(record_host, {
8
- 'method' => 'GET',
9
- 'path' => '/abcd',
10
- 'headers' => {
8
+ Faraday::Request.create :get do |req|
9
+ req.path = '/abcd'
10
+ req.params = { 'apikey' => "<%= ENV['MY_API_KEY'] %>" }
11
+ req.headers = {
11
12
  'Content-Length' => [1234],
12
13
  'Via' => ['Some Proxy'],
13
14
  'User-Agent' => ['rspec']
14
- },
15
- 'params' => []
16
- })
15
+ }
16
+ end
17
17
  end
18
+
18
19
  let(:response_adapter) do
19
- Pacto::ResponseAdapter.new(
20
- OpenStruct.new({
21
- 'status' => 200,
22
- 'headers' => {
23
- 'Date' => [Time.now],
24
- 'Server' => ['Fake Server'],
25
- 'Content-Type' => ['application/json']
26
- },
27
- 'body' => double('dummy body')
28
- })
20
+ Faraday::Response.new(
21
+ :status => 200,
22
+ :response_headers => {
23
+ 'Date' => [Time.now],
24
+ 'Server' => ['Fake Server'],
25
+ 'Content-Type' => ['application/json'],
26
+ 'Vary' => ['User-Agent']
27
+ },
28
+ :body => 'dummy body' # body is just a string
29
29
  )
30
30
  end
31
+ let(:filtered_request_headers) { double('filtered_response_headers') }
32
+ let(:filtered_response_headers) { double('filtered_response_headers') }
31
33
  let(:response_body_schema) { '{"message": "dummy generated schema"}' }
32
34
  let(:version) { 'draft3' }
33
35
  let(:schema_generator) { double('schema_generator') }
34
36
  let(:validator) { double('validator') }
37
+ let(:filters) { double :filters }
35
38
  let(:request_file) { 'request.json' }
36
- let(:generator) { described_class.new version, schema_generator, validator }
39
+ let(:options) { Pacto.configuration.generator_options }
40
+ let(:generator) { described_class.new version, schema_generator, validator, options, filters }
37
41
 
38
- def pretty obj
42
+ def pretty(obj)
39
43
  MultiJson.encode(obj, :pretty => true).gsub(/^$\n/, '')
40
44
  end
41
45
 
42
- describe '#generate' do
43
- let(:request_contract) {
44
- double({
45
- :request => request,
46
- })
47
- }
48
- let(:generated_contract) { double('generated contract') }
46
+ describe '#save' do
49
47
  before do
50
- Pacto.should_receive(:build_from_file).with(request_file, record_host).and_return request_contract
51
- request.should_receive(:execute).and_return response_adapter
52
- end
53
-
54
- it 'parses the request' do
55
- generator.should_receive(:save).with(request_file, request, anything)
56
- generator.generate request_file, record_host
57
- end
58
-
59
- it 'fetches a response' do
60
- generator.should_receive(:save).with(request_file, anything, response_adapter)
61
- generator.generate request_file, record_host
62
- end
63
-
64
- it 'saves the result' do
65
- generator.should_receive(:save).with(request_file, request, response_adapter).and_return generated_contract
66
- expect(generator.generate request_file, record_host).to eq(generated_contract)
48
+ filters.should_receive(:filter_request_headers).with(request, response_adapter).and_return filtered_request_headers
49
+ filters.should_receive(:filter_response_headers).with(request, response_adapter).and_return filtered_response_headers
67
50
  end
68
- end
69
-
70
- describe '#save' do
71
51
  context 'invalid schema' do
72
52
  it 'raises an error if schema generation fails' do
73
53
  JSON::SchemaGenerator.should_receive(:generate).and_raise ArgumentError.new('Could not generate schema')
@@ -82,11 +62,11 @@ module Pacto
82
62
  end
83
63
 
84
64
  context 'valid schema' do
85
- let(:raw_contract) {
86
- JSON::SchemaGenerator.should_receive(:generate).with(request_file, response_adapter.body, 'draft3').and_return response_body_schema
65
+ let(:raw_contract) do
66
+ JSON::SchemaGenerator.should_receive(:generate).with(request_file, response_adapter.body, Pacto.configuration.generator_options).and_return response_body_schema
87
67
  validator.should_receive(:validate).and_return true
88
68
  generator.save request_file, request, response_adapter
89
- }
69
+ end
90
70
  subject(:generated_contract) { JSON.parse raw_contract }
91
71
 
92
72
  it 'sets the body to the generated json-schema' do
@@ -99,17 +79,9 @@ module Pacto
99
79
  expect(generated_request['path']).to eq(request.path)
100
80
  end
101
81
 
102
- it 'keeps important request headers' do
103
- saved_headers = subject['request']['headers']
104
- expect(saved_headers.keys).to include 'User-Agent'
105
- end
106
-
107
- it 'filters informational request headers' do
108
- saved_headers = subject['request']['headers']
109
- expect(saved_headers).not_to include 'Date'
110
- expect(saved_headers).not_to include 'Server'
111
- expect(saved_headers).not_to include 'Content-Length'
112
- expect(saved_headers).not_to include 'Connection'
82
+ it 'preserves ERB in the request params' do
83
+ generated_request = subject['request']
84
+ expect(generated_request['params']['apikey']).to eq("<%= ENV['MY_API_KEY'] %>")
113
85
  end
114
86
 
115
87
  it 'normalizes the request method' do
@@ -122,17 +94,6 @@ module Pacto
122
94
  expect(generated_response['status']).to eq(response_adapter.status)
123
95
  end
124
96
 
125
- it 'keeps important response headers' do
126
- saved_headers = subject['response']['headers']
127
- expect(saved_headers.keys).to include 'Content-Type'
128
- end
129
-
130
- it 'filters informational response headers' do
131
- saved_headers = subject['response']['headers']
132
- expect(saved_headers).not_to include 'Content-Length'
133
- expect(saved_headers).not_to include 'Via'
134
- end
135
-
136
97
  it 'generates pretty JSON' do
137
98
  expect(raw_contract).to eq(pretty(subject))
138
99
  end
@@ -31,7 +31,7 @@ module Pacto
31
31
  EOF
32
32
  end
33
33
 
34
- let(:invalid_contract) do
34
+ let(:partial_contract) do
35
35
  <<-EOF
36
36
  {
37
37
  "request": {
@@ -47,22 +47,62 @@ module Pacto
47
47
  EOF
48
48
  end
49
49
 
50
+ let(:invalid_contract) do
51
+ <<-EOF
52
+ {
53
+ "request": {
54
+ "method": "GET",
55
+ "path": "/hello_world",
56
+ "headers": {
57
+ "Accept": "application/json"
58
+ },
59
+ "params": {}
60
+ },
61
+
62
+ "response": {
63
+ "status": 200,
64
+ "headers": {
65
+ "Content-Type": "application/json"
66
+ },
67
+ "body": {
68
+ "description": "A simple response",
69
+ "required": {},
70
+ "type": "object",
71
+ "properties": {
72
+ "message": {
73
+ "type": "string"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ EOF
80
+ end
81
+
50
82
  subject(:schema) { MetaSchema.new }
51
83
 
52
84
  describe 'when validating a contract against the master schema' do
53
85
  context 'with a valid contract structure' do
54
86
  it 'does not raise any exceptions' do
55
- expect {
87
+ expect do
56
88
  schema.validate(valid_contract)
57
- }.to_not raise_error(Exception)
89
+ end.to_not raise_error(Exception)
90
+ end
91
+ end
92
+
93
+ context 'with an partial contract structure' do
94
+ it 'raises InvalidContract exception' do
95
+ expect do
96
+ schema.validate(invalid_contract)
97
+ end.to raise_error(InvalidContract)
58
98
  end
59
99
  end
60
100
 
61
- context 'with an invalid contract structure' do
101
+ context 'with an invalid contract' do
62
102
  it 'raises InvalidContract exception' do
63
- expect {
103
+ expect do
64
104
  schema.validate(invalid_contract)
65
- }.to raise_error(InvalidContract)
105
+ end.to raise_error(InvalidContract)
66
106
  end
67
107
  end
68
108
  end
@@ -1,5 +1,6 @@
1
- describe Pacto do
1
+ require 'spec_helper'
2
2
 
3
+ describe Pacto do
3
4
  around(:each) do |example|
4
5
  $stdout = StringIO.new
5
6
  example.run
@@ -19,7 +20,7 @@ describe Pacto do
19
20
  it 'displays a success message and return true' do
20
21
  mock_validation []
21
22
  success = Pacto.validate_contract 'my_contract.json'
22
- expect(output).to eq 'All contracts successfully meta-validated'
23
+ expect(output).to eq 'Validating my_contract.json'
23
24
  expect(success).to be_true
24
25
  end
25
26
  end
@@ -28,7 +29,7 @@ describe Pacto do
28
29
  it 'displays one error messages and return false' do
29
30
  mock_validation ['Error 1']
30
31
  success = Pacto.validate_contract 'my_contract.json'
31
- expect(output).to match /error/
32
+ expect(output).to match(/error/)
32
33
  expect(success).to be_false
33
34
  end
34
35
 
@@ -40,21 +41,22 @@ describe Pacto do
40
41
  end
41
42
  end
42
43
 
43
- describe '.build_from_file' do
44
- let(:path) { 'contract/path' }
45
- let(:host) { 'http://localhost' }
46
- let(:file_pre_processor) { double('file_pre_processor') }
47
- let(:instantiated_contract) { double(:instantiated_contract) }
44
+ describe 'loading contracts' do
45
+ let(:contracts_path) { 'path/to/dir' }
46
+ let(:host) { 'localhost' }
47
+ let(:contract1) { double }
48
+ let(:contract2) { double }
49
+ let(:factory) { double(:factory) }
48
50
 
49
- it 'delegates to ContractFactory' do
50
- Pacto::ContractFactory.should_receive(:build_from_file).with(path, host, file_pre_processor)
51
- described_class.build_from_file(path, host, file_pre_processor)
51
+ before do
52
+ allow(Pacto::ContractFactory).to receive(:new).and_return(factory)
52
53
  end
53
54
 
54
- it 'returns whatever the factory returns' do
55
- Pacto::ContractFactory.stub(:build_from_file => instantiated_contract)
56
- expect(described_class.build_from_file(path, host, file_pre_processor)).to eq instantiated_contract
55
+ it 'instantiates a contract list' do
56
+ allow(Pacto::ContractFiles).to receive(:for).with(contracts_path).and_return { %w{file1 file2} }
57
+ allow(factory).to receive(:build).with(%w{file1 file2}, host).and_return { [contract1, contract2] }
58
+ expect(Pacto::ContractList).to receive(:new).with([contract1, contract2])
59
+ Pacto.load_contracts(contracts_path, host)
57
60
  end
58
61
  end
59
-
60
62
  end