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.
Files changed (109) hide show
  1. data/README.rdoc +60 -10
  2. data/Rakefile +7 -7
  3. data/lib/shoulda.rb +7 -15
  4. data/lib/shoulda/action_controller.rb +28 -0
  5. data/lib/shoulda/action_controller/helpers.rb +47 -0
  6. data/lib/shoulda/action_controller/macros.rb +277 -0
  7. data/lib/shoulda/action_controller/matchers.rb +37 -0
  8. data/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
  9. data/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
  10. data/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
  11. data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
  12. data/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +81 -0
  13. data/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
  14. data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +87 -0
  15. data/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
  16. data/lib/shoulda/action_mailer.rb +1 -1
  17. data/lib/shoulda/action_mailer/assertions.rb +32 -33
  18. data/lib/shoulda/action_view.rb +10 -0
  19. data/lib/shoulda/action_view/macros.rb +56 -0
  20. data/lib/shoulda/active_record.rb +6 -2
  21. data/lib/shoulda/active_record/assertions.rb +62 -89
  22. data/lib/shoulda/active_record/helpers.rb +40 -0
  23. data/lib/shoulda/active_record/macros.rb +520 -684
  24. data/lib/shoulda/active_record/matchers.rb +42 -0
  25. data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
  26. data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
  27. data/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
  28. data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
  29. data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
  30. data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
  31. data/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
  32. data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
  33. data/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
  34. data/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
  35. data/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
  36. data/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
  37. data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
  38. data/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
  39. data/lib/shoulda/assertions.rb +50 -40
  40. data/lib/shoulda/autoload_macros.rb +46 -0
  41. data/lib/shoulda/context.rb +124 -126
  42. data/lib/shoulda/helpers.rb +5 -7
  43. data/lib/shoulda/macros.rb +63 -64
  44. data/lib/shoulda/private_helpers.rb +16 -18
  45. data/lib/shoulda/rails.rb +5 -11
  46. data/lib/shoulda/rspec.rb +11 -0
  47. data/lib/shoulda/tasks/list_tests.rake +6 -1
  48. data/lib/shoulda/test_unit.rb +19 -0
  49. data/rails/init.rb +7 -1
  50. data/test/README +2 -2
  51. data/test/fail_macros.rb +15 -15
  52. data/test/fixtures/tags.yml +1 -1
  53. data/test/functional/posts_controller_test.rb +46 -26
  54. data/test/functional/users_controller_test.rb +0 -19
  55. data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +68 -0
  56. data/test/matchers/active_record/allow_value_matcher_test.rb +41 -0
  57. data/test/matchers/active_record/association_matcher_test.rb +258 -0
  58. data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +80 -0
  59. data/test/matchers/active_record/ensure_length_of_matcher_test.rb +158 -0
  60. data/test/matchers/active_record/have_db_column_matcher_test.rb +169 -0
  61. data/test/matchers/active_record/have_index_matcher_test.rb +74 -0
  62. data/test/matchers/active_record/have_named_scope_matcher_test.rb +65 -0
  63. data/test/matchers/active_record/have_readonly_attributes_matcher_test.rb +29 -0
  64. data/test/matchers/active_record/validate_acceptance_of_matcher_test.rb +44 -0
  65. data/test/matchers/active_record/validate_numericality_of_matcher_test.rb +52 -0
  66. data/test/matchers/active_record/validate_presence_of_matcher_test.rb +86 -0
  67. data/test/matchers/active_record/validate_uniqueness_of_matcher_test.rb +147 -0
  68. data/test/matchers/controller/assign_to_matcher_test.rb +35 -0
  69. data/test/matchers/controller/filter_param_matcher_test.rb +32 -0
  70. data/test/matchers/controller/render_with_layout_matcher_test.rb +33 -0
  71. data/test/matchers/controller/respond_with_content_type_matcher_test.rb +27 -0
  72. data/test/matchers/controller/respond_with_matcher_test.rb +106 -0
  73. data/test/matchers/controller/route_matcher_test.rb +58 -0
  74. data/test/matchers/controller/set_session_matcher_test.rb +31 -0
  75. data/test/matchers/controller/set_the_flash_matcher.rb +41 -0
  76. data/test/model_builder.rb +106 -0
  77. data/test/other/autoload_macro_test.rb +18 -0
  78. data/test/other/helpers_test.rb +58 -0
  79. data/test/other/private_helpers_test.rb +1 -1
  80. data/test/other/should_test.rb +16 -16
  81. data/test/rails_root/app/controllers/posts_controller.rb +6 -5
  82. data/test/rails_root/app/models/pets/dog.rb +10 -0
  83. data/test/rails_root/app/models/treat.rb +3 -0
  84. data/test/rails_root/app/models/user.rb +4 -3
  85. data/test/rails_root/app/views/layouts/posts.rhtml +2 -0
  86. data/test/rails_root/config/database.yml +1 -1
  87. data/test/rails_root/config/environment.rb +1 -1
  88. data/test/rails_root/config/environments/{sqlite3.rb → test.rb} +0 -0
  89. data/test/rails_root/db/migrate/001_create_users.rb +3 -2
  90. data/test/rails_root/db/migrate/011_create_treats.rb +12 -0
  91. data/test/rails_root/test/shoulda_macros/custom_macro.rb +6 -0
  92. data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +6 -0
  93. data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +6 -0
  94. data/test/rspec_test.rb +207 -0
  95. data/test/test_helper.rb +3 -1
  96. data/test/unit/address_test.rb +1 -23
  97. data/test/unit/dog_test.rb +5 -2
  98. data/test/unit/post_test.rb +7 -3
  99. data/test/unit/product_test.rb +2 -2
  100. data/test/unit/tag_test.rb +2 -1
  101. data/test/unit/user_test.rb +25 -9
  102. metadata +84 -23
  103. data/lib/shoulda/controller.rb +0 -30
  104. data/lib/shoulda/controller/formats/html.rb +0 -201
  105. data/lib/shoulda/controller/formats/xml.rb +0 -170
  106. data/lib/shoulda/controller/helpers.rb +0 -64
  107. data/lib/shoulda/controller/macros.rb +0 -316
  108. data/lib/shoulda/controller/resource_options.rb +0 -236
  109. data/test/rails_root/app/models/dog.rb +0 -5
@@ -1,170 +0,0 @@
1
- module ThoughtBot # :nodoc:
2
- module Shoulda # :nodoc:
3
- module Controller # :nodoc:
4
- module XML
5
- def self.included(other) #:nodoc:
6
- other.class_eval do
7
- extend ThoughtBot::Shoulda::Controller::XML::ClassMethods
8
- end
9
- end
10
-
11
- module ClassMethods
12
- # Macro that creates a test asserting that the controller responded with an XML content-type
13
- # and that the XML contains +<name/>+ as the root element.
14
- def should_respond_with_xml_for(name = nil)
15
- should "have ContentType set to 'application/xml'" do
16
- assert_xml_response
17
- end
18
-
19
- if name
20
- should "return <#{name}/> as the root element" do
21
- body = @response.body.first(100).map {|l| " #{l}"}
22
- assert_select name.to_s.dasherize, 1, "Body:\n#{body}...\nDoes not have <#{name}/> as the root element."
23
- end
24
- end
25
- end
26
- alias should_respond_with_xml should_respond_with_xml_for
27
-
28
- protected
29
-
30
- def make_show_xml_tests(res) # :nodoc:
31
- context "on GET to #{controller_name_from_class}#show as xml" do
32
- setup do
33
- request_xml
34
- record = get_existing_record(res)
35
- parent_params = make_parent_params(res, record)
36
- get :show, parent_params.merge({ res.identifier => record.to_param })
37
- end
38
-
39
- if res.denied.actions.include?(:show)
40
- should_not_assign_to res.object
41
- should_respond_with 401
42
- else
43
- should_assign_to res.object
44
- should_respond_with :success
45
- should_respond_with_xml_for res.object
46
- end
47
- end
48
- end
49
-
50
- def make_edit_xml_tests(res) # :nodoc:
51
- # XML doesn't need an :edit action
52
- end
53
-
54
- def make_new_xml_tests(res) # :nodoc:
55
- # XML doesn't need a :new action
56
- end
57
-
58
- def make_index_xml_tests(res) # :nodoc:
59
- context "on GET to #{controller_name_from_class}#index as xml" do
60
- setup do
61
- request_xml
62
- parent_params = make_parent_params(res)
63
- get(:index, parent_params)
64
- end
65
-
66
- if res.denied.actions.include?(:index)
67
- should_not_assign_to res.object.to_s.pluralize
68
- should_respond_with 401
69
- else
70
- should_respond_with :success
71
- should_respond_with_xml_for res.object.to_s.pluralize
72
- should_assign_to res.object.to_s.pluralize
73
- end
74
- end
75
- end
76
-
77
- def make_destroy_xml_tests(res) # :nodoc:
78
- context "on DELETE to #{controller_name_from_class}#destroy as xml" do
79
- setup do
80
- request_xml
81
- @record = get_existing_record(res)
82
- parent_params = make_parent_params(res, @record)
83
- delete :destroy, parent_params.merge({ res.identifier => @record.to_param })
84
- end
85
-
86
- if res.denied.actions.include?(:destroy)
87
- should_respond_with 401
88
-
89
- should "not destroy record" do
90
- assert @record.reload
91
- end
92
- else
93
- should "destroy record" do
94
- assert_raises(::ActiveRecord::RecordNotFound, "@#{res.object} was not destroyed.") do
95
- @record.reload
96
- end
97
- end
98
- end
99
- end
100
- end
101
-
102
- def make_create_xml_tests(res) # :nodoc:
103
- context "on POST to #{controller_name_from_class}#create as xml" do
104
- setup do
105
- request_xml
106
- parent_params = make_parent_params(res)
107
- @count = res.klass.count
108
- post :create, parent_params.merge(res.object => res.create.params)
109
- end
110
-
111
- if res.denied.actions.include?(:create)
112
- should_respond_with 401
113
- should_not_assign_to res.object
114
-
115
- should "not create new record" do
116
- assert_equal @count, res.klass.count
117
- end
118
- else
119
- should_assign_to res.object
120
-
121
- should "not have errors on @#{res.object}" do
122
- assert_equal [], pretty_error_messages(assigns(res.object)), "@#{res.object} has errors:"
123
- end
124
- end
125
- end
126
- end
127
-
128
- def make_update_xml_tests(res) # :nodoc:
129
- context "on PUT to #{controller_name_from_class}#update as xml" do
130
- setup do
131
- request_xml
132
- @record = get_existing_record(res)
133
- parent_params = make_parent_params(res, @record)
134
- put :update, parent_params.merge(res.identifier => @record.to_param, res.object => res.update.params)
135
- end
136
-
137
- if res.denied.actions.include?(:update)
138
- should_not_assign_to res.object
139
- should_respond_with 401
140
- else
141
- should_assign_to res.object
142
-
143
- should "not have errors on @#{res.object}" do
144
- assert_equal [], assigns(res.object).errors.full_messages, "@#{res.object} has errors:"
145
- end
146
- end
147
- end
148
- end
149
- end
150
-
151
- # Sets the next request's format to 'application/xml'
152
- def request_xml
153
- @request.accept = "application/xml"
154
- end
155
-
156
- # Asserts that the controller's response was 'application/xml'
157
- def assert_xml_response
158
- content_type = (@response.headers["Content-Type"] || @response.headers["type"]).to_s
159
- regex = %r{\bapplication/xml\b}
160
-
161
- msg = "Content Type '#{content_type.inspect}' doesn't match '#{regex.inspect}'\n"
162
- msg += "Body: #{@response.body.first(100).chomp} ..."
163
-
164
- assert_match regex, content_type, msg
165
- end
166
-
167
- end
168
- end
169
- end
170
- end
@@ -1,64 +0,0 @@
1
- module ThoughtBot # :nodoc:
2
- module Shoulda # :nodoc:
3
- module Controller # :nodoc:
4
- module Helpers # :nodoc:
5
- private # :enddoc:
6
-
7
- SPECIAL_INSTANCE_VARIABLES = %w{
8
- _cookies
9
- _flash
10
- _headers
11
- _params
12
- _request
13
- _response
14
- _session
15
- action_name
16
- before_filter_chain_aborted
17
- cookies
18
- flash
19
- headers
20
- ignore_missing_templates
21
- logger
22
- params
23
- request
24
- request_origin
25
- response
26
- session
27
- template
28
- template_class
29
- template_root
30
- url
31
- variables_added
32
- }.map(&:to_s)
33
-
34
- def instantiate_variables_from_assigns(*names, &blk)
35
- old = {}
36
- names = (@response.template.assigns.keys - SPECIAL_INSTANCE_VARIABLES) if names.empty?
37
- names.each do |name|
38
- old[name] = instance_variable_get("@#{name}")
39
- instance_variable_set("@#{name}", assigns(name.to_sym))
40
- end
41
- blk.call
42
- names.each do |name|
43
- instance_variable_set("@#{name}", old[name])
44
- end
45
- end
46
-
47
- def get_existing_record(res) # :nodoc:
48
- returning(instance_variable_get("@#{res.object}")) do |record|
49
- assert(record, "This test requires you to set @#{res.object} in your setup block")
50
- end
51
- end
52
-
53
- def make_parent_params(resource, record = nil, parent_names = nil) # :nodoc:
54
- parent_names ||= resource.parents.reverse
55
- return {} if parent_names == [] # Base case
56
- parent_name = parent_names.shift
57
- parent = record ? record.send(parent_name) : parent_name.to_s.classify.constantize.find(:first)
58
-
59
- { :"#{parent_name}_id" => parent.to_param }.merge(make_parent_params(resource, parent, parent_names))
60
- end
61
- end
62
- end
63
- end
64
- end
@@ -1,316 +0,0 @@
1
- module ThoughtBot # :nodoc:
2
- module Shoulda # :nodoc:
3
- module Controller # :nodoc:
4
- # = Macro test helpers for your controllers
5
- #
6
- # By using the macro helpers you can quickly and easily create concise and easy to read test suites.
7
- #
8
- # This code segment:
9
- # context "on GET to :show for first record" do
10
- # setup do
11
- # get :show, :id => 1
12
- # end
13
- #
14
- # should_assign_to :user
15
- # should_respond_with :success
16
- # should_render_template :show
17
- # should_not_set_the_flash
18
- #
19
- # should "do something else really cool" do
20
- # assert_equal 1, assigns(:user).id
21
- # end
22
- # end
23
- #
24
- # Would produce 5 tests for the +show+ action
25
- #
26
- # Furthermore, the should_be_restful helper will create an entire set of tests which will verify that your
27
- # controller responds restfully to a variety of requested formats.
28
- module Macros
29
- # <b>DEPRECATED:</b> Please see
30
- # http://thoughtbot.lighthouseapp.com/projects/5807/tickets/78 for more
31
- # information.
32
- #
33
- # Generates a full suite of tests for a restful controller.
34
- #
35
- # The following definition will generate tests for the +index+, +show+, +new+,
36
- # +edit+, +create+, +update+ and +destroy+ actions, in both +html+ and +xml+ formats:
37
- #
38
- # should_be_restful do |resource|
39
- # resource.parent = :user
40
- #
41
- # resource.create.params = { :title => "first post", :body => 'blah blah blah'}
42
- # resource.update.params = { :title => "changed" }
43
- # end
44
- #
45
- # This generates about 40 tests, all of the format:
46
- # "on GET to :show should assign @user."
47
- # "on GET to :show should not set the flash."
48
- # "on GET to :show should render 'show' template."
49
- # "on GET to :show should respond with success."
50
- # "on GET to :show as xml should assign @user."
51
- # "on GET to :show as xml should have ContentType set to 'application/xml'."
52
- # "on GET to :show as xml should respond with success."
53
- # "on GET to :show as xml should return <user/> as the root element."
54
- # The +resource+ parameter passed into the block is a ResourceOptions object, and
55
- # is used to configure the tests for the details of your resources.
56
- #
57
- def should_be_restful(&blk) # :yields: resource
58
- warn "[DEPRECATION] should_be_restful is deprecated. Please see http://thoughtbot.lighthouseapp.com/projects/5807/tickets/78 for more information."
59
-
60
- resource = ResourceOptions.new
61
- blk.call(resource)
62
- resource.normalize!(self)
63
-
64
- resource.formats.each do |format|
65
- resource.actions.each do |action|
66
- if self.respond_to? :"make_#{action}_#{format}_tests"
67
- self.send(:"make_#{action}_#{format}_tests", resource)
68
- else
69
- should "test #{action} #{format}" do
70
- flunk "Test for #{action} as #{format} not implemented"
71
- end
72
- end
73
- end
74
- end
75
- end
76
-
77
- # :section: Test macros
78
- # Macro that creates a test asserting that the flash contains the given value.
79
- # val can be a String, a Regex, or nil (indicating that the flash should not be set)
80
- #
81
- # Example:
82
- #
83
- # should_set_the_flash_to "Thank you for placing this order."
84
- # should_set_the_flash_to /created/i
85
- # should_set_the_flash_to nil
86
- def should_set_the_flash_to(val)
87
- if val
88
- should "have #{val.inspect} in the flash" do
89
- assert_contains flash.values, val, ", Flash: #{flash.inspect}"
90
- end
91
- else
92
- should "not set the flash" do
93
- assert_equal({}, flash, "Flash was set to:\n#{flash.inspect}")
94
- end
95
- end
96
- end
97
-
98
- # Macro that creates a test asserting that the flash is empty. Same as
99
- # @should_set_the_flash_to nil@
100
- def should_not_set_the_flash
101
- should_set_the_flash_to nil
102
- end
103
-
104
- # Macro that creates a test asserting that filter_parameter_logging
105
- # is set for the specified keys
106
- #
107
- # Example:
108
- #
109
- # should_filter_params :password, :ssn
110
- def should_filter_params(*keys)
111
- keys.each do |key|
112
- should "filter #{key}" do
113
- assert @controller.respond_to?(:filter_parameters),
114
- "The key #{key} is not filtered"
115
- filtered = @controller.send(:filter_parameters, {key.to_s => key.to_s})
116
- assert_equal '[FILTERED]', filtered[key.to_s],
117
- "The key #{key} is not filtered"
118
- end
119
- end
120
- end
121
-
122
- # Macro that creates a test asserting that the controller assigned to
123
- # each of the named instance variable(s).
124
- #
125
- # Options:
126
- # * <tt>:class</tt> - The expected class of the instance variable being checked.
127
- # * <tt>:equals</tt> - A string which is evaluated and compared for equality with
128
- # the instance variable being checked.
129
- #
130
- # Example:
131
- #
132
- # should_assign_to :user, :posts
133
- # should_assign_to :user, :class => User
134
- # should_assign_to :user, :equals => '@user'
135
- def should_assign_to(*names)
136
- opts = names.extract_options!
137
- names.each do |name|
138
- test_name = "assign @#{name}"
139
- test_name << " as class #{opts[:class]}" if opts[:class]
140
- test_name << " which is equal to #{opts[:equals]}" if opts[:equals]
141
- should test_name do
142
- assigned_value = assigns(name.to_sym)
143
- assert assigned_value, "The action isn't assigning to @#{name}"
144
- assert_kind_of opts[:class], assigned_value if opts[:class]
145
- if opts[:equals]
146
- instantiate_variables_from_assigns do
147
- expected_value = eval(opts[:equals], self.send(:binding), __FILE__, __LINE__)
148
- assert_equal expected_value, assigned_value,
149
- "Instance variable @#{name} expected to be #{expected_value}" +
150
- " but was #{assigned_value}"
151
- end
152
- end
153
- end
154
- end
155
- end
156
-
157
- # Macro that creates a test asserting that the controller did not assign to
158
- # any of the named instance variable(s).
159
- #
160
- # Example:
161
- #
162
- # should_not_assign_to :user, :posts
163
- def should_not_assign_to(*names)
164
- names.each do |name|
165
- should "not assign to @#{name}" do
166
- assert !assigns(name.to_sym), "@#{name} was visible"
167
- end
168
- end
169
- end
170
-
171
- # Macro that creates a test asserting that the controller responded with a 'response' status code.
172
- # Example:
173
- #
174
- # should_respond_with :success
175
- def should_respond_with(response)
176
- should "respond with #{response}" do
177
- assert_response response
178
- end
179
- end
180
-
181
- # Macro that creates a test asserting that the response content type was 'content_type'.
182
- # Example:
183
- #
184
- # should_respond_with_content_type 'application/rss+xml'
185
- # should_respond_with_content_type :rss
186
- # should_respond_with_content_type /rss/
187
- def should_respond_with_content_type(content_type)
188
- should "respond with content type of #{content_type}" do
189
- content_type = Mime::EXTENSION_LOOKUP[content_type.to_s].to_s if content_type.is_a? Symbol
190
- if content_type.is_a? Regexp
191
- assert_match content_type, @response.content_type, "Expected to match #{content_type} but was actually #{@response.content_type}"
192
- else
193
- assert_equal content_type, @response.content_type, "Expected #{content_type} but was actually #{@response.content_type}"
194
- end
195
- end
196
- end
197
-
198
- # Macro that creates a test asserting that a value returned from the session is correct.
199
- # The given string is evaled to produce the resulting redirect path. All of the instance variables
200
- # set by the controller are available to the evaled string.
201
- # Example:
202
- #
203
- # should_return_from_session :user_id, '@user.id'
204
- # should_return_from_session :message, '"Free stuff"'
205
- def should_return_from_session(key, expected)
206
- should "return the correct value from the session for key #{key}" do
207
- instantiate_variables_from_assigns do
208
- expected_value = eval(expected, self.send(:binding), __FILE__, __LINE__)
209
- assert_equal expected_value, session[key], "Expected #{expected_value.inspect} but was #{session[key]}"
210
- end
211
- end
212
- end
213
-
214
- # Macro that creates a test asserting that the controller rendered the given template.
215
- # Example:
216
- #
217
- # should_render_template :new
218
- def should_render_template(template)
219
- should "render template #{template.inspect}" do
220
- assert_template template.to_s
221
- end
222
- end
223
-
224
- # Macro that creates a test asserting that the controller rendered with the given layout.
225
- # Example:
226
- #
227
- # should_render_with_layout 'special'
228
- def should_render_with_layout(expected_layout = 'application')
229
- if expected_layout
230
- should "render with #{expected_layout.inspect} layout" do
231
- response_layout = @response.layout.blank? ? "" : @response.layout.split('/').last
232
- assert_equal expected_layout.to_s,
233
- response_layout,
234
- "Expected to render with layout #{expected_layout} but was rendered with #{response_layout}"
235
- end
236
- else
237
- should "render without layout" do
238
- assert_nil @response.layout,
239
- "Expected no layout, but was rendered using #{@response.layout}"
240
- end
241
- end
242
- end
243
-
244
- # Macro that creates a test asserting that the controller rendered without a layout.
245
- # Same as @should_render_with_layout false@
246
- def should_render_without_layout
247
- should_render_with_layout nil
248
- end
249
-
250
- # Macro that creates a test asserting that the controller returned a redirect to the given path.
251
- # The given string is evaled to produce the resulting redirect path. All of the instance variables
252
- # set by the controller are available to the evaled string.
253
- # Example:
254
- #
255
- # should_redirect_to '"/"'
256
- # should_redirect_to "user_url(@user)"
257
- # should_redirect_to "users_url"
258
- def should_redirect_to(url)
259
- should "redirect to #{url.inspect}" do
260
- instantiate_variables_from_assigns do
261
- assert_redirected_to eval(url, self.send(:binding), __FILE__, __LINE__)
262
- end
263
- end
264
- end
265
-
266
- # Macro that creates a test asserting that the rendered view contains a <form> element.
267
- def should_render_a_form
268
- should "display a form" do
269
- assert_select "form", true, "The template doesn't contain a <form> element"
270
- end
271
- end
272
-
273
- # Macro that creates a routing test. It tries to use the given HTTP
274
- # +method+ on the given +path+, and asserts that it routes to the
275
- # given +options+.
276
- #
277
- # If you don't specify a :controller, it will try to guess the controller
278
- # based on the current test.
279
- #
280
- # +to_param+ is called on the +options+ given.
281
- #
282
- # Examples:
283
- #
284
- # should_route :get, "/posts", :controller => :posts, :action => :index
285
- # should_route :get, "/posts/new", :action => :new
286
- # should_route :post, "/posts", :action => :create
287
- # should_route :get, "/posts/1", :action => :show, :id => 1
288
- # should_route :edit, "/posts/1", :action => :show, :id => 1
289
- # should_route :put, "/posts/1", :action => :update, :id => 1
290
- # should_route :delete, "/posts/1", :action => :destroy, :id => 1
291
- # should_route :get, "/users/1/posts/1",
292
- # :action => :show, :id => 1, :user_id => 1
293
- #
294
- def should_route(method, path, options)
295
- unless options[:controller]
296
- options[:controller] = self.name.gsub(/ControllerTest$/, '').tableize
297
- end
298
- options[:controller] = options[:controller].to_s
299
- options[:action] = options[:action].to_s
300
-
301
- populated_path = path.dup
302
- options.each do |key, value|
303
- options[key] = value.to_param if value.respond_to? :to_param
304
- populated_path.gsub!(key.inspect, value.to_s)
305
- end
306
-
307
- should_name = "route #{method.to_s.upcase} #{populated_path} to/from #{options.inspect}"
308
-
309
- should should_name do
310
- assert_routing({:method => method, :path => populated_path}, options)
311
- end
312
- end
313
- end
314
- end
315
- end
316
- end