francois-shoulda 2.0.5.4 → 2.10.1
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 +60 -10
- data/Rakefile +7 -7
- data/lib/shoulda.rb +7 -15
- data/lib/shoulda/action_controller.rb +28 -0
- data/lib/shoulda/action_controller/helpers.rb +47 -0
- 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 +87 -0
- data/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
- data/lib/shoulda/action_mailer.rb +1 -1
- data/lib/shoulda/action_mailer/assertions.rb +32 -33
- data/lib/shoulda/action_view.rb +10 -0
- data/lib/shoulda/action_view/macros.rb +56 -0
- data/lib/shoulda/active_record.rb +6 -2
- data/lib/shoulda/active_record/assertions.rb +62 -89
- data/lib/shoulda/active_record/helpers.rb +40 -0
- data/lib/shoulda/active_record/macros.rb +520 -684
- data/lib/shoulda/active_record/matchers.rb +42 -0
- data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
- data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
- data/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
- data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
- data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
- data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
- data/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
- data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
- data/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
- data/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
- data/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
- data/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
- data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
- data/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
- data/lib/shoulda/assertions.rb +50 -40
- data/lib/shoulda/autoload_macros.rb +46 -0
- data/lib/shoulda/context.rb +124 -126
- data/lib/shoulda/helpers.rb +5 -7
- data/lib/shoulda/macros.rb +63 -64
- data/lib/shoulda/private_helpers.rb +16 -18
- data/lib/shoulda/rails.rb +5 -11
- data/lib/shoulda/rspec.rb +11 -0
- data/lib/shoulda/tasks/list_tests.rake +6 -1
- data/lib/shoulda/test_unit.rb +19 -0
- data/rails/init.rb +7 -1
- data/test/README +2 -2
- data/test/fail_macros.rb +15 -15
- data/test/fixtures/tags.yml +1 -1
- data/test/functional/posts_controller_test.rb +46 -26
- data/test/functional/users_controller_test.rb +0 -19
- data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +68 -0
- data/test/matchers/active_record/allow_value_matcher_test.rb +41 -0
- data/test/matchers/active_record/association_matcher_test.rb +258 -0
- data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +80 -0
- data/test/matchers/active_record/ensure_length_of_matcher_test.rb +158 -0
- data/test/matchers/active_record/have_db_column_matcher_test.rb +169 -0
- data/test/matchers/active_record/have_index_matcher_test.rb +74 -0
- data/test/matchers/active_record/have_named_scope_matcher_test.rb +65 -0
- data/test/matchers/active_record/have_readonly_attributes_matcher_test.rb +29 -0
- data/test/matchers/active_record/validate_acceptance_of_matcher_test.rb +44 -0
- data/test/matchers/active_record/validate_numericality_of_matcher_test.rb +52 -0
- data/test/matchers/active_record/validate_presence_of_matcher_test.rb +86 -0
- data/test/matchers/active_record/validate_uniqueness_of_matcher_test.rb +147 -0
- 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 +31 -0
- data/test/matchers/controller/set_the_flash_matcher.rb +41 -0
- data/test/model_builder.rb +106 -0
- data/test/other/autoload_macro_test.rb +18 -0
- data/test/other/helpers_test.rb +58 -0
- data/test/other/private_helpers_test.rb +1 -1
- data/test/other/should_test.rb +16 -16
- data/test/rails_root/app/controllers/posts_controller.rb +6 -5
- data/test/rails_root/app/models/pets/dog.rb +10 -0
- data/test/rails_root/app/models/treat.rb +3 -0
- data/test/rails_root/app/models/user.rb +4 -3
- data/test/rails_root/app/views/layouts/posts.rhtml +2 -0
- data/test/rails_root/config/database.yml +1 -1
- data/test/rails_root/config/environment.rb +1 -1
- data/test/rails_root/config/environments/{sqlite3.rb → test.rb} +0 -0
- data/test/rails_root/db/migrate/001_create_users.rb +3 -2
- data/test/rails_root/db/migrate/011_create_treats.rb +12 -0
- data/test/rails_root/test/shoulda_macros/custom_macro.rb +6 -0
- data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +6 -0
- data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +6 -0
- data/test/rspec_test.rb +207 -0
- data/test/test_helper.rb +3 -1
- data/test/unit/address_test.rb +1 -23
- data/test/unit/dog_test.rb +5 -2
- data/test/unit/post_test.rb +7 -3
- data/test/unit/product_test.rb +2 -2
- data/test/unit/tag_test.rb +2 -1
- data/test/unit/user_test.rb +25 -9
- metadata +84 -23
- data/lib/shoulda/controller.rb +0 -30
- data/lib/shoulda/controller/formats/html.rb +0 -201
- data/lib/shoulda/controller/formats/xml.rb +0 -170
- data/lib/shoulda/controller/helpers.rb +0 -64
- data/lib/shoulda/controller/macros.rb +0 -316
- data/lib/shoulda/controller/resource_options.rb +0 -236
- data/test/rails_root/app/models/dog.rb +0 -5
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'shoulda/action_controller/matchers/assign_to_matcher'
|
2
|
+
require 'shoulda/action_controller/matchers/filter_param_matcher'
|
3
|
+
require 'shoulda/action_controller/matchers/set_the_flash_matcher'
|
4
|
+
require 'shoulda/action_controller/matchers/render_with_layout_matcher'
|
5
|
+
require 'shoulda/action_controller/matchers/respond_with_matcher'
|
6
|
+
require 'shoulda/action_controller/matchers/respond_with_content_type_matcher'
|
7
|
+
require 'shoulda/action_controller/matchers/set_session_matcher'
|
8
|
+
require 'shoulda/action_controller/matchers/route_matcher'
|
9
|
+
|
10
|
+
module Shoulda # :nodoc:
|
11
|
+
module ActionController # :nodoc:
|
12
|
+
|
13
|
+
# By using the macro helpers you can quickly and easily create concise and
|
14
|
+
# easy to read test suites.
|
15
|
+
#
|
16
|
+
# This code segment:
|
17
|
+
#
|
18
|
+
# describe UsersController, "on GET to show with a valid id" do
|
19
|
+
# before(:each) do
|
20
|
+
# get :show, :id => User.first.to_param
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# it { should assign_to(:user) }
|
24
|
+
# it { should respond_with(:success) }
|
25
|
+
# it { should render_template(:show) }
|
26
|
+
# it { should not_set_the_flash) }
|
27
|
+
#
|
28
|
+
# it "should do something else really cool" do
|
29
|
+
# assigns[:user].id.should == 1
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Would produce 5 tests for the show action
|
34
|
+
module Matchers
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures that the controller assigned to the named instance variable.
|
6
|
+
#
|
7
|
+
# Options:
|
8
|
+
# * <tt>with_kind_of</tt> - The expected class of the instance variable
|
9
|
+
# being checked.
|
10
|
+
# * <tt>with</tt> - The value that should be assigned.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
#
|
14
|
+
# it { should assign_to(:user) }
|
15
|
+
# it { should_not assign_to(:user) }
|
16
|
+
# it { should assign_to(:user).with_kind_of(User) }
|
17
|
+
# it { should assign_to(:user).with(@user) }
|
18
|
+
def assign_to(variable)
|
19
|
+
AssignToMatcher.new(variable)
|
20
|
+
end
|
21
|
+
|
22
|
+
class AssignToMatcher # :nodoc:
|
23
|
+
|
24
|
+
def initialize(variable)
|
25
|
+
@variable = variable.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
def with_kind_of(expected_class)
|
29
|
+
@expected_class = expected_class
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def with(expected_value)
|
34
|
+
@expected_value = expected_value
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def matches?(controller)
|
39
|
+
@controller = controller
|
40
|
+
assigned_value? && kind_of_expected_class? && equal_to_expected_value?
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :failure_message, :negative_failure_message
|
44
|
+
|
45
|
+
def description
|
46
|
+
description = "assign @#{@variable}"
|
47
|
+
description << " with a kind of #{@expected_class}" if @expected_class
|
48
|
+
description
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def assigned_value?
|
54
|
+
if assigned_value.nil?
|
55
|
+
@failure_message =
|
56
|
+
"Expected action to assign a value for @#{@variable}"
|
57
|
+
false
|
58
|
+
else
|
59
|
+
@negative_failure_message =
|
60
|
+
"Didn't expect action to assign a value for @#{@variable}, " <<
|
61
|
+
"but it was assigned to #{assigned_value.inspect}"
|
62
|
+
true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def kind_of_expected_class?
|
67
|
+
return true unless @expected_class
|
68
|
+
if assigned_value.kind_of?(@expected_class)
|
69
|
+
@negative_failure_message =
|
70
|
+
"Didn't expect action to assign a kind of #{@expected_class} " <<
|
71
|
+
"for #{@variable}, but got one anyway"
|
72
|
+
true
|
73
|
+
else
|
74
|
+
@failure_message =
|
75
|
+
"Expected action to assign a kind of #{@expected_class} " <<
|
76
|
+
"for #{@variable}, but got #{@variable.inspect} " <<
|
77
|
+
"(#{@variable.class.name})"
|
78
|
+
false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def equal_to_expected_value?
|
83
|
+
return true unless @expected_value
|
84
|
+
if @expected_value == assigned_value
|
85
|
+
@negative_failure_message =
|
86
|
+
"Didn't expect action to assign #{@expected_value.inspect} " <<
|
87
|
+
"for #{@variable}, but got it anyway"
|
88
|
+
true
|
89
|
+
else
|
90
|
+
@failure_message =
|
91
|
+
"Expected action to assign #{@expected_value.inspect} " <<
|
92
|
+
"for #{@variable}, but got #{assigned_value.inspect}"
|
93
|
+
false
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def assigned_value
|
98
|
+
assigns[@variable]
|
99
|
+
end
|
100
|
+
|
101
|
+
def assigns
|
102
|
+
@controller.response.template.assigns
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures that filter_parameter_logging is set for the specified key.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# it { should filter_param(:password) }
|
10
|
+
def filter_param(key)
|
11
|
+
FilterParamMatcher.new(key)
|
12
|
+
end
|
13
|
+
|
14
|
+
class FilterParamMatcher # :nodoc:
|
15
|
+
|
16
|
+
def initialize(key)
|
17
|
+
@key = key.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches?(controller)
|
21
|
+
@controller = controller
|
22
|
+
filters_params? && filters_key?
|
23
|
+
end
|
24
|
+
|
25
|
+
def failure_message
|
26
|
+
"Expected #{@key} to be filtered"
|
27
|
+
end
|
28
|
+
|
29
|
+
def negative_failure_message
|
30
|
+
"Did not expect #{@key} to be filtered"
|
31
|
+
end
|
32
|
+
|
33
|
+
def description
|
34
|
+
"filter #{@key}"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def filters_params?
|
40
|
+
@controller.respond_to?(:filter_parameters)
|
41
|
+
end
|
42
|
+
|
43
|
+
def filters_key?
|
44
|
+
filtered_value == '[FILTERED]'
|
45
|
+
end
|
46
|
+
|
47
|
+
def filtered_value
|
48
|
+
filtered = @controller.send(:filter_parameters,
|
49
|
+
@key.to_s => @key.to_s)
|
50
|
+
filtered[@key.to_s]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures that the controller rendered with the given layout.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# it { should render_with_layout }
|
10
|
+
# it { should render_with_layout(:special) }
|
11
|
+
# it { should_not render_with_layout }
|
12
|
+
def render_with_layout(layout = nil)
|
13
|
+
RenderWithLayout.new(layout)
|
14
|
+
end
|
15
|
+
|
16
|
+
class RenderWithLayout # :nodoc:
|
17
|
+
|
18
|
+
def initialize(layout)
|
19
|
+
@layout = layout.to_s unless layout.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def matches?(controller)
|
23
|
+
@controller = controller
|
24
|
+
rendered_with_layout? && rendered_with_expected_layout?
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message
|
28
|
+
"Expected #{expectation}, but #{result}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def negative_failure_message
|
32
|
+
"Did not expect #{expectation}, but #{result}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def description
|
36
|
+
description = "render with "
|
37
|
+
if @layout.nil?
|
38
|
+
description << "a layout"
|
39
|
+
else
|
40
|
+
description << "the #{@layout.inspect} layout"
|
41
|
+
end
|
42
|
+
description
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def rendered_with_layout?
|
48
|
+
!layout.blank?
|
49
|
+
end
|
50
|
+
|
51
|
+
def rendered_with_expected_layout?
|
52
|
+
return true if @layout.nil?
|
53
|
+
layout == @layout
|
54
|
+
end
|
55
|
+
|
56
|
+
def layout
|
57
|
+
layout = @controller.response.layout
|
58
|
+
if layout.nil?
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
layout.split('/').last
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def expectation
|
66
|
+
"to #{description}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def result
|
70
|
+
if rendered_with_layout?
|
71
|
+
"rendered with the #{layout.inspect} layout"
|
72
|
+
else
|
73
|
+
"rendered without a layout"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures a controller responded with expected 'response' content type.
|
6
|
+
#
|
7
|
+
# You can pass an explicit content type such as 'application/rss+xml'
|
8
|
+
# or its symbolic equivalent :rss
|
9
|
+
# or a regular expression such as /rss/
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# it { should respond_with_content_type(:xml) }
|
14
|
+
# it { should respond_with_content_type(:csv) }
|
15
|
+
# it { should respond_with_content_type(:atom) }
|
16
|
+
# it { should respond_with_content_type(:yaml) }
|
17
|
+
# it { should respond_with_content_type(:text) }
|
18
|
+
# it { should respond_with_content_type('application/rss+xml') }
|
19
|
+
# it { should respond_with_content_type(/json/) }
|
20
|
+
def respond_with_content_type(content_type)
|
21
|
+
RespondWithContentTypeMatcher.new(content_type)
|
22
|
+
end
|
23
|
+
|
24
|
+
class RespondWithContentTypeMatcher # :nodoc:
|
25
|
+
|
26
|
+
def initialize(content_type)
|
27
|
+
@content_type = if content_type.is_a?(Symbol)
|
28
|
+
lookup_by_extension(content_type)
|
29
|
+
else
|
30
|
+
content_type
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def matches?(controller)
|
35
|
+
@controller = controller
|
36
|
+
if @content_type.is_a?(Regexp)
|
37
|
+
response_content_type =~ @content_type
|
38
|
+
else
|
39
|
+
response_content_type == @content_type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def failure_message
|
44
|
+
"Expected #{expectation}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def negative_failure_message
|
48
|
+
"Did not expect #{expectation}"
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def response_content_type
|
54
|
+
@controller.response.content_type
|
55
|
+
end
|
56
|
+
|
57
|
+
def lookup_by_extension(extension)
|
58
|
+
Mime::Type.lookup_by_extension(extension.to_s).to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
def expectation
|
62
|
+
"content type to be #{@content_type}, " <<
|
63
|
+
"but was #{response_content_type}"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures a controller responded with expected 'response' status code.
|
6
|
+
#
|
7
|
+
# You can pass an explicit status number like 200, 301, 404, 500
|
8
|
+
# or its symbolic equivalent :success, :redirect, :missing, :error.
|
9
|
+
# See ActionController::StatusCodes for a full list.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# it { should respond_with(:success) }
|
14
|
+
# it { should respond_with(:redirect) }
|
15
|
+
# it { should respond_with(:missing) }
|
16
|
+
# it { should respond_with(:error) }
|
17
|
+
# it { should respond_with(501) }
|
18
|
+
def respond_with(status)
|
19
|
+
RespondWithMatcher.new(status)
|
20
|
+
end
|
21
|
+
|
22
|
+
class RespondWithMatcher # :nodoc:
|
23
|
+
|
24
|
+
def initialize(status)
|
25
|
+
@status = symbol_to_status_code(status)
|
26
|
+
end
|
27
|
+
|
28
|
+
def matches?(controller)
|
29
|
+
@controller = controller
|
30
|
+
correct_status_code? || correct_status_code_range?
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_message
|
34
|
+
"Expected #{expectation}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def negative_failure_message
|
38
|
+
"Did not expect #{expectation}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def description
|
42
|
+
"respond with #{@status}"
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def correct_status_code?
|
48
|
+
response_code == @status
|
49
|
+
end
|
50
|
+
|
51
|
+
def correct_status_code_range?
|
52
|
+
@status.is_a?(Range) &&
|
53
|
+
@status.include?(response_code)
|
54
|
+
end
|
55
|
+
|
56
|
+
def response_code
|
57
|
+
@controller.response.response_code
|
58
|
+
end
|
59
|
+
|
60
|
+
def symbol_to_status_code(potential_symbol)
|
61
|
+
case potential_symbol
|
62
|
+
when :success then 200
|
63
|
+
when :redirect then 300..399
|
64
|
+
when :missing then 404
|
65
|
+
when :error then 500..599
|
66
|
+
when Symbol
|
67
|
+
::ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE[potential_symbol]
|
68
|
+
else
|
69
|
+
potential_symbol
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def expectation
|
74
|
+
"response to be a #{@status}, but was #{response_code}"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Shoulda # :nodoc:
|
2
|
+
module ActionController # :nodoc:
|
3
|
+
module Matchers
|
4
|
+
|
5
|
+
# Ensures that requesting +path+ using +method+ routes to +options+.
|
6
|
+
#
|
7
|
+
# If you don't specify a controller, it will use the controller from the
|
8
|
+
# example group.
|
9
|
+
#
|
10
|
+
# +to_param+ is called on the +options+ given.
|
11
|
+
#
|
12
|
+
# Examples:
|
13
|
+
#
|
14
|
+
# it { should route(:get, "/posts").
|
15
|
+
# to(:controller => :posts, :action => :index) }
|
16
|
+
# it { should route(:get, "/posts/new").to(:action => :new) }
|
17
|
+
# it { should route(:post, "/posts").to(:action => :create) }
|
18
|
+
# it { should route(:get, "/posts/1").to(:action => :show, :id => 1) }
|
19
|
+
# it { should route(:edit, "/posts/1").to(:action => :show, :id => 1) }
|
20
|
+
# it { should route(:put, "/posts/1").to(:action => :update, :id => 1) }
|
21
|
+
# it { should route(:delete, "/posts/1").
|
22
|
+
# to(:action => :destroy, :id => 1) }
|
23
|
+
# it { should route(:get, "/users/1/posts/1").
|
24
|
+
# to(:action => :show, :id => 1, :user_id => 1) }
|
25
|
+
def route(method, path)
|
26
|
+
RouteMatcher.new(method, path, self)
|
27
|
+
end
|
28
|
+
|
29
|
+
class RouteMatcher # :nodoc:
|
30
|
+
|
31
|
+
def initialize(method, path, context)
|
32
|
+
@method = method
|
33
|
+
@path = path
|
34
|
+
@context = context
|
35
|
+
end
|
36
|
+
|
37
|
+
def to(params)
|
38
|
+
@params = params
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def in_context(context)
|
43
|
+
@context = context
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def matches?(controller)
|
48
|
+
@controller = controller
|
49
|
+
guess_controller!
|
50
|
+
stringify_params!
|
51
|
+
route_recognized?
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_reader :failure_message, :negative_failure_message
|
55
|
+
|
56
|
+
def description
|
57
|
+
"route #{@method.to_s.upcase} #{@path} to/from #{@params.inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def guess_controller!
|
63
|
+
@params[:controller] ||= @controller.controller_path
|
64
|
+
end
|
65
|
+
|
66
|
+
def stringify_params!
|
67
|
+
@params.each do |key, value|
|
68
|
+
@params[key] = value.to_param
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def route_recognized?
|
73
|
+
begin
|
74
|
+
@context.send(:assert_routing,
|
75
|
+
{ :method => @method, :path => @path },
|
76
|
+
@params)
|
77
|
+
|
78
|
+
@negative_failure_message = "Didn't expect to #{description}"
|
79
|
+
true
|
80
|
+
rescue ::ActionController::RoutingError => error
|
81
|
+
@failure_message = error.message
|
82
|
+
false
|
83
|
+
rescue Test::Unit::AssertionFailedError => error
|
84
|
+
@failure_message = error.message
|
85
|
+
false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|