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.
- data/.gitignore +3 -0
- data/.rspec +0 -2
- data/.rubocop-todo.yml +51 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +4 -2
- data/Guardfile +28 -14
- data/README.md +81 -51
- data/Rakefile +24 -11
- data/features/generation/generation.feature +25 -0
- data/features/journeys/validation.feature +74 -0
- data/features/support/env.rb +16 -0
- data/lib/pacto.rb +63 -34
- data/lib/pacto/contract.rb +25 -11
- data/lib/pacto/contract_factory.rb +13 -44
- data/lib/pacto/core/callback.rb +11 -0
- data/lib/pacto/core/configuration.rb +34 -0
- data/lib/pacto/core/contract_repository.rb +44 -0
- data/lib/pacto/erb_processor.rb +18 -0
- data/lib/pacto/exceptions/invalid_contract.rb +10 -1
- data/lib/pacto/extensions.rb +2 -2
- data/lib/pacto/generator.rb +75 -0
- data/lib/pacto/hash_merge_processor.rb +14 -0
- data/lib/pacto/hooks/erb_hook.rb +17 -0
- data/lib/pacto/logger.rb +42 -0
- data/lib/pacto/meta_schema.rb +17 -0
- data/lib/pacto/rake_task.rb +75 -12
- data/lib/pacto/request.rb +3 -4
- data/lib/pacto/response.rb +27 -19
- data/lib/pacto/server.rb +2 -0
- data/lib/pacto/server/dummy.rb +45 -0
- data/lib/pacto/server/playback_servlet.rb +21 -0
- data/lib/pacto/stubs/built_in.rb +57 -0
- data/lib/pacto/version.rb +1 -1
- data/pacto.gemspec +8 -2
- data/resources/contract_schema.json +216 -0
- data/spec/coveralls_helper.rb +10 -0
- data/spec/integration/data/strict_contract.json +33 -0
- data/spec/integration/data/templating_contract.json +25 -0
- data/spec/integration/e2e_spec.rb +40 -7
- data/spec/integration/templating_spec.rb +55 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/unit/data/simple_contract.json +22 -0
- data/spec/unit/hooks/erb_hook_spec.rb +51 -0
- data/spec/unit/pacto/configuration_spec.rb +51 -0
- data/spec/unit/pacto/contract_factory_spec.rb +4 -35
- data/spec/unit/pacto/contract_spec.rb +59 -31
- data/spec/unit/pacto/core/configuration_spec.rb +28 -0
- data/spec/unit/pacto/core/contract_repository_spec.rb +133 -0
- data/spec/unit/pacto/erb_processor_spec.rb +23 -0
- data/spec/unit/pacto/extensions_spec.rb +11 -11
- data/spec/unit/pacto/generator_spec.rb +142 -0
- data/spec/unit/pacto/hash_merge_processor_spec.rb +20 -0
- data/spec/unit/pacto/logger_spec.rb +44 -0
- data/spec/unit/pacto/meta_schema_spec.rb +70 -0
- data/spec/unit/pacto/pacto_spec.rb +32 -58
- data/spec/unit/pacto/request_spec.rb +83 -34
- data/spec/unit/pacto/response_adapter_spec.rb +9 -11
- data/spec/unit/pacto/response_spec.rb +68 -68
- data/spec/unit/pacto/server/playback_servlet_spec.rb +24 -0
- data/spec/unit/pacto/stubs/built_in_spec.rb +168 -0
- metadata +291 -147
- data/.rspec_integration +0 -4
- data/.rspec_unit +0 -4
- data/lib/pacto/file_pre_processor.rb +0 -12
- data/lib/pacto/instantiated_contract.rb +0 -62
- data/spec/integration/spec_helper.rb +0 -1
- data/spec/integration/utils/dummy_server.rb +0 -34
- data/spec/unit/pacto/file_pre_processor_spec.rb +0 -13
- data/spec/unit/pacto/instantiated_contract_spec.rb +0 -224
- data/spec/unit/spec_helper.rb +0 -5
data/.rspec_integration
DELETED
data/.rspec_unit
DELETED
@@ -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
|