Permalink
Browse files

Implements custom double response status

  • Loading branch information...
1 parent 6accb98 commit dbbdf7f7afc1d7c3b6eff2273718ee02aea6eefc @artemave artemave committed Oct 21, 2011
View
@@ -4,7 +4,7 @@
guard 'spork', :cucumber_env => { 'RACK_ENV' => 'test' }, :rspec_env => { 'RACK_ENV' => 'test' } do
watch('Gemfile')
watch('Gemfile.lock')
- watch('spec/spec_helper.rb')
+ watch(%r{spec/.+\.rb})
watch(%r{features/support/.+\.rb$})
watch(%r{^lib/.+\.rb$})
end
@@ -0,0 +1,9 @@
+class AddStatusToDoubles < ActiveRecord::Migration
+ def self.up
+ add_column :doubles, :status, :integer
+ end
+
+ def self.down
+ remove_column :doubles, :status
+ end
+end
@@ -3,29 +3,32 @@ Feature: use doubles via api
As a developer
I want to mock rest services my app is consuming from
+ @now
Scenario Outline: create double
- When I create a double with "<fullpath>" as fullpath, "<content>" as response content and "<verb>" as request verb
- Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content and "<result_verb>" as request verb
+ When I create a double with "<fullpath>" as fullpath, "<content>" as response content, "<verb>" as request verb and status as "<status>"
+ Then there should be 1 double with "<fullpath>" as fullpath, "<content>" as response content, "<result_verb>" as request verb and status as "<result_status>"
Examples:
- | fullpath | content | verb | result_verb |
- | /api/something | created | POST | POST |
- | /api/sss | changed | PUT | PUT |
- | /api/asdfsf | removed | DELETE | DELETE |
- | /api/some | text content | GET | GET |
- | /api/some?a=3&b=dd | more content | | GET |
+ | fullpath | content | verb | result_verb | status | result_status |
+ | /api/something | created | POST | POST | 200 | 200 |
+ | /api/sss | changed | PUT | PUT | 201 | 201 |
+ | /api/asdfsf | removed | DELETE | DELETE | 300 | 300 |
+ | /api/some | text content | GET | GET | 303 | 303 |
+ | /api/some?a=3&b=dd | more content | | GET | | 200 |
+ | /api/empty | | POST | POST | | 200 |
Scenario Outline: request fullpath that matches double
- Given there is double with "<fullpath>" as fullpath, "<content>" as response content and "<verb>" as request verb
+ Given there is double with "<fullpath>" as fullpath, "<content>" as response content, "<verb>" as request verb and "<status>" as status
When I "<verb>" "<fullpath>"
- Then I should get "<content>" in response content
+ Then I should get "<status>" as response status and "<content>" in response content
Examples:
- | fullpath | content | verb |
- | /api/something | created | POST |
- | /api/sss | changed | PUT |
- | /api/asdfsf | removed | DELETE |
- | /api/some?a=3&b=dd | more content | GET |
+ | fullpath | content | verb | status |
+ | /api/something | created | POST | 200 |
+ | /api/sss | changed | PUT | 201 |
+ | /api/asdfsf | removed | DELETE | 202 |
+ | /api/some?a=3&b=dd | more content | GET | 203 |
+ | /other/api | | GET | 303 |
# current rule: last added double gets picked
Scenario Outline: request fullpath that matches multiple doubles
@@ -9,25 +9,25 @@
last_response.should be_ok
end
-When /^I create a double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request verb$/ do |fullpath, content, verb|
- post '/doubles', { :fullpath => fullpath, :content => content, :verb => verb }
+When /^I create a double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb and status as "([^""]*)"$/ do |fullpath, content, verb, status|
+ post '/doubles', { :fullpath => fullpath, :content => content, :verb => verb, :status => status }
last_response.should be_ok
end
Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |n, fullpath, content|
- Double.where(:fullpath => fullpath, :content => content).count.should == 1
+ Double.where(:fullpath => fullpath, :content => content).count.should == n
end
-Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request verb$/ do |n, fullpath, content, verb|
- Double.where(:fullpath => fullpath, :content => content, :verb => verb).count.should == n
+Then /^there should be (#{CAPTURE_A_NUMBER}) double with "([^""]*)" as fullpath, "([^""]*)" as response content, "([^""]*)" as request verb and status as "(#{CAPTURE_A_NUMBER})"$/ do |n, fullpath, content, verb, status|
+ Double.where(:fullpath => fullpath, :content => content, :verb => verb, :status => status).count.should == n
end
Given /^there is double with "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |fullpath, content|
Double.create(:fullpath => fullpath, :content => content)
end
-Given /^there is double with "([^"]*)" as fullpath, "([^"]*)" as response content and "([^"]*)" as request verb$/ do |fullpath, content, verb|
- Double.create(:fullpath => fullpath, :content => content, :verb => verb)
+Given /^there is double with "([^"]*)" as fullpath, "([^"]*)" as response content, "([^"]*)" as request verb and "([^"]*)" as status$/ do |fullpath, content, verb, status|
+ Double.create(:fullpath => fullpath, :content => content, :verb => verb, :status => status)
end
Given /^I register "([^"]*)" as fullpath and "([^"]*)" as response content$/ do |fullpath, content|
@@ -43,7 +43,8 @@
send(verb.downcase, fullpath)
end
-Then /^I should get "([^"]*)" in response content$/ do |content|
+Then /^I should get (?:"(#{CAPTURE_A_NUMBER})" as response status and )?"([^"]*)" in response content$/ do |status, content|
+ last_response.status.should == status if status.present?
last_response.body.should == content
end
@@ -1,13 +1,18 @@
+require 'net/http'
+
class Double < ActiveRecord::Base
- attr_accessible :fullpath, :content, :description, :verb
+ attr_accessible :fullpath, :content, :description, :verb, :status
- METHODS = %w{GET POST PUT DELETE}
+ VERBS = %w{GET POST PUT DELETE}
+ STATUSES = Net::HTTPResponse::CODE_TO_OBJ.keys.map(&:to_i)
- validates_presence_of :fullpath, :content
- validates_inclusion_of :verb, :in => METHODS
+ validates_presence_of :fullpath
+ validates_inclusion_of :verb, :in => VERBS
+ validates_inclusion_of :status, :in => STATUSES
before_save :toggle_active
before_validation :set_verb
+ before_validation :set_status
after_destroy :set_active
has_many :requests
@@ -25,6 +30,10 @@ def set_verb
self.verb = 'GET' unless verb.present?
end
+ def set_status
+ self.status = 200 unless status.present?
+ end
+
def set_active
if active && f = Double.where(:fullpath => fullpath).last
f.active = true
@@ -27,7 +27,7 @@ def self.included(router)
end
router.post /^\/doubles(\.json)?$/ do |passes_json|
- f = { :fullpath => params['fullpath'], :content => params['content'], :description => params['description'], :verb => params['verb'] }
+ f = { :fullpath => params['fullpath'], :content => params['content'], :description => params['description'], :verb => params['verb'], :status => params['status'] }
@double = Double.create(passes_json ? JSON.parse(request.body.read)['double'] : ( params['double'] || f ))
@@ -10,6 +10,7 @@ def self.perform(app)
d.requests.create!(:rack_env => env.to_json, :body => body, :params => request.params.to_json)
app.body d.content
+ app.status d.status
elsif r = Redirect.ordered.find { |r| request.fullpath =~ /#{r.pattern}/ }
app.redirect( "#{r.to}#{request.fullpath}" )
else
@@ -1,3 +1,3 @@
module RestAssured
- VERSION = '0.2.0.rc4'
+ VERSION = '0.2.0.rc5'
end
View
@@ -0,0 +1,7 @@
+RSpec::Matchers.define :validate_inclusion_of do |field, list|
+ match do |actual|
+ list.each do |i|
+ actual.should allow_value(i).for(field)
+ end
+ end
+end
@@ -2,13 +2,13 @@
describe 'Double routes' do
let :test_double do
- { :fullpath => '/api/google?a=5', :content => 'some awesome content', :verb => 'POST' }
+ { :fullpath => '/api/google?a=5', :content => 'some awesome content', :verb => 'POST', :status => '201' }
end
let :valid_params do
- { 'double[fullpath]' => test_double[:fullpath], 'double[content]' => test_double[:content], 'double[verb]' => test_double[:verb] }
+ { 'double[fullpath]' => test_double[:fullpath], 'double[content]' => test_double[:content], 'double[verb]' => test_double[:verb], 'double[status]' => test_double[:status] }
end
let :invalid_params do
- { 'double[fullpath]' => test_double[:fullpath] }
+ valid_params.except('double[fullpath]')
end
describe "through ui", :ui => true do
@@ -46,7 +46,7 @@
post '/doubles', invalid_params
last_response.should be_ok
- last_response.body.should =~ /Crumps!.*Content can't be blank/
+ last_response.body.should =~ /Crumps!.*Fullpath can't be blank/
end
it "brings up double edit form" do
@@ -99,10 +99,10 @@
end
it "reports failure when creating with invalid parameters" do
- post '/doubles', test_double.except(:content)
+ post '/doubles', test_double.except(:fullpath)
last_response.should_not be_ok
- last_response.body.should =~ /\{"content":\["can't be blank"\]\}/
+ last_response.body.should =~ /\{"fullpath":\["can't be blank"\]\}/
end
it "deletes all doubles" do
@@ -125,10 +125,10 @@
end
it "reports failure when creating with invalid parameters" do
- post '/doubles.json', { :double => test_double.except(:content) }.to_json, 'CONTENT_TYPE' => 'Application/json'
+ post '/doubles.json', { :double => test_double.except(:fullpath) }.to_json, 'CONTENT_TYPE' => 'Application/json'
last_response.should_not be_ok
- last_response.body.should =~ /\{"content":\["can't be blank"\]\}/
+ last_response.body.should =~ /\{"fullpath":\["can't be blank"\]\}/
end
it 'loads double as AR resource' do
@@ -22,12 +22,32 @@
}
let(:rest_assured_app) { double('App', :request => request).as_null_object }
- it "returns double content if an active one found with the same fullpath and the same method as request" do
- d = Double.create :fullpath => '/some/path', :content => 'content'
- request.stub(:fullpath).and_return(d.fullpath)
+ context 'when double matches request' do
+ before do
+ @double = Double.create :fullpath => '/some/path', :content => 'content', :status => 201
+ request.stub(:fullpath).and_return(@double.fullpath)
+ end
- rest_assured_app.should_receive(:body).with(d.content)
- Response.perform(rest_assured_app)
+ it "returns double content" do
+ rest_assured_app.should_receive(:body).with(@double.content)
+
+ Response.perform(rest_assured_app)
+ end
+
+ it 'sets response status to the one from double' do
+ rest_assured_app.should_receive(:status).with(@double.status)
+
+ Response.perform(rest_assured_app)
+ end
+
+ it 'records request' do
+ requests = double
+ Double.stub_chain('where.first').and_return(double(:requests => requests).as_null_object)
+
+ requests.should_receive(:create!).with(:rack_env => 'env', :body => 'body', :params => 'params')
+
+ Response.perform(rest_assured_app)
+ end
end
it "redirects if double not hit but there is redirect that matches request" do
@@ -46,15 +66,6 @@
Response.perform(rest_assured_app)
end
- it 'records request if double matches' do
- requests = double
- Double.stub_chain('where.first').and_return(double(:requests => requests).as_null_object)
-
- requests.should_receive(:create!).with(:rack_env => 'env', :body => 'body', :params => 'params')
-
- Response.perform(rest_assured_app)
- end
-
it 'excludes "rack.input" and "rack.errors" as they break with "IOError - not opened for reading:" on consequent #to_json (as they are IO and StringIO)' do
requests = double.as_null_object
Double.stub_chain('where.first').and_return(double(:requests => requests).as_null_object)
View
@@ -2,19 +2,34 @@
describe Double do
let :valid_params do
- { :fullpath => '/some/api', :content => 'some content', :verb => 'GET' }
+ { :fullpath => '/some/api', :content => 'some content', :verb => 'GET', :status => '303' }
end
it { should validate_presence_of(:fullpath) }
- it { should validate_presence_of(:content) }
- #it { should ensure_inclusion_of(:verb).in(Double::METHODS) }
+ it { should validate_inclusion_of(:verb, Double::VERBS) }
+ it { should validate_inclusion_of(:status, Double::STATUSES) }
+ it { should allow_mass_assignment_of(:fullpath) }
+ it { should allow_mass_assignment_of(:content) }
+ it { should allow_mass_assignment_of(:verb) }
+ it { should allow_mass_assignment_of(:status) }
+
it { should have_many(:requests) }
+ it 'creates double with valid params' do
+ d = Double.new valid_params
+ d.should be_valid
+ end
+
it "defaults verb to GET" do
f = Double.create valid_params.except(:verb)
f.verb.should == 'GET'
end
+ it "defaults status to 200" do
+ f = Double.create valid_params.except(:status)
+ f.status.should == 200
+ end
+
it "makes double active by default" do
f = Double.create valid_params.except(:active)
f.active.should be true
@@ -8,6 +8,9 @@
it { should validate_presence_of(:pattern) }
it { should validate_presence_of(:to) }
+ it { should allow_mass_assignment_of(:pattern) }
+ it { should allow_mass_assignment_of(:to) }
+ it { should allow_mass_assignment_of(:position) }
# commented out since it doesn't work with :allow_blank => true
#it { should validate_uniqueness_of(:position) }
View
@@ -7,6 +7,7 @@
require 'capybara/rspec'
require 'rack/test'
require 'database_cleaner'
+ require File.expand_path('../custom_matchers', __FILE__)
ENV['RACK_ENV'] = 'test'

0 comments on commit dbbdf7f

Please sign in to comment.