rest-assured 0.2.0.rc8 → 0.2.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/Gemfile.lock +2 -2
- data/LICENSE +4 -19
- data/README.markdown +123 -36
- data/bin/console +1 -2
- data/bin/rest-assured +12 -0
- data/features/command_line_options.feature +20 -1
- data/features/{doubles_via_api.feature → rest_api/doubles.feature} +0 -0
- data/features/{redirect_rules_via_api.feature → rest_api/redirects.feature} +11 -8
- data/features/{call_history.feature → ruby_api/verify_requests.feature} +0 -0
- data/features/ruby_api/wait_for_requests.feature +39 -0
- data/features/step_definitions/command_line_options_steps.rb +12 -0
- data/features/step_definitions/doubles_steps.rb +10 -10
- data/features/step_definitions/redirect_rules_steps.rb +24 -5
- data/features/step_definitions/ruby_api_steps.rb +69 -0
- data/features/support/env.rb +3 -1
- data/features/{doubles_via_ui.feature → web_ui/doubles.feature} +0 -0
- data/features/{redirect_rules_via_ui.feature → web_ui/redirects.feature} +0 -0
- data/lib/rest-assured.rb +2 -1
- data/lib/rest-assured/client/resources.rb +12 -2
- data/lib/rest-assured/config.rb +24 -0
- data/lib/rest-assured/models/double.rb +32 -28
- data/lib/rest-assured/models/redirect.rb +28 -24
- data/lib/rest-assured/models/request.rb +11 -7
- data/lib/rest-assured/routes/double.rb +8 -8
- data/lib/rest-assured/routes/redirect.rb +8 -8
- data/lib/rest-assured/routes/response.rb +16 -14
- data/lib/rest-assured/version.rb +1 -1
- data/lib/sinatra/handler_options_patch.rb +25 -0
- data/spec/client/resource_double_spec.rb +42 -6
- data/spec/config_spec.rb +35 -0
- data/spec/functional/double_routes_spec.rb +109 -107
- data/spec/functional/redirect_routes_spec.rb +86 -75
- data/spec/functional/response_spec.rb +57 -55
- data/spec/models/double_spec.rb +67 -65
- data/spec/models/redirect_spec.rb +28 -26
- data/spec/models/request_spec.rb +10 -8
- data/ssl/localhost.crt +14 -0
- data/ssl/localhost.key +15 -0
- metadata +25 -24
- data/features/step_definitions/call_history_steps.rb +0 -24
@@ -1,16 +1,20 @@
|
|
1
1
|
Given /^there are no redirect rules$/ do
|
2
|
-
Redirect.destroy_all
|
2
|
+
RestAssured::Models::Redirect.destroy_all
|
3
3
|
end
|
4
4
|
|
5
5
|
Then /^I should get (\d+)$/ do |code|
|
6
6
|
last_response.status.should.to_s == code
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
post '/redirects', { :pattern => pattern, :to =>
|
9
|
+
Given /^there is redirect with pattern "([^"]*)" and uri "([^"]*)"$/ do |pattern, url|
|
10
|
+
post '/redirects', { :pattern => pattern, :to => url }
|
11
11
|
last_response.should be_ok
|
12
12
|
end
|
13
13
|
|
14
|
+
When /^I register redirect with pattern "([^"]*)" and uri "([^"]*)"$/ do |pattern, url|
|
15
|
+
Given %{there is redirect with pattern "#{pattern}" and uri "#{url}"}
|
16
|
+
end
|
17
|
+
|
14
18
|
Then /^it should redirect to "([^"]*)"$/ do |real_api_url|
|
15
19
|
follow_redirect!
|
16
20
|
last_response.header['Location'].should == real_api_url
|
@@ -18,7 +22,7 @@ end
|
|
18
22
|
|
19
23
|
Given /^the following redirects exist:$/ do |redirects|
|
20
24
|
redirects.hashes.each do |row|
|
21
|
-
Redirect.create(:pattern => row['pattern'], :to => row['to'])
|
25
|
+
RestAssured::Models::Redirect.create(:pattern => row['pattern'], :to => row['to'])
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
@@ -50,7 +54,7 @@ Given /^I choose to delete redirect with pattern "([^"]*)"$/ do |pattern|
|
|
50
54
|
end
|
51
55
|
|
52
56
|
When /^I reorder second redirect to be the first one$/ do
|
53
|
-
handler = find("#redirects #redirect_#{Redirect.last.id} td.handle")
|
57
|
+
handler = find("#redirects #redirect_#{RestAssured::Models::Redirect.last.id} td.handle")
|
54
58
|
target = find('#redirects thead')
|
55
59
|
|
56
60
|
handler.drag_to target
|
@@ -64,3 +68,18 @@ Then /^"([^"]*)" should be redirected to "([^"]*)"$/ do |missing_request, url|
|
|
64
68
|
|
65
69
|
last_request.url.should == "#{url}#{missing_request}"
|
66
70
|
end
|
71
|
+
|
72
|
+
Given /^blank slate$/ do
|
73
|
+
end
|
74
|
+
|
75
|
+
Given /^there are some redirects$/ do
|
76
|
+
RestAssured::Models::Redirect.create(:pattern => 'something', :to => 'somewhere')
|
77
|
+
end
|
78
|
+
|
79
|
+
When /^I delete all redirects$/ do
|
80
|
+
delete '/redirects/all'
|
81
|
+
end
|
82
|
+
|
83
|
+
Then /^there should be no redirects$/ do
|
84
|
+
RestAssured::Models::Redirect.count.should == 0
|
85
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
Given /^there is a double$/ do
|
2
|
+
@double = RestAssured::Double.create(:fullpath => '/some/path', :content => 'some content', :verb => 'POST')
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^that double gets requested$/ do
|
6
|
+
post @double.fullpath, { :foo => 'bar' }.to_json, "CONTENT_TYPE" => "application/json"
|
7
|
+
post @double.fullpath, { :fooz => 'baaz'}, 'SOME_HEADER' => 'header_data'
|
8
|
+
end
|
9
|
+
|
10
|
+
When /^I request call history for that double$/ do
|
11
|
+
@requests = @double.reload.requests
|
12
|
+
end
|
13
|
+
|
14
|
+
Then /^I should see history records for those requests$/ do
|
15
|
+
@requests.first.body.should == { :foo => 'bar' }.to_json
|
16
|
+
JSON.parse( @requests.first.rack_env )["CONTENT_TYPE"].should == 'application/json'
|
17
|
+
|
18
|
+
JSON.parse( @requests.last.params ).should == { 'fooz' => 'baaz' }
|
19
|
+
JSON.parse( @requests.last.rack_env )["SOME_HEADER"].should == 'header_data'
|
20
|
+
end
|
21
|
+
|
22
|
+
Then /^it should be empty$/ do
|
23
|
+
@requests.size.should == 0
|
24
|
+
end
|
25
|
+
|
26
|
+
Given /^I created a double:$/ do |string|
|
27
|
+
# expected string is:
|
28
|
+
# @double = RestAssured::Double.create(:fullpath => '/some/api', :verb => 'POST')
|
29
|
+
eval string
|
30
|
+
end
|
31
|
+
|
32
|
+
When /^that double gets requested (#{CAPTURE_A_NUMBER}) times$/ do |num|
|
33
|
+
num.times do
|
34
|
+
sleep 0.5
|
35
|
+
send(@double.verb.downcase, @double.fullpath)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
When /^I wait for (\d+) requests:$/ do |num, string|
|
40
|
+
# expected string
|
41
|
+
# @double.wait_for_requests(3)
|
42
|
+
|
43
|
+
@wait_start = Time.now
|
44
|
+
@t = Thread.new do
|
45
|
+
begin
|
46
|
+
eval string
|
47
|
+
rescue RestAssured::MoreRequestsExpected => e
|
48
|
+
@more_reqs_exc = e
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
Then /^it should let me through$/ do
|
54
|
+
@t.join
|
55
|
+
@more_reqs_exc.should == nil
|
56
|
+
end
|
57
|
+
|
58
|
+
Then /^it should wait for (#{CAPTURE_A_NUMBER}) seconds(?: \(default timeout\))?$/ do |timeout|
|
59
|
+
@t.join
|
60
|
+
wait_time = Time.now - @wait_start
|
61
|
+
#(timeout..(timeout+1)).should cover(wait_time) # cover() only avilable in 1.9
|
62
|
+
wait_time.should >= timeout
|
63
|
+
wait_time.should < timeout + 1
|
64
|
+
end
|
65
|
+
|
66
|
+
Then /^it should raise MoreRequestsExpected error after with the following message:$/ do |string|
|
67
|
+
@more_reqs_exc.should be_instance_of RestAssured::MoreRequestsExpected
|
68
|
+
@more_reqs_exc.message.should =~ /#{string}/
|
69
|
+
end
|
data/features/support/env.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rubygems'
|
|
3
3
|
require 'spork'
|
4
4
|
|
5
5
|
Spork.prefork do
|
6
|
-
require 'rspec
|
6
|
+
require 'rspec'
|
7
7
|
require 'rack/test'
|
8
8
|
require 'capybara'
|
9
9
|
require 'capybara/firebug'
|
@@ -77,6 +77,8 @@ Spork.each_run do
|
|
77
77
|
After do
|
78
78
|
sleep 0.1
|
79
79
|
DatabaseCleaner.clean
|
80
|
+
|
81
|
+
@t.join if @t.is_a?(Thread)
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
File without changes
|
File without changes
|
data/lib/rest-assured.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'sinatra/base'
|
3
|
+
require 'sinatra/handler_options_patch'
|
3
4
|
require 'haml'
|
4
5
|
require 'rack-flash'
|
5
6
|
require 'sinatra/partials'
|
@@ -14,7 +15,7 @@ require 'rest-assured/routes/response'
|
|
14
15
|
module RestAssured
|
15
16
|
class Application < Sinatra::Base
|
16
17
|
|
17
|
-
include
|
18
|
+
include Config
|
18
19
|
|
19
20
|
enable :method_override
|
20
21
|
|
@@ -1,8 +1,18 @@
|
|
1
1
|
require 'active_resource'
|
2
2
|
|
3
3
|
module RestAssured
|
4
|
-
|
5
|
-
|
4
|
+
class MoreRequestsExpected < StandardError; end
|
5
|
+
|
6
|
+
class Double < ActiveResource::Base
|
7
|
+
def wait_for_requests(n, opts = {})
|
8
|
+
timeout = opts[:timeout] || 5
|
9
|
+
|
10
|
+
timeout.times do
|
11
|
+
sleep 1
|
12
|
+
reload
|
13
|
+
return if requests.count >= n
|
14
|
+
end
|
15
|
+
raise MoreRequestsExpected.new("Expected #{n} requests. Got #{requests.count}.")
|
6
16
|
end
|
7
17
|
end
|
8
18
|
end
|
data/lib/rest-assured/config.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'active_record'
|
3
3
|
require 'active_support/core_ext/kernel/reporting'
|
4
|
+
require 'webrick'
|
5
|
+
require 'webrick/https'
|
4
6
|
|
5
7
|
module RestAssured
|
6
8
|
module Config
|
@@ -37,11 +39,13 @@ module RestAssured
|
|
37
39
|
File.expand_path("../../../#{AppConfig.environment}.log", __FILE__)
|
38
40
|
end
|
39
41
|
build_db_config
|
42
|
+
build_ssl_config
|
40
43
|
end
|
41
44
|
|
42
45
|
def self.included(klass)
|
43
46
|
init_logger
|
44
47
|
setup_db
|
48
|
+
setup_ssl(klass) if AppConfig.use_ssl
|
45
49
|
|
46
50
|
klass.set :port, AppConfig.port
|
47
51
|
klass.set :environment, AppConfig.environment
|
@@ -52,6 +56,19 @@ module RestAssured
|
|
52
56
|
|
53
57
|
private
|
54
58
|
|
59
|
+
def self.setup_ssl(klass)
|
60
|
+
ssl_config = {
|
61
|
+
:SSLEnable => true,
|
62
|
+
:SSLCertificate => OpenSSL::X509::Certificate.new( File.read( AppConfig.ssl_cert ) ),
|
63
|
+
:SSLPrivateKey => OpenSSL::PKey::RSA.new( File.read( AppConfig.ssl_key ) ),
|
64
|
+
:SSLCertName => [ ["CN", WEBrick::Utils::getservername] ],
|
65
|
+
:SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE
|
66
|
+
}
|
67
|
+
|
68
|
+
klass.set :server, %[webrick]
|
69
|
+
klass.set :webrick, ssl_config
|
70
|
+
end
|
71
|
+
|
55
72
|
def self.setup_db
|
56
73
|
setup_db_logging
|
57
74
|
connect_db
|
@@ -118,6 +135,7 @@ module RestAssured
|
|
118
135
|
opts = {
|
119
136
|
:adapter => 'mysql',
|
120
137
|
:reconnect => true,
|
138
|
+
:pool => 20,
|
121
139
|
:user => AppConfig.user || 'root',
|
122
140
|
:database => AppConfig.database || default_database
|
123
141
|
}
|
@@ -132,6 +150,12 @@ module RestAssured
|
|
132
150
|
raise "Unsupported db adapter '#{AppConfig.adapter}'. Valid adapters are sqlite and mysql"
|
133
151
|
end
|
134
152
|
end
|
153
|
+
|
154
|
+
def self.build_ssl_config
|
155
|
+
AppConfig.use_ssl ||= false
|
156
|
+
AppConfig.ssl_cert ||= File.expand_path('../../../ssl/localhost.crt', __FILE__)
|
157
|
+
AppConfig.ssl_key ||= File.expand_path('../../../ssl/localhost.key', __FILE__)
|
158
|
+
end
|
135
159
|
end
|
136
160
|
end
|
137
161
|
|
@@ -1,43 +1,47 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module RestAssured
|
4
|
+
module Models
|
5
|
+
class Double < ActiveRecord::Base
|
6
|
+
attr_accessible :fullpath, :content, :description, :verb, :status
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
+
VERBS = %w{GET POST PUT DELETE}
|
9
|
+
STATUSES = Net::HTTPResponse::CODE_TO_OBJ.keys.map(&:to_i)
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
validates_presence_of :fullpath
|
12
|
+
validates_inclusion_of :verb, :in => VERBS
|
13
|
+
validates_inclusion_of :status, :in => STATUSES
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
before_save :toggle_active
|
16
|
+
before_validation :set_verb
|
17
|
+
before_validation :set_status
|
18
|
+
after_destroy :set_active
|
17
19
|
|
18
|
-
|
20
|
+
has_many :requests, :dependent => :destroy
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
private
|
23
|
+
def toggle_active
|
24
|
+
ne = id ? '!=' : 'IS NOT'
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
+
if active && Double.where("fullpath = ? AND active = ? AND id #{ne} ?", fullpath, true, id).exists?
|
27
|
+
Double.where("fullpath = ? AND id #{ne} ?", fullpath, id).update_all :active => false
|
28
|
+
end
|
26
29
|
end
|
27
|
-
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
def set_verb
|
32
|
+
self.verb = 'GET' unless verb.present?
|
33
|
+
end
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
def set_status
|
36
|
+
self.status = 200 unless status.present?
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
def set_active
|
40
|
+
if active && f = Double.where(:fullpath => fullpath).last
|
41
|
+
f.active = true
|
42
|
+
f.save
|
43
|
+
end
|
41
44
|
end
|
42
45
|
end
|
46
|
+
end
|
43
47
|
end
|
@@ -1,35 +1,39 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module RestAssured
|
2
|
+
module Models
|
3
|
+
class Redirect < ActiveRecord::Base
|
4
|
+
attr_accessible :pattern, :to, :position
|
3
5
|
|
4
|
-
|
6
|
+
validates_presence_of :pattern, :to
|
5
7
|
|
6
|
-
|
8
|
+
scope :ordered, order('position')
|
7
9
|
|
8
|
-
|
10
|
+
before_create :assign_position
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
def self.update_order(ordered_redirect_ids)
|
13
|
+
success = true
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
transaction do
|
16
|
+
begin
|
17
|
+
ordered_redirect_ids.each_with_index do |r_id, idx|
|
18
|
+
r = find(r_id)
|
19
|
+
r.position = idx
|
20
|
+
r.save!
|
21
|
+
end
|
22
|
+
rescue => e
|
23
|
+
# TODO log exception
|
24
|
+
puts e.inspect
|
25
|
+
success = false
|
26
|
+
raise ActiveRecord::Rollback
|
27
|
+
end
|
19
28
|
end
|
20
|
-
|
21
|
-
# TODO log exception
|
22
|
-
puts e.inspect
|
23
|
-
success = false
|
24
|
-
raise ActiveRecord::Rollback
|
29
|
+
success
|
25
30
|
end
|
26
|
-
end
|
27
|
-
success
|
28
|
-
end
|
29
31
|
|
30
|
-
|
32
|
+
private
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
def assign_position
|
35
|
+
self.position = ( self.class.maximum(:position) || -1 ) + 1
|
36
|
+
end
|
34
37
|
end
|
38
|
+
end
|
35
39
|
end
|
@@ -1,12 +1,16 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module RestAssured
|
2
|
+
module Models
|
3
|
+
class Request < ActiveRecord::Base
|
4
|
+
belongs_to :double
|
3
5
|
|
4
|
-
|
6
|
+
validates_presence_of :rack_env
|
5
7
|
|
6
|
-
|
8
|
+
after_create :save_created_at
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
private
|
11
|
+
def save_created_at
|
12
|
+
self.created_at = Time.now
|
13
|
+
end
|
11
14
|
end
|
15
|
+
end
|
12
16
|
end
|
@@ -8,18 +8,18 @@ module RestAssured
|
|
8
8
|
end
|
9
9
|
|
10
10
|
router.get '/doubles' do
|
11
|
-
@doubles = Double.all
|
11
|
+
@doubles = Models::Double.all
|
12
12
|
haml :'doubles/index'
|
13
13
|
end
|
14
14
|
|
15
15
|
router.get '/doubles/new' do
|
16
|
-
@double = Double.new
|
16
|
+
@double = Models::Double.new
|
17
17
|
haml :'doubles/new'
|
18
18
|
end
|
19
19
|
|
20
20
|
router.get '/doubles/:id.json' do |id|
|
21
21
|
begin
|
22
|
-
double = Double.find(id)
|
22
|
+
double = Models::Double.find(id)
|
23
23
|
body double.to_json(:include => :requests)
|
24
24
|
rescue ActiveRecord::RecordNotFound
|
25
25
|
status 404
|
@@ -29,7 +29,7 @@ module RestAssured
|
|
29
29
|
router.post /^\/doubles(\.json)?$/ do |passes_json|
|
30
30
|
f = { :fullpath => params['fullpath'], :content => params['content'], :description => params['description'], :verb => params['verb'], :status => params['status'] }
|
31
31
|
|
32
|
-
@double = Double.create(passes_json ? JSON.parse(request.body.read)['double'] : ( params['double'] || f ))
|
32
|
+
@double = Models::Double.create(passes_json ? JSON.parse(request.body.read)['double'] : ( params['double'] || f ))
|
33
33
|
|
34
34
|
if browser?
|
35
35
|
if @double.errors.blank?
|
@@ -50,12 +50,12 @@ module RestAssured
|
|
50
50
|
end
|
51
51
|
|
52
52
|
router.get %r{/doubles/(\d+)/edit} do |id|
|
53
|
-
@double = Double.find(id)
|
53
|
+
@double = Models::Double.find(id)
|
54
54
|
haml :'doubles/edit'
|
55
55
|
end
|
56
56
|
|
57
57
|
router.put %r{/doubles/(\d+)} do |id|
|
58
|
-
@double = Double.find(id)
|
58
|
+
@double = Models::Double.find(id)
|
59
59
|
|
60
60
|
if request.xhr?
|
61
61
|
if params['active']
|
@@ -77,14 +77,14 @@ module RestAssured
|
|
77
77
|
end
|
78
78
|
|
79
79
|
router.delete %r{/doubles/(\d+)} do |id|
|
80
|
-
if Double.destroy(id)
|
80
|
+
if Models::Double.destroy(id)
|
81
81
|
flash[:notice] = 'Double deleted'
|
82
82
|
redirect '/doubles'
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
router.delete '/doubles/all' do
|
87
|
-
status Double.delete_all ? 200 : 500
|
87
|
+
status Models::Double.delete_all ? 200 : 500
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|