thoughtbot-shoulda 2.9.1 → 2.9.2
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/README.rdoc +27 -5
- data/Rakefile +2 -2
- data/lib/shoulda.rb +1 -1
- data/lib/shoulda/{controller.rb → action_controller.rb} +6 -8
- data/lib/shoulda/{controller → action_controller}/helpers.rb +1 -16
- data/lib/shoulda/action_controller/macros.rb +277 -0
- data/lib/shoulda/action_controller/matchers.rb +37 -0
- data/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
- data/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
- data/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
- data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
- data/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +81 -0
- data/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
- data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +83 -0
- data/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
- data/lib/shoulda/action_view.rb +10 -0
- data/lib/shoulda/action_view/macros.rb +56 -0
- data/lib/shoulda/active_record/macros.rb +8 -13
- data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +1 -1
- data/lib/shoulda/rails.rb +4 -3
- data/lib/shoulda/rspec.rb +7 -5
- data/test/functional/posts_controller_test.rb +28 -22
- data/test/functional/users_controller_test.rb +0 -19
- data/test/matchers/{allow_mass_assignment_of_matcher_test.rb → active_record/allow_mass_assignment_of_matcher_test.rb} +1 -1
- data/test/matchers/{allow_value_matcher_test.rb → active_record/allow_value_matcher_test.rb} +1 -1
- data/test/matchers/{association_matcher_test.rb → active_record/association_matcher_test.rb} +1 -1
- data/test/matchers/{ensure_inclusion_of_matcher_test.rb → active_record/ensure_inclusion_of_matcher_test.rb} +1 -1
- data/test/matchers/{ensure_length_of_matcher_test.rb → active_record/ensure_length_of_matcher_test.rb} +1 -1
- data/test/matchers/{have_db_column_matcher_test.rb → active_record/have_db_column_matcher_test.rb} +1 -1
- data/test/matchers/{have_index_matcher_test.rb → active_record/have_index_matcher_test.rb} +1 -1
- data/test/matchers/{have_named_scope_matcher_test.rb → active_record/have_named_scope_matcher_test.rb} +1 -1
- data/test/matchers/{have_readonly_attributes_matcher_test.rb → active_record/have_readonly_attributes_matcher_test.rb} +1 -1
- data/test/matchers/{validate_acceptance_of_matcher_test.rb → active_record/validate_acceptance_of_matcher_test.rb} +1 -1
- data/test/matchers/{validate_numericality_of_matcher_test.rb → active_record/validate_numericality_of_matcher_test.rb} +1 -1
- data/test/matchers/{validate_presence_of_matcher_test.rb → active_record/validate_presence_of_matcher_test.rb} +1 -1
- data/test/matchers/{validate_uniqueness_of_matcher_test.rb → active_record/validate_uniqueness_of_matcher_test.rb} +8 -2
- data/test/matchers/controller/assign_to_matcher_test.rb +35 -0
- data/test/matchers/controller/filter_param_matcher_test.rb +32 -0
- data/test/matchers/controller/render_with_layout_matcher_test.rb +33 -0
- data/test/matchers/controller/respond_with_content_type_matcher_test.rb +27 -0
- data/test/matchers/controller/respond_with_matcher_test.rb +106 -0
- data/test/matchers/controller/route_matcher_test.rb +58 -0
- data/test/matchers/controller/set_session_matcher_test.rb +27 -0
- data/test/matchers/controller/set_the_flash_matcher.rb +41 -0
- data/test/model_builder.rb +47 -2
- data/test/rails_root/app/models/user.rb +2 -1
- data/test/rails_root/config/environment.rb +1 -1
- data/test/rspec_test.rb +207 -0
- data/test/unit/user_test.rb +10 -1
- metadata +43 -24
- data/lib/shoulda/controller/formats/html.rb +0 -199
- data/lib/shoulda/controller/formats/xml.rb +0 -168
- data/lib/shoulda/controller/macros.rb +0 -336
- data/lib/shoulda/controller/resource_options.rb +0 -233
@@ -0,0 +1,83 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures that a session key was set to the expected value.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# it { should set_session(:message) }
|
10
|
+
# it { should set_session(:user_id).to(@user.id) }
|
11
|
+
# it { should_not set_session(:user_id) }
|
12
|
+
def set_session(key)
|
13
|
+
SetSessionMatcher.new(key)
|
14
|
+
end
|
15
|
+
|
16
|
+
class SetSessionMatcher # :nodoc:
|
17
|
+
|
18
|
+
def initialize(key)
|
19
|
+
@key = key.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def to(value)
|
23
|
+
@value = value
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def matches?(controller)
|
28
|
+
@controller = controller
|
29
|
+
assigned_value? && assigned_correct_value?
|
30
|
+
end
|
31
|
+
|
32
|
+
def failure_message
|
33
|
+
"Expected #{expectation}, but #{result}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def negative_failure_message
|
37
|
+
"Didn't expect #{expectation}, but #{result}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def description
|
41
|
+
description = "set session variable #{@key.inspect}"
|
42
|
+
description << " to #{@value.inspect}" if @value
|
43
|
+
description
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def assigned_value?
|
49
|
+
!assigned_value.blank?
|
50
|
+
end
|
51
|
+
|
52
|
+
def assigned_correct_value?
|
53
|
+
return true if @value.nil?
|
54
|
+
assigned_value == @value
|
55
|
+
end
|
56
|
+
|
57
|
+
def assigned_value
|
58
|
+
session[@key]
|
59
|
+
end
|
60
|
+
|
61
|
+
def session
|
62
|
+
@controller.response.session.data
|
63
|
+
end
|
64
|
+
|
65
|
+
def expectation
|
66
|
+
expectation = "session variable #{@key} to be set"
|
67
|
+
expectation << " to #{@value.inspect}" if @value
|
68
|
+
expectation
|
69
|
+
end
|
70
|
+
|
71
|
+
def result
|
72
|
+
if session.empty?
|
73
|
+
"no session variables were set"
|
74
|
+
else
|
75
|
+
"the session was #{session.inspect}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures that the flash contains the given value. Can be a String, a
|
6
|
+
# Regexp, or nil (indicating that the flash should not be set).
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# it { should set_the_flash }
|
11
|
+
# it { should set_the_flash.to("Thank you for placing this order.") }
|
12
|
+
# it { should set_the_flash.to(/created/i) }
|
13
|
+
# it { should_not set_the_flash }
|
14
|
+
def set_the_flash
|
15
|
+
SetTheFlashMatcher.new
|
16
|
+
end
|
17
|
+
|
18
|
+
class SetTheFlashMatcher # :nodoc:
|
19
|
+
|
20
|
+
def to(value)
|
21
|
+
@value = value
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def matches?(controller)
|
26
|
+
@controller = controller
|
27
|
+
sets_the_flash? && string_value_matches? && regexp_value_matches?
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :failure_message, :negative_failure_message
|
31
|
+
|
32
|
+
def description
|
33
|
+
description = "set the flash"
|
34
|
+
description << " to #{@value.inspect}" unless @value.nil?
|
35
|
+
description
|
36
|
+
end
|
37
|
+
|
38
|
+
def failure_message
|
39
|
+
"Expected #{expectation}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def negative_failure_message
|
43
|
+
"Did not expect #{expectation}"
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def sets_the_flash?
|
49
|
+
!flash.blank?
|
50
|
+
end
|
51
|
+
|
52
|
+
def string_value_matches?
|
53
|
+
return true unless String === @value
|
54
|
+
flash.values.any? {|value| value == @value }
|
55
|
+
end
|
56
|
+
|
57
|
+
def regexp_value_matches?
|
58
|
+
return true unless Regexp === @value
|
59
|
+
flash.values.any? {|value| value =~ @value }
|
60
|
+
end
|
61
|
+
|
62
|
+
def flash
|
63
|
+
@controller.response.session['flash']
|
64
|
+
end
|
65
|
+
|
66
|
+
def expectation
|
67
|
+
expectation = "the flash to be set"
|
68
|
+
expectation << " to #{@value.inspect}" unless @value.nil?
|
69
|
+
expectation << ", but #{flash_description}"
|
70
|
+
expectation
|
71
|
+
end
|
72
|
+
|
73
|
+
def flash_description
|
74
|
+
if flash.blank?
|
75
|
+
"no flash was set"
|
76
|
+
else
|
77
|
+
"was #{flash.inspect}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionView # :nodoc:
|
3
|
+
# = Macro test helpers for your view
|
4
|
+
#
|
5
|
+
# By using the macro helpers you can quickly and easily create concise and
|
6
|
+
# easy to read test suites.
|
7
|
+
#
|
8
|
+
# This code segment:
|
9
|
+
# context "on GET to :new" do
|
10
|
+
# setup do
|
11
|
+
# get :new
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# should_render_a_form
|
15
|
+
# should_render_page_with_metadata :title => /index/
|
16
|
+
#
|
17
|
+
# should "do something else really cool" do
|
18
|
+
# assert_select '#really_cool'
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Would produce 3 tests for the +show+ action
|
23
|
+
module Macros
|
24
|
+
|
25
|
+
# Macro that creates a test asserting that the rendered view contains a <form> element.
|
26
|
+
def should_render_a_form
|
27
|
+
should "display a form" do
|
28
|
+
assert_select "form", true, "The template doesn't contain a <form> element"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Macro that creates a test asserting that the rendered view contains the selected metatags.
|
33
|
+
# Values can be string or Regexps.
|
34
|
+
# Example:
|
35
|
+
#
|
36
|
+
# should_render_page_with_metadata :description => "Description of this page", :keywords => /post/
|
37
|
+
#
|
38
|
+
# You can also use this method to test the rendered views title.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
# should_render_page_with_metadata :title => /index/
|
42
|
+
def should_render_page_with_metadata(options)
|
43
|
+
options.each do |key, value|
|
44
|
+
should "have metatag #{key}" do
|
45
|
+
if key.to_sym == :title
|
46
|
+
assert_select "title", value
|
47
|
+
else
|
48
|
+
assert_select "meta[name=?][content#{"*" if value.is_a?(Regexp)}=?]", key, value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -23,14 +23,6 @@ module Shoulda # :nodoc:
|
|
23
23
|
include Helpers
|
24
24
|
include Matchers
|
25
25
|
|
26
|
-
# <b>DEPRECATED:</b> Use <tt>fixtures :all</tt> instead
|
27
|
-
#
|
28
|
-
# Loads all fixture files (<tt>test/fixtures/*.yml</tt>)
|
29
|
-
def load_all_fixtures
|
30
|
-
warn "[DEPRECATION] load_all_fixtures is deprecated. Use `fixtures :all` instead."
|
31
|
-
fixtures :all
|
32
|
-
end
|
33
|
-
|
34
26
|
# Ensures that the model cannot be saved if one of the attributes listed is not present.
|
35
27
|
#
|
36
28
|
# If an instance variable has been created in the setup named after the
|
@@ -304,13 +296,16 @@ module Shoulda # :nodoc:
|
|
304
296
|
# should_ensure_value_in_range :age, (0..100)
|
305
297
|
#
|
306
298
|
def should_ensure_value_in_range(attribute, range, opts = {})
|
307
|
-
message = get_options!([opts],
|
308
|
-
|
309
|
-
|
299
|
+
message, low_message, high_message = get_options!([opts],
|
300
|
+
:message,
|
301
|
+
:low_message,
|
302
|
+
:high_message)
|
310
303
|
klass = model_class
|
311
304
|
matcher = ensure_inclusion_of(attribute).
|
312
305
|
in_range(range).
|
313
|
-
with_message(message)
|
306
|
+
with_message(message).
|
307
|
+
with_low_message(low_message).
|
308
|
+
with_high_message(high_message)
|
314
309
|
should matcher.description do
|
315
310
|
assert_accepts matcher, get_instance_of(klass)
|
316
311
|
end
|
@@ -341,7 +336,7 @@ module Shoulda # :nodoc:
|
|
341
336
|
end
|
342
337
|
end
|
343
338
|
|
344
|
-
# Deprecated. See
|
339
|
+
# Deprecated. See should_validate_numericality_of
|
345
340
|
def should_only_allow_numeric_values_for(*attributes)
|
346
341
|
warn "[DEPRECATION] should_only_allow_numeric_values_for is " <<
|
347
342
|
"deprecated. Use should_validate_numericality_of instead."
|
data/lib/shoulda/rails.rb
CHANGED
@@ -2,9 +2,10 @@ require 'rubygems'
|
|
2
2
|
require 'active_support'
|
3
3
|
require 'shoulda'
|
4
4
|
|
5
|
-
require 'shoulda/active_record'
|
6
|
-
require 'shoulda/
|
7
|
-
require 'shoulda/
|
5
|
+
require 'shoulda/active_record' if defined? ActiveRecord::Base
|
6
|
+
require 'shoulda/action_controller' if defined? ActionController::Base
|
7
|
+
require 'shoulda/action_view' if defined? ActionView::Base
|
8
|
+
require 'shoulda/action_mailer' if defined? ActionMailer::Base
|
8
9
|
|
9
10
|
if defined?(RAILS_ROOT)
|
10
11
|
# load in the 3rd party macros from vendorized plugins and gems
|
data/lib/shoulda/rspec.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'shoulda/active_record/matchers'
|
2
|
+
require 'shoulda/action_controller/matchers'
|
3
|
+
require 'active_support/test_case'
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# :enddoc:
|
6
|
+
module ActiveSupport
|
7
|
+
class TestCase
|
8
|
+
include Shoulda::ActiveRecord::Matchers
|
9
|
+
include Shoulda::ActionController::Matchers
|
8
10
|
end
|
9
11
|
end
|
@@ -33,44 +33,27 @@ class PostsControllerTest < Test::Unit::TestCase
|
|
33
33
|
should_route :get, '/users/5/posts/new', :action => :new, :user_id => 5
|
34
34
|
should_route :put, '/users/5/posts/1', :action => :update, :id => 1, :user_id => 5
|
35
35
|
|
36
|
-
context "The public" do
|
37
|
-
setup do
|
38
|
-
@request.session[:logged_in] = false
|
39
|
-
end
|
40
|
-
|
41
|
-
should_be_restful do |resource|
|
42
|
-
resource.parent = :user
|
43
|
-
|
44
|
-
resource.denied.actions = [:index, :show, :edit, :new, :create, :update, :destroy]
|
45
|
-
resource.denied.flash = /what/i
|
46
|
-
resource.denied.redirect = '"/"'
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
36
|
context "Logged in" do
|
51
37
|
setup do
|
52
38
|
@request.session[:logged_in] = true
|
53
39
|
end
|
54
40
|
|
55
|
-
should_be_restful do |resource|
|
56
|
-
resource.parent = :user
|
57
|
-
|
58
|
-
resource.create.params = { :title => "first post", :body => 'blah blah blah'}
|
59
|
-
resource.update.params = { :title => "changed" }
|
60
|
-
end
|
61
|
-
|
62
41
|
context "viewing posts for a user" do
|
63
42
|
setup do
|
64
43
|
get :index, :user_id => users(:first)
|
65
44
|
end
|
66
45
|
should_respond_with :success
|
67
46
|
should_assign_to :user, :class => User, :equals => 'users(:first)'
|
47
|
+
should_assign_to(:user) { users(:first) }
|
68
48
|
should_fail do
|
69
49
|
should_assign_to :user, :class => Post
|
70
50
|
end
|
71
51
|
should_fail do
|
72
52
|
should_assign_to :user, :equals => 'posts(:first)'
|
73
53
|
end
|
54
|
+
should_fail do
|
55
|
+
should_assign_to(:user) { posts(:first) }
|
56
|
+
end
|
74
57
|
should_assign_to :posts
|
75
58
|
should_not_assign_to :foo, :bar
|
76
59
|
should_render_page_with_metadata :description => /Posts/, :title => /index/
|
@@ -87,7 +70,12 @@ class PostsControllerTest < Test::Unit::TestCase
|
|
87
70
|
should_respond_with_content_type :rss
|
88
71
|
should_respond_with_content_type /rss/
|
89
72
|
should_return_from_session :special, "'$2 off your next purchase'"
|
90
|
-
|
73
|
+
should_set_session :special, "'$2 off your next purchase'"
|
74
|
+
should_set_session :special_user_id, '@user.id'
|
75
|
+
should_set_session(:special_user_id) { @user.id }
|
76
|
+
should_fail do
|
77
|
+
should_set_session(:special_user_id) { 'value' }
|
78
|
+
end
|
91
79
|
should_assign_to :user, :posts
|
92
80
|
should_not_assign_to :foo, :bar
|
93
81
|
end
|
@@ -103,6 +91,24 @@ class PostsControllerTest < Test::Unit::TestCase
|
|
103
91
|
setup { get :new, :user_id => users(:first) }
|
104
92
|
should_render_without_layout
|
105
93
|
end
|
94
|
+
|
95
|
+
context "on POST to #create" do
|
96
|
+
setup do
|
97
|
+
post :create, :user_id => users(:first),
|
98
|
+
:post => { :title => "first post",
|
99
|
+
:body => 'blah blah blah' }
|
100
|
+
end
|
101
|
+
|
102
|
+
should_redirect_to 'user_post_url(@post.user, @post)'
|
103
|
+
should_redirect_to('the created post') { user_post_url(users(:first),
|
104
|
+
assigns(:post)) }
|
105
|
+
should_fail do
|
106
|
+
should_redirect_to 'user_posts_url(@post.user)'
|
107
|
+
end
|
108
|
+
should_fail do
|
109
|
+
should_redirect_to('elsewhere') { user_posts_url(users(:first)) }
|
110
|
+
end
|
111
|
+
end
|
106
112
|
end
|
107
113
|
|
108
114
|
end
|
@@ -16,23 +16,4 @@ class UsersControllerTest < Test::Unit::TestCase
|
|
16
16
|
|
17
17
|
should_filter_params :ssn
|
18
18
|
|
19
|
-
should_be_restful do |resource|
|
20
|
-
resource.identifier = :id
|
21
|
-
resource.klass = User
|
22
|
-
resource.object = :user
|
23
|
-
resource.parent = []
|
24
|
-
resource.actions = [:index, :show, :new, :edit, :update, :create, :destroy]
|
25
|
-
resource.formats = [:html, :xml]
|
26
|
-
|
27
|
-
resource.create.params = { :name => "bob", :email => 'bob@bob.com', :age => 13, :ssn => "123456789"}
|
28
|
-
resource.update.params = { :name => "sue" }
|
29
|
-
|
30
|
-
resource.create.redirect = "user_url(@user)"
|
31
|
-
resource.update.redirect = "user_url(@user)"
|
32
|
-
resource.destroy.redirect = "users_url"
|
33
|
-
|
34
|
-
resource.create.flash = /created/i
|
35
|
-
resource.update.flash = /updated/i
|
36
|
-
resource.destroy.flash = /removed/i
|
37
|
-
end
|
38
19
|
end
|