rest-assured 0.1.4 → 0.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +6 -6
- data/db/migrate/20111013122857_create_requests.rb +15 -0
- data/db/migrate/20111016174101_rename_method_to_verb.rb +9 -0
- data/features/call_history.feature +16 -0
- data/features/doubles_via_api.feature +6 -6
- data/features/step_definitions/call_history_steps.rb +24 -0
- data/features/step_definitions/doubles_steps.rb +9 -8
- data/features/support/env.rb +16 -0
- data/features/support/test-server.rb +46 -0
- data/lib/rest-assured.rb +5 -17
- data/lib/rest-assured/client.rb +17 -0
- data/lib/rest-assured/client/double.rb +9 -0
- data/lib/rest-assured/client/resources.rb +7 -0
- data/lib/rest-assured/models/double.rb +7 -5
- data/lib/rest-assured/models/request.rb +12 -0
- data/lib/rest-assured/routes/double.rb +19 -5
- data/lib/rest-assured/routes/response.rb +17 -0
- data/lib/rest-assured/version.rb +1 -1
- data/rest-assured.gemspec +1 -1
- data/spec/client/resource_double_spec.rb +44 -0
- data/spec/functional/double_routes_spec.rb +35 -3
- data/spec/functional/response_spec.rb +56 -0
- data/spec/models/double_spec.rb +6 -5
- data/spec/models/request_spec.rb +15 -0
- data/spec/spec_helper.rb +18 -2
- metadata +46 -9
data/README.markdown
CHANGED
@@ -28,20 +28,20 @@ This starts an instance of rest-assured on port 4578 (changable with --port opti
|
|
28
28
|
|
29
29
|
Double is a stub/mock of a particular external call. There is the following rest API for setting up doubles:
|
30
30
|
|
31
|
-
* `POST '/doubles', { fullpath: path, content: content,
|
31
|
+
* `POST '/doubles', { fullpath: path, content: content, verb: verb }`
|
32
32
|
Creates double with the following parameters:
|
33
33
|
|
34
34
|
- __fullpath__ - e.g., `/some/api/object`, or with parameters in query string (useful for doubling GETs) - `/some/other/api/object?a=2&b=c`. Mandatory.
|
35
35
|
- __content__ - whatever you want this double to respond with. Mandatory.
|
36
|
-
-
|
36
|
+
- __verb__ - one of http the following http verbs: GET, POST, PUT, DELETE. Optional. GET is default.
|
37
37
|
|
38
38
|
Example (using ruby RestClient):
|
39
39
|
|
40
|
-
RestClient.post 'http://localhost:4578
|
40
|
+
RestClient.post 'http://localhost:4578/doubles', { fullpath: '/api/v2/products?type=fresh', verb: 'GET', content: 'this is list of products' }
|
41
41
|
|
42
42
|
Now GETting http://localhost:4578/api/v2/products?type=fresh (in browser for instance) should return "this is list of products".
|
43
43
|
|
44
|
-
If there is more than one double for the same request\_fullpath and
|
44
|
+
If there is more than one double for the same request\_fullpath and verb, the last created one gets served. In UI you can manually control which double is 'active' (gets served).
|
45
45
|
|
46
46
|
* `DELETE '/doubles/all'`
|
47
47
|
Deletes all doubles.
|
@@ -59,7 +59,7 @@ It is sometimes desirable to only double certain calls while letting others thro
|
|
59
59
|
|
60
60
|
RestClient.post 'http://localhost:4578/redirects', { pattern: '^/auth', to: 'https://myserver.com/api' }
|
61
61
|
|
62
|
-
Now request (any
|
62
|
+
Now request (any verb) to http://localhost:4578/auth/services/1 will get redirected to https://myserver.com/api/auth/services/1. Provided of course there is no double matched for that fullpath and verb.
|
63
63
|
Much like rewrite rules, redirects are evaluated in order (of creation). In UI you can manually rearrange the order.
|
64
64
|
|
65
65
|
### Storage
|
@@ -75,7 +75,7 @@ It is sometimes useful to see what requests rest-assured is being hit. Either to
|
|
75
75
|
* Implement expectations
|
76
76
|
* Support headers (extends previous point)
|
77
77
|
* Ruby client library
|
78
|
-
* Support
|
78
|
+
* Support verbs in UI (at the moment it is always GET)
|
79
79
|
* Don't allow to double internal routes. Just in case
|
80
80
|
|
81
81
|
## Author
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateRequests < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :requests do |t|
|
4
|
+
t.integer :double_id
|
5
|
+
t.text :params
|
6
|
+
t.text :body
|
7
|
+
t.text :rack_env
|
8
|
+
t.datetime :created_at
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :requests
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Feature: check double's call history
|
2
|
+
In order to verify outcomes of my app that take form of http requests
|
3
|
+
As test developer
|
4
|
+
I want to be able to get double 'call history'
|
5
|
+
|
6
|
+
Scenario: no calls made to double
|
7
|
+
Given there is a double
|
8
|
+
When I request call history for that double
|
9
|
+
Then it should be empty
|
10
|
+
|
11
|
+
@now
|
12
|
+
Scenario: some calls made to double
|
13
|
+
Given there is a double
|
14
|
+
When that double gets requested
|
15
|
+
And I request call history for that double
|
16
|
+
Then I should see history records for those requests
|
@@ -4,11 +4,11 @@ Feature: use doubles via api
|
|
4
4
|
I want to mock rest services my app is consuming from
|
5
5
|
|
6
6
|
Scenario Outline: create double
|
7
|
-
When I create a double with "<fullpath>" as fullpath, "<content>" as response content and "<
|
8
|
-
Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content and "<
|
7
|
+
When I create a double with "<fullpath>" as fullpath, "<content>" as response content and "<verb>" as request verb
|
8
|
+
Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content and "<result_verb>" as request verb
|
9
9
|
|
10
10
|
Examples:
|
11
|
-
| fullpath | content |
|
11
|
+
| fullpath | content | verb | result_verb |
|
12
12
|
| /api/something | created | POST | POST |
|
13
13
|
| /api/sss | changed | PUT | PUT |
|
14
14
|
| /api/asdfsf | removed | DELETE | DELETE |
|
@@ -16,12 +16,12 @@ Feature: use doubles via api
|
|
16
16
|
| /api/some?a=3&b=dd | more content | | GET |
|
17
17
|
|
18
18
|
Scenario Outline: request fullpath that matches double
|
19
|
-
Given there is double with "<fullpath>" as fullpath, "<content>" as response content and "<
|
20
|
-
When I "<
|
19
|
+
Given there is double with "<fullpath>" as fullpath, "<content>" as response content and "<verb>" as request verb
|
20
|
+
When I "<verb>" "<fullpath>"
|
21
21
|
Then I should get "<content>" in response content
|
22
22
|
|
23
23
|
Examples:
|
24
|
-
| fullpath | content |
|
24
|
+
| fullpath | content | verb |
|
25
25
|
| /api/something | created | POST |
|
26
26
|
| /api/sss | changed | PUT |
|
27
27
|
| /api/asdfsf | removed | DELETE |
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Given /^there is a double$/ do
|
2
|
+
@double = RestAssured::Client::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
|
@@ -9,8 +9,8 @@ When /^I create a double with "([^"]*)" as fullpath and "([^"]*)" as response co
|
|
9
9
|
last_response.should be_ok
|
10
10
|
end
|
11
11
|
|
12
|
-
When /^I create a double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request
|
13
|
-
post '/doubles', { :fullpath => fullpath, :content => content, :
|
12
|
+
When /^I create a double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request verb$/ do |fullpath, content, verb|
|
13
|
+
post '/doubles', { :fullpath => fullpath, :content => content, :verb => verb }
|
14
14
|
last_response.should be_ok
|
15
15
|
end
|
16
16
|
|
@@ -18,16 +18,16 @@ Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^"]*)" as fullpath a
|
|
18
18
|
Double.where(:fullpath => fullpath, :content => content).count.should == 1
|
19
19
|
end
|
20
20
|
|
21
|
-
Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request
|
22
|
-
Double.where(:fullpath => fullpath, :content => content, :
|
21
|
+
Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request verb$/ do |n, fullpath, content, verb|
|
22
|
+
Double.where(:fullpath => fullpath, :content => content, :verb => verb).count.should == n
|
23
23
|
end
|
24
24
|
|
25
25
|
Given /^there is double with "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |fullpath, content|
|
26
26
|
Double.create(:fullpath => fullpath, :content => content)
|
27
27
|
end
|
28
28
|
|
29
|
-
Given /^there is double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request
|
30
|
-
Double.create(:fullpath => fullpath, :content => content, :
|
29
|
+
Given /^there is double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request verb$/ do |fullpath, content, verb|
|
30
|
+
Double.create(:fullpath => fullpath, :content => content, :verb => verb)
|
31
31
|
end
|
32
32
|
|
33
33
|
Given /^I register "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |fullpath, content|
|
@@ -39,8 +39,8 @@ When /^I request "([^"]*)"$/ do |fullpath|
|
|
39
39
|
get fullpath
|
40
40
|
end
|
41
41
|
|
42
|
-
When /^I "([^"]*)" "([^"]*)"$/ do |
|
43
|
-
send(
|
42
|
+
When /^I "([^"]*)" "([^"]*)"$/ do |verb, fullpath|
|
43
|
+
send(verb.downcase, fullpath)
|
44
44
|
end
|
45
45
|
|
46
46
|
Then /^I should get "([^"]*)" in response content$/ do |content|
|
@@ -141,3 +141,4 @@ end
|
|
141
141
|
Then /^I should be asked to confirm delete$/ do
|
142
142
|
page.driver.browser.switch_to.alert.accept
|
143
143
|
end
|
144
|
+
|
data/features/support/env.rb
CHANGED
@@ -33,11 +33,27 @@ Spork.prefork do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
World(Capybara, Rack::Test::Methods, RackHeaderHack)
|
36
|
+
|
36
37
|
end
|
37
38
|
|
38
39
|
|
39
40
|
Spork.each_run do
|
40
41
|
require 'rest-assured'
|
42
|
+
require 'rest-assured/client'
|
43
|
+
require File.expand_path('../test-server', __FILE__)
|
44
|
+
|
45
|
+
at_exit do
|
46
|
+
TestServer.stop
|
47
|
+
end
|
48
|
+
|
49
|
+
TestServer.start(:port => 9876)
|
50
|
+
|
51
|
+
while not TestServer.up?
|
52
|
+
puts 'Waiting for TestServer to come up...'
|
53
|
+
sleep 1
|
54
|
+
end
|
55
|
+
|
56
|
+
RestAssured::Client.config.server_address = 'http://localhost:9876'
|
41
57
|
|
42
58
|
def app
|
43
59
|
RestAssured::Application
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
# This is only needed till I get ActiveResource going through rack-test
|
4
|
+
class TestServer
|
5
|
+
@pid_file = "./rest-assured.pid"
|
6
|
+
|
7
|
+
def self.start(opts = {})
|
8
|
+
@server_port = opts[:port] || 9876
|
9
|
+
|
10
|
+
print 'Starting TestServer server... '
|
11
|
+
|
12
|
+
p = Process.fork do
|
13
|
+
if get_pid
|
14
|
+
print "\nPrevious TestServer instance appears to be running. Will be using it."
|
15
|
+
else
|
16
|
+
Process.exec("bundle exec rest-assured -p #{@server_port}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Process.detach(p)
|
21
|
+
puts 'Done.'
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.stop
|
25
|
+
print 'Shutting down TestServer server... '
|
26
|
+
Process.kill('TERM', get_pid.to_i) rescue puts( "Failed to kill TestServer server: #{$!}" )
|
27
|
+
puts 'Done.'
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.server_address
|
31
|
+
"http://localhost:#{@server_port}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.up?
|
35
|
+
Net::HTTP.new('localhost', @server_port).head('/')
|
36
|
+
true
|
37
|
+
rescue Errno::ECONNREFUSED
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def self.get_pid
|
44
|
+
`ps -eo pid,args`.split("\n").grep( /rest-assured -p #{@server_port}/ ).map{|p| p.split.first }.first
|
45
|
+
end
|
46
|
+
end
|
data/lib/rest-assured.rb
CHANGED
@@ -2,14 +2,15 @@ require 'rubygems'
|
|
2
2
|
require 'sinatra/base'
|
3
3
|
require 'haml'
|
4
4
|
require 'sass'
|
5
|
-
#require 'sinatra/reloader'
|
6
5
|
require 'rack-flash'
|
7
6
|
require 'sinatra/partials'
|
8
7
|
require 'rest-assured/init'
|
9
8
|
require 'rest-assured/models/double'
|
10
9
|
require 'rest-assured/models/redirect'
|
10
|
+
require 'rest-assured/models/request'
|
11
11
|
require 'rest-assured/routes/double'
|
12
12
|
require 'rest-assured/routes/redirect'
|
13
|
+
require 'rest-assured/routes/response'
|
13
14
|
|
14
15
|
module RestAssured
|
15
16
|
class Application < Sinatra::Base
|
@@ -46,23 +47,10 @@ module RestAssured
|
|
46
47
|
scss :base
|
47
48
|
end
|
48
49
|
|
49
|
-
%w{get post put delete}.each do |
|
50
|
-
send
|
51
|
-
|
50
|
+
%w{get post put delete}.each do |verb|
|
51
|
+
send verb, /.*/ do
|
52
|
+
Response.perform(self)
|
52
53
|
end
|
53
54
|
end
|
54
|
-
|
55
|
-
#configure(:development) do
|
56
|
-
#register Sinatra::Reloader
|
57
|
-
#end
|
58
|
-
|
59
|
-
private
|
60
|
-
def try_redirect(request)
|
61
|
-
r = Redirect.ordered.find do |r|
|
62
|
-
request.fullpath =~ /#{r.pattern}/
|
63
|
-
end
|
64
|
-
|
65
|
-
r && redirect( "#{r.to}#{request.fullpath}" )
|
66
|
-
end
|
67
55
|
end
|
68
56
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RestAssured
|
2
|
+
module Client
|
3
|
+
class Config
|
4
|
+
attr_reader :server_address
|
5
|
+
|
6
|
+
def server_address=(addr)
|
7
|
+
@server_address = Double.site = addr
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.config
|
12
|
+
@config ||= Config.new
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'rest-assured/client/resources'
|
@@ -1,15 +1,17 @@
|
|
1
1
|
class Double < ActiveRecord::Base
|
2
|
-
attr_accessible :fullpath, :content, :description, :
|
2
|
+
attr_accessible :fullpath, :content, :description, :verb
|
3
3
|
|
4
4
|
METHODS = %w{GET POST PUT DELETE}
|
5
5
|
|
6
6
|
validates_presence_of :fullpath, :content
|
7
|
-
validates_inclusion_of :
|
7
|
+
validates_inclusion_of :verb, :in => METHODS
|
8
8
|
|
9
9
|
before_save :toggle_active
|
10
|
-
before_validation :
|
10
|
+
before_validation :set_verb
|
11
11
|
after_destroy :set_active
|
12
12
|
|
13
|
+
has_many :requests
|
14
|
+
|
13
15
|
private
|
14
16
|
def toggle_active
|
15
17
|
ne = id ? '!=' : 'IS NOT'
|
@@ -19,8 +21,8 @@ class Double < ActiveRecord::Base
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
def
|
23
|
-
self.
|
24
|
+
def set_verb
|
25
|
+
self.verb = 'GET' unless verb.present?
|
24
26
|
end
|
25
27
|
|
26
28
|
def set_active
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
1
3
|
module RestAssured
|
2
4
|
module DoubleRoutes
|
3
5
|
def self.included(router)
|
@@ -15,9 +17,19 @@ module RestAssured
|
|
15
17
|
haml :'doubles/new'
|
16
18
|
end
|
17
19
|
|
18
|
-
router.
|
19
|
-
|
20
|
-
|
20
|
+
router.get '/doubles/:id.json' do |id|
|
21
|
+
begin
|
22
|
+
double = Double.find(id)
|
23
|
+
body double.to_json(:include => :requests)
|
24
|
+
rescue ActiveRecord::RecordNotFound
|
25
|
+
status 404
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
router.post /^\/doubles(\.json)?$/ do |passes_json|
|
30
|
+
f = { :fullpath => params['fullpath'], :content => params['content'], :description => params['description'], :verb => params['verb'] }
|
31
|
+
|
32
|
+
@double = Double.create(passes_json ? JSON.parse(request.body.read)['double'] : ( params['double'] || f ))
|
21
33
|
|
22
34
|
if browser?
|
23
35
|
if @double.errors.blank?
|
@@ -29,8 +41,10 @@ module RestAssured
|
|
29
41
|
end
|
30
42
|
else
|
31
43
|
if @double.errors.present?
|
32
|
-
status
|
33
|
-
body @double.errors.
|
44
|
+
status 422
|
45
|
+
body @double.errors.to_json
|
46
|
+
else
|
47
|
+
body @double.to_json
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Response
|
2
|
+
def self.perform(app)
|
3
|
+
request = app.request
|
4
|
+
|
5
|
+
if d = Double.where(:fullpath => request.fullpath, :active => true, :verb => request.request_method).first
|
6
|
+
request.body.rewind
|
7
|
+
body = request.body.read #without temp variable ':body => body' is always nil. mistery
|
8
|
+
d.requests.create!(:rack_env => request.env.to_json, :body => body, :params => request.params.to_json)
|
9
|
+
|
10
|
+
app.body d.content
|
11
|
+
elsif r = Redirect.ordered.find { |r| request.fullpath =~ /#{r.pattern}/ }
|
12
|
+
app.redirect( "#{r.to}#{request.fullpath}" )
|
13
|
+
else
|
14
|
+
app.status 404
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/rest-assured/version.rb
CHANGED
data/rest-assured.gemspec
CHANGED
@@ -22,10 +22,10 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.add_dependency 'sinatra', '>= 1.3.1'
|
24
24
|
s.add_dependency 'rack-flash', '>= 0.1.2'
|
25
|
-
#s.add_dependency 'sinatra-reloader'
|
26
25
|
s.add_dependency 'haml', '>= 3.1.3'
|
27
26
|
s.add_dependency 'sass', '>= 3.1.8'
|
28
27
|
s.add_dependency 'activerecord', '~> 3.1.0'
|
29
28
|
s.add_dependency 'sqlite3', '>= 1.3.4'
|
29
|
+
s.add_dependency 'activeresource'
|
30
30
|
end
|
31
31
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
3
|
+
|
4
|
+
module RestAssured::Client
|
5
|
+
describe Double do
|
6
|
+
before do
|
7
|
+
@orig_addr = RestAssured::Client.config.server_address
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
RestAssured::Client.config.server_address = @orig_addr
|
12
|
+
end
|
13
|
+
|
14
|
+
it { should be_kind_of ActiveResource::Base }
|
15
|
+
|
16
|
+
it 'knows where rest-assured server is' do
|
17
|
+
RestAssured::Client.config.server_address = 'http://localhost:1234'
|
18
|
+
Double.site.should == URI.parse('http://localhost:1234')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates new double' do
|
22
|
+
d = Double.create :fullpath => '/some/api', :content => 'content'
|
23
|
+
::Double.where(:id => d.id).should exist
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'finds exising double' do
|
27
|
+
d = ::Double.create :fullpath => '/some/api', :content => 'content'
|
28
|
+
|
29
|
+
Double.find(d.id).id.should be d.id
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'shows request history' do
|
33
|
+
d = ::Double.create :fullpath => '/some/api', :content => 'content'
|
34
|
+
d.requests << Request.create(:rack_env => 'rack_env json', :body => 'body', :params => 'params')
|
35
|
+
d.requests << Request.create(:rack_env => 'different rack_env', :body => 'other body', :params => 'more params')
|
36
|
+
|
37
|
+
dd = Double.find(d.id)
|
38
|
+
dd.requests.size.should == 2
|
39
|
+
dd.requests.first.rack_env.should == 'rack_env json'
|
40
|
+
dd.requests.first.params.should == 'params'
|
41
|
+
dd.requests.last.body.should == 'other body'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -2,10 +2,10 @@ require File.expand_path('../../spec_helper', __FILE__)
|
|
2
2
|
|
3
3
|
describe 'Double routes' do
|
4
4
|
let :test_double do
|
5
|
-
{ :fullpath => '/api/google?a=5', :content => 'some awesome content', :
|
5
|
+
{ :fullpath => '/api/google?a=5', :content => 'some awesome content', :verb => 'POST' }
|
6
6
|
end
|
7
7
|
let :valid_params do
|
8
|
-
{ 'double[fullpath]' => test_double[:fullpath], 'double[content]' => test_double[:content], 'double[
|
8
|
+
{ 'double[fullpath]' => test_double[:fullpath], 'double[content]' => test_double[:content], 'double[verb]' => test_double[:verb] }
|
9
9
|
end
|
10
10
|
let :invalid_params do
|
11
11
|
{ 'double[fullpath]' => test_double[:fullpath] }
|
@@ -102,7 +102,7 @@ describe 'Double routes' do
|
|
102
102
|
post '/doubles', test_double.except(:content)
|
103
103
|
|
104
104
|
last_response.should_not be_ok
|
105
|
-
last_response.body.should =~
|
105
|
+
last_response.body.should =~ /\{"content":\["can't be blank"\]\}/
|
106
106
|
end
|
107
107
|
|
108
108
|
it "deletes all doubles" do
|
@@ -114,4 +114,36 @@ describe 'Double routes' do
|
|
114
114
|
Double.count.should == 0
|
115
115
|
end
|
116
116
|
end
|
117
|
+
|
118
|
+
describe 'through REST (ActiveResource compatible) json api', :ui => false do
|
119
|
+
it "creates double as AR resource" do
|
120
|
+
post '/doubles.json', { :double => test_double }.to_json, 'CONTENT_TYPE' => 'Application/json'
|
121
|
+
|
122
|
+
last_response.should be_ok
|
123
|
+
Double.exists?(test_double).should be_true
|
124
|
+
last_response.body.should == Double.where(test_double).first.to_json
|
125
|
+
end
|
126
|
+
|
127
|
+
it "reports failure when creating with invalid parameters" do
|
128
|
+
post '/doubles.json', { :double => test_double.except(:content) }.to_json, 'CONTENT_TYPE' => 'Application/json'
|
129
|
+
|
130
|
+
last_response.should_not be_ok
|
131
|
+
last_response.body.should =~ /\{"content":\["can't be blank"\]\}/
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'loads double as AR resource' do
|
135
|
+
d = Double.create test_double
|
136
|
+
|
137
|
+
get "/doubles/#{d.id}.json", 'CONTENT_TYPE' => 'Application/json'
|
138
|
+
|
139
|
+
last_response.should be_ok
|
140
|
+
last_response.body.should == d.to_json(:include => :requests)
|
141
|
+
end
|
142
|
+
|
143
|
+
it '404s if double is not found' do
|
144
|
+
get "/doubles/345345.json", 'CONTENT_TYPE' => 'Application/json'
|
145
|
+
|
146
|
+
last_response.status.should == 404
|
147
|
+
end
|
148
|
+
end
|
117
149
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
require 'rest-assured/routes/response'
|
3
|
+
|
4
|
+
describe Response do
|
5
|
+
[:get, :post, :put, :delete].each do |verb|
|
6
|
+
it "processes an unknown request" do
|
7
|
+
|
8
|
+
Response.should_receive(:perform).with(an_instance_of(RestAssured::Application))
|
9
|
+
send verb, '/some/path'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:request) {
|
14
|
+
double('Request',
|
15
|
+
:request_method => 'GET',
|
16
|
+
:fullpath => '/api',
|
17
|
+
:env => stub(:to_json => 'env'),
|
18
|
+
:body => stub(:read => 'body').as_null_object,
|
19
|
+
:params => stub(:to_json => 'params')
|
20
|
+
)
|
21
|
+
}
|
22
|
+
let(:rest_assured_app) { double('App', :request => request).as_null_object }
|
23
|
+
|
24
|
+
it "returns double content if an active one found with the same fullpath and the same method as request" do
|
25
|
+
d = Double.create :fullpath => '/some/path', :content => 'content'
|
26
|
+
request.stub(:fullpath).and_return(d.fullpath)
|
27
|
+
|
28
|
+
rest_assured_app.should_receive(:body).with(d.content)
|
29
|
+
Response.perform(rest_assured_app)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "redirects if double not hit but there is redirect that matches request" do
|
33
|
+
r = Redirect.create :to => 'http://exmple.com/api', :pattern => '.*'
|
34
|
+
fullpath = '/some/other/path'
|
35
|
+
request.stub(:fullpath).and_return(fullpath)
|
36
|
+
|
37
|
+
rest_assured_app.should_receive(:redirect).with(r.to + fullpath)
|
38
|
+
|
39
|
+
Response.perform(rest_assured_app)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns 404 if neither double nor redirect matches the request" do
|
43
|
+
rest_assured_app.should_receive(:status).with(404)
|
44
|
+
|
45
|
+
Response.perform(rest_assured_app)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'records request if double matches' do
|
49
|
+
requests = double
|
50
|
+
Double.stub_chain('where.first').and_return(double(:requests => requests).as_null_object)
|
51
|
+
|
52
|
+
requests.should_receive(:create!).with(:rack_env => 'env', :body => 'body', :params => 'params')
|
53
|
+
|
54
|
+
Response.perform(rest_assured_app)
|
55
|
+
end
|
56
|
+
end
|
data/spec/models/double_spec.rb
CHANGED
@@ -2,16 +2,17 @@ require File.expand_path('../../spec_helper', __FILE__)
|
|
2
2
|
|
3
3
|
describe Double do
|
4
4
|
let :valid_params do
|
5
|
-
{ :fullpath => '/some/api', :content => 'some content', :
|
5
|
+
{ :fullpath => '/some/api', :content => 'some content', :verb => 'GET' }
|
6
6
|
end
|
7
7
|
|
8
8
|
it { should validate_presence_of(:fullpath) }
|
9
9
|
it { should validate_presence_of(:content) }
|
10
|
-
#it { should ensure_inclusion_of(:
|
10
|
+
#it { should ensure_inclusion_of(:verb).in(Double::METHODS) }
|
11
|
+
it { should have_many(:requests) }
|
11
12
|
|
12
|
-
it "defaults
|
13
|
-
f = Double.create valid_params.except(:
|
14
|
-
f.
|
13
|
+
it "defaults verb to GET" do
|
14
|
+
f = Double.create valid_params.except(:verb)
|
15
|
+
f.verb.should == 'GET'
|
15
16
|
end
|
16
17
|
|
17
18
|
it "makes double active by default" do
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
require 'rest-assured/models/request'
|
3
|
+
|
4
|
+
describe Request do
|
5
|
+
it { should belong_to(:double) }
|
6
|
+
it { should validate_presence_of(:rack_env) }
|
7
|
+
|
8
|
+
it 'knows when it has been created' do
|
9
|
+
now = Time.now
|
10
|
+
Time.stub(:now).and_return(now)
|
11
|
+
r = Request.create(:body => 'sdfsd', :rack_env => 'headers')
|
12
|
+
|
13
|
+
r.created_at.should == now
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'spork'
|
3
3
|
|
4
|
+
$:.unshift(File.expand_path('../../lib'), __FILE__)
|
5
|
+
|
4
6
|
Spork.prefork do
|
5
7
|
require 'capybara/rspec'
|
6
8
|
require 'rack/test'
|
@@ -40,10 +42,23 @@ Spork.prefork do
|
|
40
42
|
end
|
41
43
|
|
42
44
|
Spork.each_run do
|
43
|
-
require
|
45
|
+
require 'rest-assured'
|
46
|
+
require 'rest-assured/client'
|
44
47
|
require 'shoulda-matchers'
|
48
|
+
require File.expand_path('../../features/support/test-server', __FILE__)
|
45
49
|
|
46
|
-
|
50
|
+
at_exit do
|
51
|
+
TestServer.stop
|
52
|
+
end
|
53
|
+
|
54
|
+
TestServer.start(:port => 9876)
|
55
|
+
|
56
|
+
while not TestServer.up?
|
57
|
+
puts 'Waiting for TestServer to come up...'
|
58
|
+
sleep 1
|
59
|
+
end
|
60
|
+
|
61
|
+
RestAssured::Client.config.server_address = 'http://localhost:9876'
|
47
62
|
|
48
63
|
Capybara.app = RestAssured::Application
|
49
64
|
|
@@ -51,4 +66,5 @@ Spork.each_run do
|
|
51
66
|
RestAssured::Application
|
52
67
|
end
|
53
68
|
|
69
|
+
DatabaseCleaner.strategy = :truncation
|
54
70
|
end
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-assured
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 15424055
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
- rc
|
8
11
|
- 1
|
9
|
-
|
10
|
-
version: 0.1.4
|
12
|
+
version: 0.2.0.rc1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Artem Avetisyan
|
@@ -15,7 +17,7 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date: 2011-10-
|
20
|
+
date: 2011-10-17 00:00:00 Z
|
19
21
|
dependencies:
|
20
22
|
- !ruby/object:Gem::Dependency
|
21
23
|
name: sinatra
|
@@ -113,6 +115,20 @@ dependencies:
|
|
113
115
|
version: 1.3.4
|
114
116
|
type: :runtime
|
115
117
|
version_requirements: *id006
|
118
|
+
- !ruby/object:Gem::Dependency
|
119
|
+
name: activeresource
|
120
|
+
prerelease: false
|
121
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
version: "0"
|
130
|
+
type: :runtime
|
131
|
+
version_requirements: *id007
|
116
132
|
description:
|
117
133
|
email:
|
118
134
|
- artem.avetisyan@bbc.co.uk
|
@@ -140,25 +156,35 @@ files:
|
|
140
156
|
- db/migrate/20110823132023_add_method_to_fixtures.rb
|
141
157
|
- db/migrate/20110912162948_rename_url_to_fullpath.rb
|
142
158
|
- db/migrate/20110912163705_rename_fixtures_to_doubles.rb
|
159
|
+
- db/migrate/20111013122857_create_requests.rb
|
160
|
+
- db/migrate/20111016174101_rename_method_to_verb.rb
|
161
|
+
- features/call_history.feature
|
143
162
|
- features/doubles_via_api.feature
|
144
163
|
- features/doubles_via_ui.feature
|
145
164
|
- features/persistence.feature
|
146
165
|
- features/redirect_rules_via_api.feature
|
147
166
|
- features/redirect_rules_via_ui.feature
|
167
|
+
- features/step_definitions/call_history_steps.rb
|
148
168
|
- features/step_definitions/doubles_steps.rb
|
149
169
|
- features/step_definitions/persistence_steps.rb
|
150
170
|
- features/step_definitions/redirect_rules_steps.rb
|
151
171
|
- features/step_definitions/support/numeric_transforms.rb
|
152
172
|
- features/support/env.rb
|
153
173
|
- features/support/selenium-fix.rb
|
174
|
+
- features/support/test-server.rb
|
154
175
|
- lib/active_record/leak_connection_patch.rb
|
155
176
|
- lib/rest-assured.rb
|
177
|
+
- lib/rest-assured/client.rb
|
178
|
+
- lib/rest-assured/client/double.rb
|
179
|
+
- lib/rest-assured/client/resources.rb
|
156
180
|
- lib/rest-assured/config.rb
|
157
181
|
- lib/rest-assured/init.rb
|
158
182
|
- lib/rest-assured/models/double.rb
|
159
183
|
- lib/rest-assured/models/redirect.rb
|
184
|
+
- lib/rest-assured/models/request.rb
|
160
185
|
- lib/rest-assured/routes/double.rb
|
161
186
|
- lib/rest-assured/routes/redirect.rb
|
187
|
+
- lib/rest-assured/routes/response.rb
|
162
188
|
- lib/rest-assured/version.rb
|
163
189
|
- lib/sinatra/partials.rb
|
164
190
|
- public/css/grid.inuit.css
|
@@ -177,10 +203,13 @@ files:
|
|
177
203
|
- public/javascript/application.js
|
178
204
|
- public/javascript/jquery.jgrowl_minimized.js
|
179
205
|
- rest-assured.gemspec
|
206
|
+
- spec/client/resource_double_spec.rb
|
180
207
|
- spec/functional/double_routes_spec.rb
|
181
208
|
- spec/functional/redirect_routes_spec.rb
|
209
|
+
- spec/functional/response_spec.rb
|
182
210
|
- spec/models/double_spec.rb
|
183
211
|
- spec/models/redirect_spec.rb
|
212
|
+
- spec/models/request_spec.rb
|
184
213
|
- spec/spec_helper.rb
|
185
214
|
- views/base.scss
|
186
215
|
- views/doubles/_form.haml
|
@@ -214,12 +243,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
214
243
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
215
244
|
none: false
|
216
245
|
requirements:
|
217
|
-
- - "
|
246
|
+
- - ">"
|
218
247
|
- !ruby/object:Gem::Version
|
219
|
-
hash:
|
248
|
+
hash: 25
|
220
249
|
segments:
|
221
|
-
-
|
222
|
-
|
250
|
+
- 1
|
251
|
+
- 3
|
252
|
+
- 1
|
253
|
+
version: 1.3.1
|
223
254
|
requirements: []
|
224
255
|
|
225
256
|
rubyforge_project: rest-assured
|
@@ -228,19 +259,25 @@ signing_key:
|
|
228
259
|
specification_version: 3
|
229
260
|
summary: A tool for high level mocking/stubbing HTTP based REST services
|
230
261
|
test_files:
|
262
|
+
- features/call_history.feature
|
231
263
|
- features/doubles_via_api.feature
|
232
264
|
- features/doubles_via_ui.feature
|
233
265
|
- features/persistence.feature
|
234
266
|
- features/redirect_rules_via_api.feature
|
235
267
|
- features/redirect_rules_via_ui.feature
|
268
|
+
- features/step_definitions/call_history_steps.rb
|
236
269
|
- features/step_definitions/doubles_steps.rb
|
237
270
|
- features/step_definitions/persistence_steps.rb
|
238
271
|
- features/step_definitions/redirect_rules_steps.rb
|
239
272
|
- features/step_definitions/support/numeric_transforms.rb
|
240
273
|
- features/support/env.rb
|
241
274
|
- features/support/selenium-fix.rb
|
275
|
+
- features/support/test-server.rb
|
276
|
+
- spec/client/resource_double_spec.rb
|
242
277
|
- spec/functional/double_routes_spec.rb
|
243
278
|
- spec/functional/redirect_routes_spec.rb
|
279
|
+
- spec/functional/response_spec.rb
|
244
280
|
- spec/models/double_spec.rb
|
245
281
|
- spec/models/redirect_spec.rb
|
282
|
+
- spec/models/request_spec.rb
|
246
283
|
- spec/spec_helper.rb
|