Module: Shoulda::Controller::Macros

Included in:
Test::Unit::TestCase
Defined in:
lib/shoulda/controller/macros.rb

Overview

Macro test helpers for your controllers

By using the macro helpers you can quickly and easily create concise and easy to read test suites.

This code segment:

context "on GET to :show for first record" do
  setup do
    get :show, :id => 1
  end

  should_assign_to :user
  should_respond_with :success
  should_render_template :show
  should_not_set_the_flash

  should "do something else really cool" do
    assert_equal 1, assigns(:user).id
  end
end

Would produce 5 tests for the show action

Furthermore, the should_be_restful helper will create an entire set of tests which will verify that your controller responds restfully to a variety of requested formats.

Instance Method Summary collapse

Instance Method Details

#should_assign_to(*names) ⇒ Object

Macro that creates a test asserting that the controller assigned to each of the named instance variable(s).

Options:

  • :class - The expected class of the instance variable being checked.

  • :equals - A string which is evaluated and compared for equality with

the instance variable being checked.

Example:

should_assign_to :user, :posts
should_assign_to :user, :class => User
should_assign_to :user, :equals => '@user'


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/shoulda/controller/macros.rb', line 134

def should_assign_to(*names)
  opts = names.extract_options!
  names.each do |name|
    test_name = "assign @#{name}"
    test_name << " as class #{opts[:class]}" if opts[:class]
    test_name << " which is equal to #{opts[:equals]}" if opts[:equals]
    should test_name do
      assigned_value = assigns(name.to_sym)
      assert_not_nil assigned_value, "The action isn't assigning to @#{name}"
      assert_kind_of opts[:class], assigned_value if opts[:class]
      if opts[:equals]
        instantiate_variables_from_assigns do
          expected_value = eval(opts[:equals], self.send(:binding), __FILE__, __LINE__)
          assert_equal expected_value, assigned_value,
                       "Instance variable @#{name} expected to be #{expected_value}" +
                       " but was #{assigned_value}"
        end
      end
    end
  end
end

#should_be_restful(&blk) ⇒ Object

DEPRECATED: Please see thoughtbot.lighthouseapp.com/projects/5807/tickets/78 for more information.

Generates a full suite of tests for a restful controller.

The following definition will generate tests for the index, show, new, edit, create, update and destroy actions, in both html and xml formats:

should_be_restful do |resource|
  resource.parent = :user

  resource.create.params = { :title => "first post", :body => 'blah blah blah'}
  resource.update.params = { :title => "changed" }
end

This generates about 40 tests, all of the format:

"on GET to :show should assign @user."
"on GET to :show should not set the flash."
"on GET to :show should render 'show' template."
"on GET to :show should respond with success."
"on GET to :show as xml should assign @user."
"on GET to :show as xml should have ContentType set to 'application/xml'."
"on GET to :show as xml should respond with success."
"on GET to :show as xml should return <user/> as the root element."

The resource parameter passed into the block is a ResourceOptions object, and is used to configure the tests for the details of your resources.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/shoulda/controller/macros.rb', line 56

def should_be_restful(&blk) # :yields: resource
  warn "[DEPRECATION] should_be_restful is deprecated.  Please see http://thoughtbot.lighthouseapp.com/projects/5807/tickets/78 for more information."

  resource = ResourceOptions.new
  blk.call(resource)
  resource.normalize!(self)

  resource.formats.each do |format|
    resource.actions.each do |action|
      if self.respond_to? :"make_#{action}_#{format}_tests"
        self.send(:"make_#{action}_#{format}_tests", resource)
      else
        should "test #{action} #{format}" do
          flunk "Test for #{action} as #{format} not implemented"
        end
      end
    end
  end
end

#should_filter_params(*keys) ⇒ Object

Macro that creates a test asserting that filter_parameter_logging is set for the specified keys

Example:

should_filter_params :password, :ssn


109
110
111
112
113
114
115
116
117
118
119
# File 'lib/shoulda/controller/macros.rb', line 109

def should_filter_params(*keys)
  keys.each do |key|
    should "filter #{key}" do
      assert @controller.respond_to?(:filter_parameters),
        "The key #{key} is not filtered"
      filtered = @controller.send(:filter_parameters, {key.to_s => key.to_s})
      assert_equal '[FILTERED]', filtered[key.to_s],
        "The key #{key} is not filtered"
    end
  end
end

#should_not_assign_to(*names) ⇒ Object

Macro that creates a test asserting that the controller did not assign to any of the named instance variable(s).

Example:

should_not_assign_to :user, :posts


162
163
164
165
166
167
168
# File 'lib/shoulda/controller/macros.rb', line 162

def should_not_assign_to(*names)
  names.each do |name|
    should "not assign to @#{name}" do
      assert !assigns(name.to_sym), "@#{name} was visible"
    end
  end
end

#should_not_set_the_flashObject

Macro that creates a test asserting that the flash is empty. Same as



99
100
101
# File 'lib/shoulda/controller/macros.rb', line 99

def should_not_set_the_flash
  should_set_the_flash_to nil
end

#should_redirect_to(url) ⇒ Object

Macro that creates a test asserting that the controller returned a redirect to the given path. The given string is evaled to produce the resulting redirect path. All of the instance variables set by the controller are available to the evaled string. Example:

should_redirect_to '"/"'
should_redirect_to "user_url(@user)"
should_redirect_to "users_url"


257
258
259
260
261
262
263
# File 'lib/shoulda/controller/macros.rb', line 257

def should_redirect_to(url)
  should "redirect to #{url.inspect}" do
    instantiate_variables_from_assigns do
      assert_redirected_to eval(url, self.send(:binding), __FILE__, __LINE__)
    end
  end
end

#should_render_a_formObject

Macro that creates a test asserting that the rendered view contains a <form> element.



266
267
268
269
270
# File 'lib/shoulda/controller/macros.rb', line 266

def should_render_a_form
  should "display a form" do
    assert_select "form", true, "The template doesn't contain a <form> element"
  end
end

#should_render_page_with_metadata(options) ⇒ Object

Macro that creates a test asserting that the rendered view contains the selected metatags. Values can be string or Regexps. Example:

 :description => "Description of this page", :keywords => /post/

You can also use this method to test the rendered views title.

Example:

 :title => /index/


282
283
284
285
286
287
288
289
290
291
292
# File 'lib/shoulda/controller/macros.rb', line 282

def (options)
  options.each do |key, value|
    should "have metatag #{key}" do
      if key.to_sym == :title
        assert_select "title", value
      else
        assert_select "meta[name=?][content#{"*" if value.is_a?(Regexp)}=?]", key, value
      end
    end
  end
end

#should_render_template(template) ⇒ Object

Macro that creates a test asserting that the controller rendered the given template. Example:

should_render_template :new


217
218
219
220
221
# File 'lib/shoulda/controller/macros.rb', line 217

def should_render_template(template)
  should "render template #{template.inspect}" do
    assert_template template.to_s
  end
end

#should_render_with_layout(expected_layout = 'application') ⇒ Object

Macro that creates a test asserting that the controller rendered with the given layout. Example:

should_render_with_layout 'special'


227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/shoulda/controller/macros.rb', line 227

def should_render_with_layout(expected_layout = 'application')
  if expected_layout
    should "render with #{expected_layout.inspect} layout" do
      response_layout = @response.layout.blank? ? "" : @response.layout.split('/').last
      assert_equal expected_layout.to_s,
                   response_layout,
                   "Expected to render with layout #{expected_layout} but was rendered with #{response_layout}"
    end
  else
    should "render without layout" do
      assert_nil @response.layout,
                 "Expected no layout, but was rendered using #{@response.layout}"
    end
  end
end

#should_render_without_layoutObject

Macro that creates a test asserting that the controller rendered without a layout. Same as @should_render_with_layout false@



245
246
247
# File 'lib/shoulda/controller/macros.rb', line 245

def should_render_without_layout
  should_render_with_layout nil
end

#should_respond_with(response) ⇒ Object

Macro that creates a test asserting that the controller responded with a ‘response’ status code. Example:

should_respond_with :success


174
175
176
177
178
# File 'lib/shoulda/controller/macros.rb', line 174

def should_respond_with(response)
  should "respond with #{response}" do
    assert_response response
  end
end

#should_respond_with_content_type(content_type) ⇒ Object

Macro that creates a test asserting that the response content type was ‘content_type’. Example:

should_respond_with_content_type 'application/rss+xml'
should_respond_with_content_type :rss
should_respond_with_content_type /rss/


186
187
188
189
190
191
192
193
194
195
# File 'lib/shoulda/controller/macros.rb', line 186

def should_respond_with_content_type(content_type)
  should "respond with content type of #{content_type}" do
    content_type = Mime::EXTENSION_LOOKUP[content_type.to_s].to_s if content_type.is_a? Symbol
    if content_type.is_a? Regexp
      assert_match content_type, @response.content_type, "Expected to match #{content_type} but was actually #{@response.content_type}"
    else
      assert_equal content_type, @response.content_type, "Expected #{content_type} but was actually #{@response.content_type}"
    end
  end
end

#should_return_from_session(key, expected) ⇒ Object

Macro that creates a test asserting that a value returned from the session is correct. The given string is evaled to produce the resulting redirect path. All of the instance variables set by the controller are available to the evaled string. Example:

should_return_from_session :user_id, '@user.id'
should_return_from_session :message, '"Free stuff"'


204
205
206
207
208
209
210
211
# File 'lib/shoulda/controller/macros.rb', line 204

def should_return_from_session(key, expected)
  should "return the correct value from the session for key #{key}" do
    instantiate_variables_from_assigns do
      expected_value = eval(expected, self.send(:binding), __FILE__, __LINE__)
      assert_equal expected_value, session[key], "Expected #{expected_value.inspect} but was #{session[key]}"
    end
  end
end

#should_route(method, path, options) ⇒ Object

Macro that creates a routing test. It tries to use the given HTTP method on the given path, and asserts that it routes to the given options.

If you don’t specify a :controller, it will try to guess the controller based on the current test.

to_param is called on the options given.

Examples:

should_route :get, "/posts", :controller => :posts, :action => :index
should_route :get, "/posts/new", :action => :new
should_route :post, "/posts", :action => :create
should_route :get, "/posts/1", :action => :show, :id => 1
should_route :edit, "/posts/1", :action => :show, :id => 1
should_route :put, "/posts/1", :action => :update, :id => 1
should_route :delete, "/posts/1", :action => :destroy, :id => 1
should_route :get, "/users/1/posts/1",
  :action => :show, :id => 1, :user_id => 1


315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/shoulda/controller/macros.rb', line 315

def should_route(method, path, options)
  unless options[:controller]
    options[:controller] = self.name.gsub(/ControllerTest$/, '').tableize
  end
  options[:controller] = options[:controller].to_s
  options[:action] = options[:action].to_s

  populated_path = path.dup
  options.each do |key, value|
    options[key] = value.to_param if value.respond_to? :to_param
    populated_path.gsub!(key.inspect, value.to_s)
  end

  should_name = "route #{method.to_s.upcase} #{populated_path} to/from #{options.inspect}"

  should should_name do
    assert_routing({:method => method, :path => populated_path}, options)
  end
end

#should_set_the_flash_to(val) ⇒ Object

:section: Test macros Macro that creates a test asserting that the flash contains the given value. val can be a String, a Regex, or nil (indicating that the flash should not be set)

Example:

should_set_the_flash_to "Thank you for placing this order."
should_set_the_flash_to /created/i
should_set_the_flash_to nil


85
86
87
88
89
90
91
92
93
94
95
# File 'lib/shoulda/controller/macros.rb', line 85

def should_set_the_flash_to(val)
  if val
    should "have #{val.inspect} in the flash" do
      assert_contains flash.values, val, ", Flash: #{flash.inspect}"
    end
  else
    should "not set the flash" do
      assert_equal({}, flash, "Flash was set to:\n#{flash.inspect}")
    end
  end
end