rest-assured 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/Gemfile +2 -0
- data/README.markdown +9 -8
- data/features/rest_api/doubles.feature +1 -0
- data/features/step_definitions/ruby_api_steps.rb +1 -1
- data/lib/rest-assured/models/double.rb +1 -1
- data/lib/rest-assured/routes/response.rb +21 -11
- data/lib/rest-assured/utils/subprocess.rb +1 -10
- data/lib/rest-assured/version.rb +1 -1
- data/rest-assured.gemspec +3 -4
- data/spec/functional/response_spec.rb +13 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/subprocess_spec.rb +1 -29
- metadata +18 -30
- data/lib/active_record/leaky_connections_patch.rb +0 -55
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -27,8 +27,8 @@ It is also recommended to have thin installed. This improves startup time (over
|
|
27
27
|
|
28
28
|
Then install gem and run:
|
29
29
|
|
30
|
-
bash$ gem install rest-assured
|
31
|
-
bash$ rest-assured
|
30
|
+
bash$ gem install rest-assured
|
31
|
+
bash$ rest-assured &
|
32
32
|
|
33
33
|
Or clone from github and run:
|
34
34
|
|
@@ -40,8 +40,6 @@ This starts up an instance of rest-assured on port 4578. It is accessible via RE
|
|
40
40
|
|
41
41
|
Various options (such as ssl, port, db credentials, etc.) are available through command line options. Check out `rest-assured -h` to see what they are.
|
42
42
|
|
43
|
-
NOTE that although sqlite is an extremely handy option (especially with `-d :memory:`), I found it sometimes locking tables under non-trivial load. Hence there is a Plan B - mysql. But may be that is just me sqliting it wrong.
|
44
|
-
|
45
43
|
## Doubles
|
46
44
|
|
47
45
|
Double is a stub/spy of HTTP request. Create a double that has the same request fullpath and method as the one your app is sending to a dependant service and then convience your app that rest-assured is that dependency (hint: by making endpoints configurable).
|
@@ -171,7 +169,7 @@ For those using rest-assured from non-ruby environments.
|
|
171
169
|
|
172
170
|
It is sometimes desirable to only double certain calls while letting others through to the "real" services. Meet Redirects. Kind of "rewrite rules" for requests that didn't match any double.
|
173
171
|
|
174
|
-
Another
|
172
|
+
Another use for redirects is setting up a "default" double that matches multiple fullpaths. If a redirect pattern matches a defined double then it will act like a double and respond directly. If it does not match a double then it will return HTTP 303 redirect instead. Note that HTTP redirects are usually converted to GET requests by HTTP clients.
|
175
173
|
|
176
174
|
Here is the rest API for managing redirects:
|
177
175
|
|
@@ -200,7 +198,11 @@ Here is the rest API for managing redirects:
|
|
200
198
|
|
201
199
|
## Changelog
|
202
200
|
|
203
|
-
#### 1.
|
201
|
+
#### 1.1.0 (17 Feb 2012)
|
202
|
+
|
203
|
+
* Redirects supports 'real' (without http redirect) rewrite to local double
|
204
|
+
|
205
|
+
#### 1.0.0 (14 Feb 2012)
|
204
206
|
|
205
207
|
* start/stop rest-assured via api
|
206
208
|
* redirects support pattern/replacement
|
@@ -211,8 +213,7 @@ Here is the rest API for managing redirects:
|
|
211
213
|
|
212
214
|
#### 0.3.1 (09 Jan 2012)
|
213
215
|
|
214
|
-
* lock rack version to <= 1.3.6 until they release fix for
|
215
|
-
https://github.com/rack/rack/issues/299
|
216
|
+
* lock rack version to <= 1.3.6 until they release fix for https://github.com/rack/rack/issues/299
|
216
217
|
|
217
218
|
#### 0.3 (12 Dec 2011)
|
218
219
|
|
@@ -15,6 +15,7 @@ Feature: use doubles via api
|
|
15
15
|
| /api/some | text content | GET | GET | 303 | 303 |
|
16
16
|
| /api/some?a=3&b=dd | more content | | GET | | 200 |
|
17
17
|
| /api/empty | | POST | POST | | 200 |
|
18
|
+
| /api/file | | HEAD | HEAD | | 200 |
|
18
19
|
|
19
20
|
Scenario: view created double details
|
20
21
|
When I create a double
|
@@ -55,7 +55,7 @@ Then /^it should wait for (#{CAPTURE_A_NUMBER}) seconds(?: \(default timeout\))?
|
|
55
55
|
wait_time = Time.now - @wait_start
|
56
56
|
#(timeout..(timeout+1)).should cover(wait_time) # cover() only avilable in 1.9
|
57
57
|
wait_time.should >= timeout
|
58
|
-
wait_time.should < timeout + 1
|
58
|
+
wait_time.should < timeout + 1.5
|
59
59
|
end
|
60
60
|
|
61
61
|
Then /^it should raise MoreRequestsExpected error after with the following message:$/ do |string|
|
@@ -1,23 +1,33 @@
|
|
1
1
|
module RestAssured
|
2
2
|
class Response
|
3
|
+
|
3
4
|
def self.perform(app)
|
4
5
|
request = app.request
|
5
|
-
|
6
6
|
if d = Models::Double.where(:fullpath => request.fullpath, :active => true, :verb => request.request_method).first
|
7
|
-
|
8
|
-
body = request.body.read #without temp variable ':body = > body' is always nil. mistery
|
9
|
-
env = request.env.except('rack.input', 'rack.errors', 'rack.logger')
|
10
|
-
|
11
|
-
d.requests.create!(:rack_env => env.to_json, :body => body, :params => request.params.to_json)
|
12
|
-
|
13
|
-
app.headers d.response_headers
|
14
|
-
app.body d.content
|
15
|
-
app.status d.status
|
7
|
+
return_double app, d
|
16
8
|
elsif redirect_url = Models::Redirect.find_redirect_url_for(request.fullpath)
|
17
|
-
|
9
|
+
if d = Models::Double.where(:fullpath => redirect_url, :active => true, :verb => request.request_method).first
|
10
|
+
return_double app, d
|
11
|
+
else
|
12
|
+
app.redirect redirect_url
|
13
|
+
end
|
18
14
|
else
|
19
15
|
app.status 404
|
20
16
|
end
|
21
17
|
end
|
18
|
+
|
19
|
+
def self.return_double(app, d)
|
20
|
+
request = app.request
|
21
|
+
request.body.rewind
|
22
|
+
body = request.body.read #without temp variable ':body = > body' is always nil. mistery
|
23
|
+
env = request.env.except('rack.input', 'rack.errors', 'rack.logger')
|
24
|
+
|
25
|
+
d.requests.create!(:rack_env => env.to_json, :body => body, :params => request.params.to_json)
|
26
|
+
|
27
|
+
app.headers d.response_headers
|
28
|
+
app.body d.content
|
29
|
+
app.status d.status
|
30
|
+
end
|
31
|
+
|
22
32
|
end
|
23
33
|
end
|
@@ -6,19 +6,10 @@ module RestAssured
|
|
6
6
|
def initialize
|
7
7
|
@pid = Kernel.fork do
|
8
8
|
trap('USR1') do
|
9
|
-
$stopped = true
|
10
9
|
Process.kill('TERM', Process.pid) # unlike 'exit' this one is NOT being intercepted by Webrick
|
11
10
|
end
|
12
11
|
|
13
|
-
at_exit
|
14
|
-
if $stopped
|
15
|
-
puts "Being stopped from parent..."
|
16
|
-
#else
|
17
|
-
#puts "Shutting down parent..."
|
18
|
-
#Process.kill('TERM', Process.ppid)
|
19
|
-
end
|
20
|
-
exit!
|
21
|
-
end
|
12
|
+
at_exit { exit! }
|
22
13
|
|
23
14
|
begin
|
24
15
|
yield
|
data/lib/rest-assured/version.rb
CHANGED
data/rest-assured.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ['Artem Avetisyan']
|
10
10
|
s.email = ['artem.avetisyan@bbc.co.uk']
|
11
11
|
s.homepage = "https://github.com/BBC/rest-assured"
|
12
|
-
s.summary = %q{
|
12
|
+
s.summary = %q{Real stubs and spies for HTTP(S) services}
|
13
13
|
#s.description = %q{TODO: Write a gem description}
|
14
14
|
|
15
15
|
s.rubyforge_project = "rest-assured"
|
@@ -20,9 +20,8 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.executables = ['rest-assured']
|
21
21
|
s.require_paths = ['lib']
|
22
22
|
|
23
|
-
s.add_dependency 'sinatra', '>= 1.3.
|
24
|
-
s.add_dependency '
|
25
|
-
s.add_dependency 'childprocess', '~> 0.2.8'
|
23
|
+
s.add_dependency 'sinatra', '>= 1.3.2'
|
24
|
+
s.add_dependency 'childprocess', '~> 0.3.0'
|
26
25
|
s.add_dependency 'sinatra-flash'
|
27
26
|
s.add_dependency 'haml', '>= 3.1.3'
|
28
27
|
s.add_dependency 'activerecord', '~> 3.1.0'
|
@@ -60,6 +60,19 @@ module RestAssured
|
|
60
60
|
|
61
61
|
Response.perform(rest_assured_app)
|
62
62
|
end
|
63
|
+
|
64
|
+
it "returns double when redirect matches double" do
|
65
|
+
fullpath = '/some/other/path'
|
66
|
+
request.stub(:fullpath).and_return(fullpath)
|
67
|
+
Models::Redirect.stub(:find_redirect_url_for).with(fullpath).and_return('/some/path')
|
68
|
+
|
69
|
+
rest_assured_app.should_receive(:body).with(@double.content)
|
70
|
+
rest_assured_app.should_receive(:status).with(@double.status)
|
71
|
+
rest_assured_app.should_receive(:headers).with(@double.response_headers)
|
72
|
+
|
73
|
+
Response.perform(rest_assured_app)
|
74
|
+
end
|
75
|
+
|
63
76
|
end
|
64
77
|
|
65
78
|
it "redirects if double not hit but there is redirect that matches request" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,17 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
|
3
|
+
if RUBY_VERSION =~ /^1.9/
|
4
|
+
begin
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.start do
|
7
|
+
at_exit {} # reset built in at_exit or else it gets triggered when RestAssured::Server.stop is called from tests
|
8
|
+
add_filter "/spec/"
|
9
|
+
add_filter "/sinatra/"
|
10
|
+
end
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
2
15
|
require 'spork'
|
3
16
|
|
4
17
|
$:.unshift(File.expand_path('../../lib'), __FILE__)
|
@@ -44,6 +57,12 @@ Spork.prefork do
|
|
44
57
|
c.before(:each, :ui => false) do
|
45
58
|
header 'User-Agent', nil
|
46
59
|
end
|
60
|
+
|
61
|
+
if defined?(SimpleCov)
|
62
|
+
c.after(:suite) do
|
63
|
+
SimpleCov.result.format!
|
64
|
+
end
|
65
|
+
end
|
47
66
|
end
|
48
67
|
require 'rest-assured/config'
|
49
68
|
db_opts = { :dbuser => ENV['TRAVIS'] ? "''" : "root", :adapter => 'mysql' }
|
data/spec/subprocess_spec.rb
CHANGED
@@ -43,35 +43,6 @@ module RestAssured::Utils
|
|
43
43
|
res_file.read.should == 'true'
|
44
44
|
end
|
45
45
|
|
46
|
-
# I am not sure this is actually useful
|
47
|
-
#describe 'commits seppuku' do
|
48
|
-
#it 'if child raises exception' do
|
49
|
-
#res_file = Tempfile.new('res')
|
50
|
-
#fork do
|
51
|
-
#at_exit { exit! }
|
52
|
-
#Subprocess.new { raise "!!NO PANIC!! This exception is part of test"; sleep 1 }
|
53
|
-
#sleep 0.5
|
54
|
-
#res_file.write('should not exist because this process should be killed by now')
|
55
|
-
#res_file.rewind
|
56
|
-
#end
|
57
|
-
#Process.wait
|
58
|
-
#res_file.read.should == ''
|
59
|
-
#end
|
60
|
-
|
61
|
-
#it 'if child just quits' do
|
62
|
-
#res_file = Tempfile.new('res')
|
63
|
-
#fork do
|
64
|
-
#at_exit { exit! }
|
65
|
-
#Subprocess.new { 1 }
|
66
|
-
#sleep 0.5
|
67
|
-
#res_file.write('should not exist because this process should be killed by now')
|
68
|
-
#res_file.rewind
|
69
|
-
#end
|
70
|
-
#Process.wait
|
71
|
-
#res_file.read.should == ''
|
72
|
-
#end
|
73
|
-
#end
|
74
|
-
|
75
46
|
context 'shuts down child process' do
|
76
47
|
let(:child_pid) do
|
77
48
|
Tempfile.new('child_pid')
|
@@ -97,6 +68,7 @@ module RestAssured::Utils
|
|
97
68
|
res_file.rewind
|
98
69
|
end
|
99
70
|
Process.wait
|
71
|
+
sleep 0.5
|
100
72
|
res_file.read.should == 'false'
|
101
73
|
end
|
102
74
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-assured
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,44 +9,33 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: &
|
16
|
+
requirement: &2168491020 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.3.
|
21
|
+
version: 1.3.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: rack
|
27
|
-
requirement: &2154191300 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
|
-
requirements:
|
30
|
-
- - <=
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.3.6
|
33
|
-
type: :runtime
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: *2154191300
|
24
|
+
version_requirements: *2168491020
|
36
25
|
- !ruby/object:Gem::Dependency
|
37
26
|
name: childprocess
|
38
|
-
requirement: &
|
27
|
+
requirement: &2168528060 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
29
|
requirements:
|
41
30
|
- - ~>
|
42
31
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.
|
32
|
+
version: 0.3.0
|
44
33
|
type: :runtime
|
45
34
|
prerelease: false
|
46
|
-
version_requirements: *
|
35
|
+
version_requirements: *2168528060
|
47
36
|
- !ruby/object:Gem::Dependency
|
48
37
|
name: sinatra-flash
|
49
|
-
requirement: &
|
38
|
+
requirement: &2168523560 !ruby/object:Gem::Requirement
|
50
39
|
none: false
|
51
40
|
requirements:
|
52
41
|
- - ! '>='
|
@@ -54,10 +43,10 @@ dependencies:
|
|
54
43
|
version: '0'
|
55
44
|
type: :runtime
|
56
45
|
prerelease: false
|
57
|
-
version_requirements: *
|
46
|
+
version_requirements: *2168523560
|
58
47
|
- !ruby/object:Gem::Dependency
|
59
48
|
name: haml
|
60
|
-
requirement: &
|
49
|
+
requirement: &2168565440 !ruby/object:Gem::Requirement
|
61
50
|
none: false
|
62
51
|
requirements:
|
63
52
|
- - ! '>='
|
@@ -65,10 +54,10 @@ dependencies:
|
|
65
54
|
version: 3.1.3
|
66
55
|
type: :runtime
|
67
56
|
prerelease: false
|
68
|
-
version_requirements: *
|
57
|
+
version_requirements: *2168565440
|
69
58
|
- !ruby/object:Gem::Dependency
|
70
59
|
name: activerecord
|
71
|
-
requirement: &
|
60
|
+
requirement: &2168564340 !ruby/object:Gem::Requirement
|
72
61
|
none: false
|
73
62
|
requirements:
|
74
63
|
- - ~>
|
@@ -76,10 +65,10 @@ dependencies:
|
|
76
65
|
version: 3.1.0
|
77
66
|
type: :runtime
|
78
67
|
prerelease: false
|
79
|
-
version_requirements: *
|
68
|
+
version_requirements: *2168564340
|
80
69
|
- !ruby/object:Gem::Dependency
|
81
70
|
name: activeresource
|
82
|
-
requirement: &
|
71
|
+
requirement: &2168563340 !ruby/object:Gem::Requirement
|
83
72
|
none: false
|
84
73
|
requirements:
|
85
74
|
- - ~>
|
@@ -87,7 +76,7 @@ dependencies:
|
|
87
76
|
version: 3.1.0
|
88
77
|
type: :runtime
|
89
78
|
prerelease: false
|
90
|
-
version_requirements: *
|
79
|
+
version_requirements: *2168563340
|
91
80
|
description:
|
92
81
|
email:
|
93
82
|
- artem.avetisyan@bbc.co.uk
|
@@ -137,7 +126,6 @@ files:
|
|
137
126
|
- features/support/world_helpers.rb
|
138
127
|
- features/web_ui/doubles.feature
|
139
128
|
- features/web_ui/redirects.feature
|
140
|
-
- lib/active_record/leaky_connections_patch.rb
|
141
129
|
- lib/rest-assured.rb
|
142
130
|
- lib/rest-assured/api.rb
|
143
131
|
- lib/rest-assured/api/app_runner.rb
|
@@ -223,13 +211,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
223
211
|
version: '0'
|
224
212
|
segments:
|
225
213
|
- 0
|
226
|
-
hash:
|
214
|
+
hash: 1944321672567783063
|
227
215
|
requirements: []
|
228
216
|
rubyforge_project: rest-assured
|
229
217
|
rubygems_version: 1.8.10
|
230
218
|
signing_key:
|
231
219
|
specification_version: 3
|
232
|
-
summary:
|
220
|
+
summary: Real stubs and spies for HTTP(S) services
|
233
221
|
test_files:
|
234
222
|
- features/command_line_options.feature
|
235
223
|
- features/rest_api/doubles.feature
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# fix leaking db connections https://github.com/rails/rails/commit/ea341b8e043160a7ddaba9e6b2bb6044f73c31a8
|
2
|
-
# TODO remove with the next ActiveRecord update as this patch will be there
|
3
|
-
module ActiveRecord
|
4
|
-
class ConnectionAdapters::ConnectionPool
|
5
|
-
def current_connection_id #:nodoc:
|
6
|
-
ActiveRecord::Base.connection_id ||= Thread.current.object_id
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
class Base::ConnectionSpecification
|
11
|
-
class << self
|
12
|
-
def connection_id
|
13
|
-
Thread.current['ActiveRecord::Base.connection_id']
|
14
|
-
end
|
15
|
-
|
16
|
-
def connection_id=(connection_id)
|
17
|
-
Thread.current['ActiveRecord::Base.connection_id'] = connection_id
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class QueryCache
|
23
|
-
class BodyProxy
|
24
|
-
def initialize(original_cache_value, target, connection_id)
|
25
|
-
@original_cache_value = original_cache_value
|
26
|
-
@target = target
|
27
|
-
@connection_id = connection_id
|
28
|
-
end
|
29
|
-
|
30
|
-
def close
|
31
|
-
@target.close if @target.respond_to?(:close)
|
32
|
-
ensure
|
33
|
-
ActiveRecord::Base.connection_id = @connection_id
|
34
|
-
ActiveRecord::Base.connection.clear_query_cache
|
35
|
-
unless @original_cache_value
|
36
|
-
ActiveRecord::Base.connection.disable_query_cache!
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def call(env)
|
42
|
-
old = ActiveRecord::Base.connection.query_cache_enabled
|
43
|
-
ActiveRecord::Base.connection.enable_query_cache!
|
44
|
-
|
45
|
-
status, headers, body = @app.call(env)
|
46
|
-
[status, headers, BodyProxy.new(old, body, ActiveRecord::Base.connection_id)]
|
47
|
-
rescue Exception => e
|
48
|
-
ActiveRecord::Base.connection.clear_query_cache
|
49
|
-
unless old
|
50
|
-
ActiveRecord::Base.connection.disable_query_cache!
|
51
|
-
end
|
52
|
-
raise e
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|