pacto 0.2.5 → 0.3.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +3 -0
  2. data/.rspec +0 -2
  3. data/.rubocop-todo.yml +51 -0
  4. data/.rubocop.yml +1 -0
  5. data/.travis.yml +4 -2
  6. data/Guardfile +28 -14
  7. data/README.md +81 -51
  8. data/Rakefile +24 -11
  9. data/features/generation/generation.feature +25 -0
  10. data/features/journeys/validation.feature +74 -0
  11. data/features/support/env.rb +16 -0
  12. data/lib/pacto.rb +63 -34
  13. data/lib/pacto/contract.rb +25 -11
  14. data/lib/pacto/contract_factory.rb +13 -44
  15. data/lib/pacto/core/callback.rb +11 -0
  16. data/lib/pacto/core/configuration.rb +34 -0
  17. data/lib/pacto/core/contract_repository.rb +44 -0
  18. data/lib/pacto/erb_processor.rb +18 -0
  19. data/lib/pacto/exceptions/invalid_contract.rb +10 -1
  20. data/lib/pacto/extensions.rb +2 -2
  21. data/lib/pacto/generator.rb +75 -0
  22. data/lib/pacto/hash_merge_processor.rb +14 -0
  23. data/lib/pacto/hooks/erb_hook.rb +17 -0
  24. data/lib/pacto/logger.rb +42 -0
  25. data/lib/pacto/meta_schema.rb +17 -0
  26. data/lib/pacto/rake_task.rb +75 -12
  27. data/lib/pacto/request.rb +3 -4
  28. data/lib/pacto/response.rb +27 -19
  29. data/lib/pacto/server.rb +2 -0
  30. data/lib/pacto/server/dummy.rb +45 -0
  31. data/lib/pacto/server/playback_servlet.rb +21 -0
  32. data/lib/pacto/stubs/built_in.rb +57 -0
  33. data/lib/pacto/version.rb +1 -1
  34. data/pacto.gemspec +8 -2
  35. data/resources/contract_schema.json +216 -0
  36. data/spec/coveralls_helper.rb +10 -0
  37. data/spec/integration/data/strict_contract.json +33 -0
  38. data/spec/integration/data/templating_contract.json +25 -0
  39. data/spec/integration/e2e_spec.rb +40 -7
  40. data/spec/integration/templating_spec.rb +55 -0
  41. data/spec/spec_helper.rb +17 -0
  42. data/spec/unit/data/simple_contract.json +22 -0
  43. data/spec/unit/hooks/erb_hook_spec.rb +51 -0
  44. data/spec/unit/pacto/configuration_spec.rb +51 -0
  45. data/spec/unit/pacto/contract_factory_spec.rb +4 -35
  46. data/spec/unit/pacto/contract_spec.rb +59 -31
  47. data/spec/unit/pacto/core/configuration_spec.rb +28 -0
  48. data/spec/unit/pacto/core/contract_repository_spec.rb +133 -0
  49. data/spec/unit/pacto/erb_processor_spec.rb +23 -0
  50. data/spec/unit/pacto/extensions_spec.rb +11 -11
  51. data/spec/unit/pacto/generator_spec.rb +142 -0
  52. data/spec/unit/pacto/hash_merge_processor_spec.rb +20 -0
  53. data/spec/unit/pacto/logger_spec.rb +44 -0
  54. data/spec/unit/pacto/meta_schema_spec.rb +70 -0
  55. data/spec/unit/pacto/pacto_spec.rb +32 -58
  56. data/spec/unit/pacto/request_spec.rb +83 -34
  57. data/spec/unit/pacto/response_adapter_spec.rb +9 -11
  58. data/spec/unit/pacto/response_spec.rb +68 -68
  59. data/spec/unit/pacto/server/playback_servlet_spec.rb +24 -0
  60. data/spec/unit/pacto/stubs/built_in_spec.rb +168 -0
  61. metadata +291 -147
  62. data/.rspec_integration +0 -4
  63. data/.rspec_unit +0 -4
  64. data/lib/pacto/file_pre_processor.rb +0 -12
  65. data/lib/pacto/instantiated_contract.rb +0 -62
  66. data/spec/integration/spec_helper.rb +0 -1
  67. data/spec/integration/utils/dummy_server.rb +0 -34
  68. data/spec/unit/pacto/file_pre_processor_spec.rb +0 -13
  69. data/spec/unit/pacto/instantiated_contract_spec.rb +0 -224
  70. data/spec/unit/spec_helper.rb +0 -5
data/.rspec_integration DELETED
@@ -1,4 +0,0 @@
1
- --colour
2
- --require spec_helper
3
- --require integration/spec_helper
4
- --pattern spec/integration/**/*_spec.rb
data/.rspec_unit DELETED
@@ -1,4 +0,0 @@
1
- --colour
2
- --require spec_helper
3
- --require unit/spec_helper
4
- --pattern spec/unit/**/*_spec.rb
@@ -1,12 +0,0 @@
1
- module Pacto
2
- class FilePreProcessor
3
- def process(file_string)
4
- erb = ERB.new file_string
5
- erb_result = erb.result binding
6
- if ENV["DEBUG_PACTO"]
7
- puts "[DEBUG] Processed contract: #{erb_result.inspect}"
8
- end
9
- erb_result
10
- end
11
- end
12
- end
@@ -1,62 +0,0 @@
1
- module Pacto
2
- class InstantiatedContract
3
- attr_reader :response_body
4
-
5
- def initialize(request, response)
6
- @request = request
7
- @response = response
8
- @response_body = response.body
9
- end
10
-
11
- def request_path
12
- @request.absolute_uri
13
- end
14
-
15
- def request_uri
16
- @request.full_uri
17
- end
18
-
19
- def replace!(values)
20
- if @response_body.respond_to?(:normalize_keys)
21
- @response_body = @response_body.normalize_keys.deep_merge(values.normalize_keys)
22
- else
23
- @response_body = values
24
- end
25
- end
26
-
27
- def stub!
28
- WebMock.stub_request(@request.method, "#{@request.host}#{@request.path}").
29
- with(request_details).
30
- to_return({
31
- :status => @response.status,
32
- :headers => @response.headers,
33
- :body => format_body(@response_body)
34
- })
35
- end
36
-
37
- private
38
-
39
- def format_body(body)
40
- if body.is_a?(Hash) or body.is_a?(Array)
41
- body.to_json
42
- else
43
- body
44
- end
45
- end
46
-
47
- def request_details
48
- details = {}
49
- unless @request.params.empty?
50
- details[webmock_params_key] = @request.params
51
- end
52
- unless @request.headers.empty?
53
- details[:headers] = @request.headers
54
- end
55
- details
56
- end
57
-
58
- def webmock_params_key
59
- @request.method == :get ? :query : :body
60
- end
61
- end
62
- end
@@ -1 +0,0 @@
1
- require_relative 'utils/dummy_server'
@@ -1,34 +0,0 @@
1
- require 'webrick'
2
-
3
- class Servlet < WEBrick::HTTPServlet::AbstractServlet
4
- def initialize(server, json)
5
- super(server)
6
- @json = json
7
- end
8
-
9
- def do_GET(request, response)
10
- response.status = 200
11
- response['Content-Type'] = 'application/json'
12
- response.body = @json
13
- end
14
- end
15
-
16
- class DummyServer
17
- def initialize port, path, response
18
- @server = WEBrick::HTTPServer.new :Port => port,
19
- :AccessLog => [],
20
- :Logger => WEBrick::Log::new("/dev/null", 7)
21
- @server.mount path, Servlet, response
22
- end
23
-
24
- def start
25
- @pid = fork do
26
- trap 'INT' do @server.shutdown end
27
- @server.start
28
- end
29
- end
30
-
31
- def terminate
32
- Process.kill('INT', @pid)
33
- end
34
- end
@@ -1,13 +0,0 @@
1
- module Pacto
2
- describe FilePreProcessor do
3
- describe "#process" do
4
- it "should return the result of ERB" do
5
- subject.process("2 + 2 = <%= 2 + 2 %>").should == "2 + 2 = 4"
6
- end
7
-
8
- it "should not mess with pure JSONs" do
9
- subject.process('{"property": ["one", "two, null"]}')
10
- end
11
- end
12
- end
13
- end
@@ -1,224 +0,0 @@
1
- module Pacto
2
- describe InstantiatedContract do
3
- describe '#replace!' do
4
- let(:body) { double('body') }
5
- let(:response) { double(:body => body) }
6
- let(:values) { double('values') }
7
-
8
- context 'when response body is a hash' do
9
- let(:normalized_values) { double('normalized values') }
10
- let(:normalized_body) { double('normalized body') }
11
- let(:merged_body) { double('merged body') }
12
-
13
- it 'should normalize keys and deep merge response body with given values' do
14
- values.should_receive(:normalize_keys).and_return(normalized_values)
15
- response.body.should_receive(:normalize_keys).and_return(normalized_body)
16
- normalized_body.should_receive(:deep_merge).with(normalized_values).and_return(merged_body)
17
-
18
- instantiated_contract = described_class.new(nil, response)
19
- instantiated_contract.replace!(values)
20
-
21
- instantiated_contract.response_body.should == merged_body
22
- end
23
- end
24
-
25
- context 'when response body is a string' do
26
- let(:body) { 'foo' }
27
-
28
- it 'should replace response body with given values' do
29
- instantiated_contract = described_class.new(nil, response)
30
- instantiated_contract.replace!(values)
31
- instantiated_contract.response_body.should == values
32
- end
33
- end
34
-
35
- context 'when response body is nil' do
36
- let(:body) { nil }
37
-
38
- it 'should replace response body with given values' do
39
- instantiated_contract = described_class.new(nil, response)
40
- instantiated_contract.replace!(values)
41
- instantiated_contract.response_body.should == values
42
- end
43
- end
44
- end
45
-
46
- describe '#response_body' do
47
- let(:response) { double(:body => double('body')) }
48
-
49
- it "should return response body" do
50
- described_class.new(nil, response).response_body.should == response.body
51
- end
52
- end
53
-
54
- describe '#request_path' do
55
- let(:request) { double('request', :absolute_uri => "http://dummy_link/hello_world") }
56
- let(:response) { double('response', :body => double('body')) }
57
-
58
- it "should return the request absolute uri" do
59
- described_class.new(request, response).request_path.should == "http://dummy_link/hello_world"
60
- end
61
- end
62
-
63
- describe '#request_uri' do
64
- let(:request) { double('request', :full_uri => "http://dummy_link/hello_world?param=value#fragment") }
65
- let(:response) { double('response', :body => double('body')) }
66
-
67
- it "should return request full uri" do
68
- described_class.new(request, response).request_uri.should == "http://dummy_link/hello_world?param=value#fragment"
69
- end
70
- end
71
-
72
- describe '#stub!' do
73
- let(:request) do
74
- double({
75
- :host => 'http://localhost',
76
- :method => method,
77
- :path => '/hello_world',
78
- :headers => {'Accept' => 'application/json'},
79
- :params => {'foo' => 'bar'}
80
- })
81
- end
82
-
83
- let(:method) { :get }
84
-
85
- let(:response) do
86
- double({
87
- :status => 200,
88
- :headers => {},
89
- :body => body
90
- })
91
- end
92
-
93
- let(:body) do
94
- {'message' => 'foo'}
95
- end
96
-
97
- let(:stubbed_request) { double('stubbed request') }
98
-
99
- before do
100
- WebMock.should_receive(:stub_request).
101
- with(request.method, "#{request.host}#{request.path}").
102
- and_return(stubbed_request)
103
-
104
- stubbed_request.stub(:to_return).with({
105
- :status => response.status,
106
- :headers => response.headers,
107
- :body => response.body.to_json
108
- })
109
- end
110
-
111
- context 'when the response body is an object' do
112
- let(:body) do
113
- {'message' => 'foo'}
114
- end
115
-
116
- it 'should stub the response body with a json representation' do
117
- stubbed_request.should_receive(:to_return).with({
118
- :status => response.status,
119
- :headers => response.headers,
120
- :body => response.body.to_json
121
- })
122
-
123
- stubbed_request.stub(:with).and_return(stubbed_request)
124
-
125
- described_class.new(request, response).stub!
126
- end
127
- end
128
-
129
- context 'when the response body is an array' do
130
- let(:body) do
131
- [1, 2, 3]
132
- end
133
-
134
- it 'should stub the response body with a json representation' do
135
- stubbed_request.should_receive(:to_return).with({
136
- :status => response.status,
137
- :headers => response.headers,
138
- :body => response.body.to_json
139
- })
140
-
141
- stubbed_request.stub(:with).and_return(stubbed_request)
142
-
143
- described_class.new(request, response).stub!
144
- end
145
- end
146
-
147
- context 'when the response body is not an object or an array' do
148
- let(:body) { nil }
149
-
150
- it 'should stub the response body with the original body' do
151
- stubbed_request.should_receive(:to_return).with({
152
- :status => response.status,
153
- :headers => response.headers,
154
- :body => response.body
155
- })
156
-
157
- stubbed_request.stub(:with).and_return(stubbed_request)
158
-
159
- described_class.new(request, response).stub!
160
- end
161
- end
162
-
163
- context 'a GET request' do
164
- let(:method) { :get }
165
-
166
- it 'should use WebMock to stub the request' do
167
- stubbed_request.should_receive(:with).
168
- with({:headers => request.headers, :query => request.params}).
169
- and_return(stubbed_request)
170
- described_class.new(request, response).stub!
171
- end
172
- end
173
-
174
- context 'a POST request' do
175
- let(:method) { :post }
176
-
177
- it 'should use WebMock to stub the request' do
178
- stubbed_request.should_receive(:with).
179
- with({:headers => request.headers, :body => request.params}).
180
- and_return(stubbed_request)
181
- described_class.new(request, response).stub!
182
- end
183
- end
184
-
185
- context 'a request with no headers' do
186
- let(:request) do
187
- double({
188
- :host => 'http://localhost',
189
- :method => :get,
190
- :path => '/hello_world',
191
- :headers => {},
192
- :params => {'foo' => 'bar'}
193
- })
194
- end
195
-
196
- it 'should use WebMock to stub the request' do
197
- stubbed_request.should_receive(:with).
198
- with({:query => request.params}).
199
- and_return(stubbed_request)
200
- described_class.new(request, response).stub!
201
- end
202
- end
203
-
204
- context 'a request with no params' do
205
- let(:request) do
206
- double({
207
- :host => 'http://localhost',
208
- :method => :get,
209
- :path => '/hello_world',
210
- :headers => {},
211
- :params => {}
212
- })
213
- end
214
-
215
- it 'should use WebMock to stub the request' do
216
- stubbed_request.should_receive(:with).
217
- with({}).
218
- and_return(stubbed_request)
219
- described_class.new(request, response).stub!
220
- end
221
- end
222
- end
223
- end
224
- end
@@ -1,5 +0,0 @@
1
- # Enable Coveralls only on the CI environment
2
- if ENV['CI']
3
- require 'coveralls'
4
- Coveralls.wear!
5
- end