shoulda 2.0.6 → 2.9.0

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