rspec-rails-ext 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +12 -0
- data/LICENCE +11 -0
- data/Manifest +11 -0
- data/README.rdoc +82 -0
- data/Rakefile +12 -0
- data/lib/controller_example_group.rb +65 -0
- data/lib/mocks.rb +36 -0
- data/lib/responses.rb +92 -0
- data/lib/rspec_rails_extensions.rb +5 -0
- data/lib/use_layout.rb +29 -0
- data/rspec-rails-ext.gemspec +30 -0
- metadata +76 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
v1.7.1. Added be_not_acceptable
|
2
|
+
v1.7. Added use_layout matcher
|
3
|
+
v1.6.3. Changed the output when status/locations don't match
|
4
|
+
v1.6.2. Changed how we match the status header
|
5
|
+
v1.6.1. Added associated_model builder
|
6
|
+
v1.6.0. Pushed a version that actually works (oops, sorry about that)
|
7
|
+
v1.005. Added invalid_model
|
8
|
+
v1.004. Added `rake build`
|
9
|
+
v1.003. Added mocks - prepare_for_errors_on
|
10
|
+
v1.002. Bugfix
|
11
|
+
v1.001. Bugfix
|
12
|
+
v1.000. Initial release
|
data/LICENCE
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Released under the MIT Licence
|
2
|
+
|
3
|
+
Copyright (c) 2008 Brightbox Systems Ltd
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
10
|
+
|
11
|
+
See http://www.brightbox.co.uk/ for contact details.
|
data/Manifest
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
= RSpec-Rails Extensions
|
2
|
+
|
3
|
+
Some prettifications for RSpec Rails.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
sudo gem install rspec-rails-ext
|
8
|
+
|
9
|
+
Then, within your spec/spec_helper.rb
|
10
|
+
|
11
|
+
require 'rspec_rails_extensions'
|
12
|
+
|
13
|
+
== ActiveRecord::RecordInvalid
|
14
|
+
|
15
|
+
If you try to call ActiveRecord::RecordInvalid.new(@my_object) where @my_object is a mock then your exception will not be raised; instead you get a cryptic error. This is because RecordInvalid expects to be able to call certain methods on your ActiveRecord model, which your mock isn't set up for. So instead, prepare your mock, like so:
|
16
|
+
|
17
|
+
@thingy = mock_model Thingy, :field => 'value'
|
18
|
+
prepare_for_errors_on @thingy
|
19
|
+
raise ActiveRecord::RecordInvalid.new(@thingy)
|
20
|
+
|
21
|
+
There's also a short-cut method:
|
22
|
+
|
23
|
+
@thingy = invalid_model Thingy, :field => 'value'
|
24
|
+
raise ActiveRecord::RecordInvalid.new(@thingy)
|
25
|
+
|
26
|
+
== Matchers
|
27
|
+
|
28
|
+
Some helpful matchers for testing HTTP statuses beyond the default be_success (200 OK)
|
29
|
+
|
30
|
+
# looks for a 201 Created (useful for API CREATE calls)
|
31
|
+
response.should be_successfully_created
|
32
|
+
|
33
|
+
# expects a Location field with the given URL (useful for API CREATE calls)
|
34
|
+
response.should point_to(url)
|
35
|
+
|
36
|
+
# looks for a 422 response (invalid object)
|
37
|
+
response.should be_unprocessable
|
38
|
+
|
39
|
+
# looks for a 404
|
40
|
+
response.should be_not_found
|
41
|
+
|
42
|
+
# looks for a 401
|
43
|
+
response.should be_unauthorised
|
44
|
+
|
45
|
+
# looks for a 500
|
46
|
+
response.should be_an_error
|
47
|
+
|
48
|
+
Also a helper for testing which layout was used
|
49
|
+
|
50
|
+
# Makes sure it used the "bare" layout
|
51
|
+
response.should use_layout("bare")
|
52
|
+
|
53
|
+
== Specifying your controllers
|
54
|
+
|
55
|
+
One of the issues with writing standard controller specifications, using RSpec's inbuilt mock objects is that the "flow" of your specs feels wrong.
|
56
|
+
|
57
|
+
it "should display a page for a given thingy" do
|
58
|
+
@thingy = mock_model Thingy, :name => 'Wotsit'
|
59
|
+
Thingy.should_receive(:find).with('1').and_return(@thingy)
|
60
|
+
|
61
|
+
get :show, :id => '1'
|
62
|
+
|
63
|
+
response.should be_success
|
64
|
+
response.should render_template('thingies/show')
|
65
|
+
end
|
66
|
+
|
67
|
+
In other words you are setting expectations before you are doing the work - technically correct but it reads wrongly.
|
68
|
+
|
69
|
+
These extra helpers let you write specifications in a more english-like manner.
|
70
|
+
|
71
|
+
it "should display a page for a given thingy" do
|
72
|
+
@thingy = mock_model Thingy
|
73
|
+
|
74
|
+
on_getting :show, :id => '1' do
|
75
|
+
Thingy.should_receive(:find).with('1').and_return(@thingy)
|
76
|
+
end
|
77
|
+
|
78
|
+
response.should be_success
|
79
|
+
response.should render_template('thingies/show')
|
80
|
+
end
|
81
|
+
|
82
|
+
Isn't that lovely?
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'echoe'
|
2
|
+
Echoe.new('rspec-rails-ext') do | gem |
|
3
|
+
gem.author = ["Rahoul Baruah", "Caius Durling"]
|
4
|
+
gem.email = 'support@brightbox.co.uk'
|
5
|
+
gem.summary = 'Helpers for prettying up your RSpec-Rails specifications'
|
6
|
+
gem.url = 'http://github.com/brightbox/rspec-rails-extensions/tree/master'
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Generates the manifest and the gemspec"
|
10
|
+
task :build => [:manifest, :build_gemspec] do
|
11
|
+
puts "Built!"
|
12
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rails
|
3
|
+
module Example
|
4
|
+
class ControllerExampleGroup < FunctionalExampleGroup
|
5
|
+
# Perform a pseudo HTTP GET, performing any code in the block beforehand. This is to allow you to set up expectations on your mocks whilst keeping the code readable.
|
6
|
+
# For example:
|
7
|
+
# on_getting :show, :id => '25' do
|
8
|
+
# @person = mock_model Person
|
9
|
+
# Person.should_receive(:find).with('25').and_return(@person)
|
10
|
+
# end
|
11
|
+
# If you want an XMLHTTPRequest pass in :as_xhr => true in the parameters
|
12
|
+
# (don't worry - it won't be passed to your controller)
|
13
|
+
# For example:
|
14
|
+
# on_getting :show, :id => '25', :as_xhr => true do
|
15
|
+
# whatever
|
16
|
+
# end
|
17
|
+
def on_getting page, parameters = {}
|
18
|
+
yield if block_given?
|
19
|
+
is_xhr_request = parameters.delete(:as_xhr)
|
20
|
+
if is_xhr_request
|
21
|
+
xhr :get, page, parameters
|
22
|
+
else
|
23
|
+
get page, parameters
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Perform a pseudo HTTP POST, performing any code in the block beforehand. This is to allow you to set up expectations on your mocks whilst keeping the code readable.
|
28
|
+
# As with on_getting, use :as_xhr => true to make this an XMLHTTPRequest
|
29
|
+
def on_posting_to page, parameters = {}
|
30
|
+
yield if block_given?
|
31
|
+
is_xhr_request = parameters.delete(:as_xhr)
|
32
|
+
if is_xhr_request
|
33
|
+
xhr :post, page, parameters
|
34
|
+
else
|
35
|
+
post page, parameters
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Perform a pseudo HTTP PUT, performing any code in the block beforehand. This is to allow you to set up expectations on your mocks whilst keeping the code readable.
|
40
|
+
# As with on_getting, use :as_xhr => true to make this an XMLHTTPRequest
|
41
|
+
def on_putting_to page, parameters = {}
|
42
|
+
yield if block_given?
|
43
|
+
is_xhr_request = parameters.delete(:as_xhr)
|
44
|
+
if is_xhr_request
|
45
|
+
xhr :put, page, parameters
|
46
|
+
else
|
47
|
+
put page, parameters
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Perform a pseudo HTTP DELETE, performing any code in the block beforehand. This is to allow you to set up expectations on your mocks whilst keeping the code readable.
|
52
|
+
# As with on_getting, use :as_xhr => true to make this an XMLHTTPRequest
|
53
|
+
def on_deleting_from page, parameters = {}
|
54
|
+
yield if block_given?
|
55
|
+
is_xhr_request = parameters.delete(:as_xhr)
|
56
|
+
if is_xhr_request
|
57
|
+
xhr :delete, page, parameters
|
58
|
+
else
|
59
|
+
delete page, parameters
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/mocks.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Spec
|
2
|
+
module Rails
|
3
|
+
module Mocks
|
4
|
+
# Set up the given mock model in preparation for an ActiveRecord::RecordInvalid call
|
5
|
+
# For example:
|
6
|
+
# @user = mock_model User
|
7
|
+
# prepare_for_errors_on @user
|
8
|
+
# @user.should_receive(:save!).and_raise(ActiveRecord::RecordInvalid.new(@user))
|
9
|
+
# If you tried this without the call to prepare_for_errors_on, the RecordInvalid exception would not be raised.
|
10
|
+
def prepare_for_errors_on model
|
11
|
+
errors = mock 'errors'
|
12
|
+
errors.should_receive(:full_messages).and_return([])
|
13
|
+
model.should_receive(:errors).and_return(errors)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Shortcut to create a mock model that is prepared for a ActiveRecord::RecordInvalid.new(@model) call
|
17
|
+
# Equivalent to:
|
18
|
+
# @model = mock_model Model, :some => :fields
|
19
|
+
# prepare_for_errors_on @model
|
20
|
+
def invalid_model class_name, stubs = {}
|
21
|
+
model = mock_model class_name, stubs
|
22
|
+
prepare_for_errors_on model
|
23
|
+
return model
|
24
|
+
end
|
25
|
+
|
26
|
+
# Shortcut to create a model that will be used in an association
|
27
|
+
# Example:
|
28
|
+
# @model = MasterModel.create!
|
29
|
+
# @mock = associated_model ChildModel, :some => :value
|
30
|
+
# @model.children << @mock
|
31
|
+
def associated_model class_name, stubs = {}
|
32
|
+
mock_model class_name, stubs.merge(:[]= => true, :save => true)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/responses.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Module with a set of matchers for examining ActionController::Response objects
|
3
|
+
=end
|
4
|
+
module ResponseMatchers
|
5
|
+
# test for a 201 response
|
6
|
+
def be_successfully_created
|
7
|
+
ResponseStatusMatcher.new "201 Created"
|
8
|
+
end
|
9
|
+
|
10
|
+
# test for a 422 response
|
11
|
+
def be_unprocessable
|
12
|
+
ResponseStatusMatcher.new "422 Unprocessable Entity"
|
13
|
+
end
|
14
|
+
|
15
|
+
# test for a 404 response
|
16
|
+
def be_not_found
|
17
|
+
ResponseStatusMatcher.new "404 Not Found"
|
18
|
+
end
|
19
|
+
|
20
|
+
# test for a 401 response
|
21
|
+
def be_unauthorised
|
22
|
+
ResponseStatusMatcher.new "401 Unauthorized"
|
23
|
+
end
|
24
|
+
alias :be_unauthorized :be_unauthorised
|
25
|
+
|
26
|
+
# test for a 406 response
|
27
|
+
def be_not_acceptable
|
28
|
+
ResponseStatusMatcher.new "406 Not Acceptable"
|
29
|
+
end
|
30
|
+
|
31
|
+
# test for a 500 internal server error
|
32
|
+
def be_an_error
|
33
|
+
ResponseStatusMatcher.new "500 Internal Error"
|
34
|
+
end
|
35
|
+
|
36
|
+
# test that the location points to a given URI
|
37
|
+
def point_to url
|
38
|
+
ResponseLocationMatcher.new url
|
39
|
+
end
|
40
|
+
|
41
|
+
# Response matcher that examines ActionController::Response headers for the required status code
|
42
|
+
class ResponseStatusMatcher
|
43
|
+
# Set up this matcher as required
|
44
|
+
def initialize status_code
|
45
|
+
@status_code = status_code
|
46
|
+
end
|
47
|
+
|
48
|
+
# Does the given target object match the required status code?
|
49
|
+
def matches? target
|
50
|
+
(@target_status = target.status) == @status_code
|
51
|
+
end
|
52
|
+
|
53
|
+
# What do we tell the user when it fails?
|
54
|
+
def failure_message
|
55
|
+
a = <<-EOF
|
56
|
+
expected the location header to be #{@status_code.inspect}
|
57
|
+
instead it was #{@target_status.inspect}
|
58
|
+
EOF
|
59
|
+
end
|
60
|
+
|
61
|
+
# What do we tell the user when it shouldn't fail but does
|
62
|
+
def negative_failure_message
|
63
|
+
"expected the response to be different to #{@status_code.inspect}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Response matcher that examines ActionController::Response headers for the given location code
|
68
|
+
class ResponseLocationMatcher
|
69
|
+
def initialize url
|
70
|
+
@url = url
|
71
|
+
end
|
72
|
+
|
73
|
+
# Does the given target object match the required location?
|
74
|
+
def matches? target
|
75
|
+
(@target_url = target.headers['Location']) == @url
|
76
|
+
end
|
77
|
+
|
78
|
+
# What do we tell the user when it fails?
|
79
|
+
def failure_message
|
80
|
+
a = <<-EOF
|
81
|
+
expected the location header to be #{@target_url.inspect}
|
82
|
+
instead it was #{@url.inspect}
|
83
|
+
EOF
|
84
|
+
end
|
85
|
+
|
86
|
+
# What do we tell the user when it shouldn't fail but does
|
87
|
+
def negative_failure_message
|
88
|
+
"expected the location header to be different to #{@url.inspect}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/lib/use_layout.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
=begin rdoc
|
2
|
+
Module for testing the layout used in a response object
|
3
|
+
=end
|
4
|
+
module ResponseMatchers
|
5
|
+
# From http://rubyforge.org/pipermail/rspec-users/2007-May/001818.html
|
6
|
+
class UseLayout
|
7
|
+
def initialize(expected)
|
8
|
+
@expected = 'layouts/' + expected
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?(controller)
|
12
|
+
@actual = controller.layout
|
13
|
+
#@actual.equal?(@expected)
|
14
|
+
@actual == @expected
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure_message
|
18
|
+
return "use_layout expected #{@expected.inspect}, got #{@actual.inspect}", @expected, @actual
|
19
|
+
end
|
20
|
+
|
21
|
+
def negeative_failure_message
|
22
|
+
return "use_layout expected #{@expected.inspect} not to equal #{@actual.inspect}", @expected, @actual
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def use_layout(expected)
|
27
|
+
UseLayout.new(expected)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{rspec-rails-ext}
|
5
|
+
s.version = "1.7.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Rahoul Baruah, Caius Durling"]
|
9
|
+
s.date = %q{2009-11-10}
|
10
|
+
s.description = %q{Helpers for prettying up your RSpec-Rails specifications}
|
11
|
+
s.email = %q{support@brightbox.co.uk}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "README.rdoc", "lib/controller_example_group.rb", "lib/mocks.rb", "lib/responses.rb", "lib/rspec_rails_extensions.rb", "lib/use_layout.rb"]
|
13
|
+
s.files = ["CHANGELOG", "LICENCE", "Manifest", "README.rdoc", "Rakefile", "lib/controller_example_group.rb", "lib/mocks.rb", "lib/responses.rb", "lib/rspec_rails_extensions.rb", "lib/use_layout.rb", "rspec-rails-ext.gemspec"]
|
14
|
+
s.homepage = %q{http://github.com/brightbox/rspec-rails-extensions/tree/master}
|
15
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rspec-rails-ext", "--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{rspec-rails-ext}
|
18
|
+
s.rubygems_version = %q{1.3.5}
|
19
|
+
s.summary = %q{Helpers for prettying up your RSpec-Rails specifications}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
else
|
27
|
+
end
|
28
|
+
else
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-rails-ext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.7.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rahoul Baruah, Caius Durling
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-10 00:00:00 +00:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Helpers for prettying up your RSpec-Rails specifications
|
17
|
+
email: support@brightbox.co.uk
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- README.rdoc
|
25
|
+
- lib/controller_example_group.rb
|
26
|
+
- lib/mocks.rb
|
27
|
+
- lib/responses.rb
|
28
|
+
- lib/rspec_rails_extensions.rb
|
29
|
+
- lib/use_layout.rb
|
30
|
+
files:
|
31
|
+
- CHANGELOG
|
32
|
+
- LICENCE
|
33
|
+
- Manifest
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- lib/controller_example_group.rb
|
37
|
+
- lib/mocks.rb
|
38
|
+
- lib/responses.rb
|
39
|
+
- lib/rspec_rails_extensions.rb
|
40
|
+
- lib/use_layout.rb
|
41
|
+
- rspec-rails-ext.gemspec
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://github.com/brightbox/rspec-rails-extensions/tree/master
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --line-numbers
|
49
|
+
- --inline-source
|
50
|
+
- --title
|
51
|
+
- Rspec-rails-ext
|
52
|
+
- --main
|
53
|
+
- README.rdoc
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "1.2"
|
67
|
+
version:
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project: rspec-rails-ext
|
71
|
+
rubygems_version: 1.3.5
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Helpers for prettying up your RSpec-Rails specifications
|
75
|
+
test_files: []
|
76
|
+
|