action_pack_assertions_test.rb 17.5 KB
Newer Older
1
require 'abstract_unit'
2
require 'action_view/vendor/html-scanner'
3
require 'controller/fake_controllers'
D
Initial  
David Heinemeier Hansson 已提交
4 5 6

class ActionPackAssertionsController < ActionController::Base

J
Jeremy Kemper 已提交
7
  def nothing() head :ok end
D
Initial  
David Heinemeier Hansson 已提交
8

9
  def hello_world() render :template => "test/hello_world"; end
10
  def hello_repeating_in_path() render :template => "test/hello/hello"; end
D
Initial  
David Heinemeier Hansson 已提交
11

12
  def hello_xml_world() render :template => "test/hello_xml_world"; end
13

14 15 16 17 18 19 20 21 22 23
  def hello_xml_world_pdf
    self.content_type = "application/pdf"
    render :template => "test/hello_xml_world"
  end

  def hello_xml_world_pdf_header
    response.headers["Content-Type"] = "application/pdf; charset=utf-8"
    render :template => "test/hello_xml_world"
  end

24 25
  def partial() render :partial => 'test/partial'; end

26
  def redirect_internal() redirect_to "/nothing"; end
D
Initial  
David Heinemeier Hansson 已提交
27

28
  def redirect_to_action() redirect_to :action => "flash_me", :id => 1, :params => { "panda" => "fun" }; end
29 30 31

  def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end

32 33
  def redirect_to_controller_with_symbol() redirect_to :controller => :elsewhere, :action => :flash_me; end

34
  def redirect_to_path() redirect_to '/some/path' end
35

36 37
  def redirect_invalid_external_route() redirect_to 'ht_tp://www.rubyonrails.org' end

38
  def redirect_to_named_route() redirect_to route_one_url end
39

40
  def redirect_external() redirect_to "http://www.rubyonrails.org"; end
41

42 43
  def redirect_external_protocol_relative() redirect_to "//www.rubyonrails.org"; end

J
Jeremy Kemper 已提交
44
  def response404() head '404 AWOL' end
D
Initial  
David Heinemeier Hansson 已提交
45

J
Jeremy Kemper 已提交
46
  def response500() head '500 Sorry' end
D
Initial  
David Heinemeier Hansson 已提交
47

J
Jeremy Kemper 已提交
48
  def response599() head '599 Whoah!' end
D
Initial  
David Heinemeier Hansson 已提交
49 50 51

  def flash_me
    flash['hello'] = 'my name is inigo montoya...'
52
    render :text => "Inconceivable!"
D
Initial  
David Heinemeier Hansson 已提交
53 54 55 56
  end

  def flash_me_naked
    flash.clear
57
    render :text => "wow!"
D
Initial  
David Heinemeier Hansson 已提交
58 59 60 61
  end

  def assign_this
    @howdy = "ho"
62
    render :inline => "Mr. Henke"
D
Initial  
David Heinemeier Hansson 已提交
63 64 65
  end

  def render_based_on_parameters
66
    render :text => "Mr. #{params[:name]}"
D
Initial  
David Heinemeier Hansson 已提交
67 68
  end

69
  def render_url
70
    render :text => "<div>#{url_for(:action => 'flash_me', :only_path => true)}</div>"
71 72
  end

73 74 75 76
  def render_text_with_custom_content_type
    render :text => "Hello!", :content_type => Mime::RSS
  end

77
  def render_with_layout
78
    @variable_for_layout = nil
79 80 81
    render "test/hello_world", :layout => "layouts/standard"
  end

82 83 84 85 86
  def render_with_layout_and_partial
    @variable_for_layout = nil
    render "test/hello_world_with_partial", :layout => "layouts/standard"
  end

D
Initial  
David Heinemeier Hansson 已提交
87 88
  def session_stuffing
    session['xmas'] = 'turkey'
89
    render :text => "ho ho ho"
D
Initial  
David Heinemeier Hansson 已提交
90
  end
91

92
  def raise_exception_on_get
93
    raise "get" if request.get?
94
    render :text => "request method: #{request.env['REQUEST_METHOD']}"
95 96
  end

97
  def raise_exception_on_post
98
    raise "post" if request.post?
99
    render :text => "request method: #{request.env['REQUEST_METHOD']}"
100
  end
101 102 103 104 105 106 107 108

  def render_file_absolute_path
    render :file => File.expand_path('../../../README.rdoc', __FILE__)
  end

  def render_file_relative_path
    render :file => 'README.rdoc'
  end
109 110
end

111 112 113 114 115 116 117
# Used to test that assert_response includes the exception message
# in the failure message when an action raises and assert_response
# is expecting something other than an error.
class AssertResponseWithUnexpectedErrorController < ActionController::Base
  def index
    raise 'FAIL'
  end
118 119 120 121

  def show
    render :text => "Boom", :status => 500
  end
122 123
end

124 125
module Admin
  class InnerModuleController < ActionController::Base
126 127 128 129 130 131 132 133
    def index
      render :nothing => true
    end

    def redirect_to_index
      redirect_to admin_inner_module_path
    end

134 135 136
    def redirect_to_absolute_controller
      redirect_to :controller => '/content'
    end
137

138 139 140
    def redirect_to_fellow_controller
      redirect_to :controller => 'user'
    end
141

142 143 144
    def redirect_to_top_level_named_route
      redirect_to top_level_url(:id => "foo")
    end
145
  end
D
Initial  
David Heinemeier Hansson 已提交
146 147
end

148
class ActionPackAssertionsControllerTest < ActionController::TestCase
D
Initial  
David Heinemeier Hansson 已提交
149

150 151 152 153 154
  def test_assert_tag_and_url_for
    get :render_url
    assert_tag :content => "/action_pack_assertions/flash_me"
  end

155 156
  def test_render_file_absolute_path
    get :render_file_absolute_path
C
Carlos Antonio da Silva 已提交
157
    assert_match(/\A= Action Pack/, @response.body)
158 159 160 161
  end

  def test_render_file_relative_path
    get :render_file_relative_path
C
Carlos Antonio da Silva 已提交
162
    assert_match(/\A= Action Pack/, @response.body)
163 164
  end

165 166 167
  def test_get_request
    assert_raise(RuntimeError) { get :raise_exception_on_get }
    get :raise_exception_on_post
168 169 170
    assert_equal @response.body, 'request method: GET'
  end

171 172 173 174 175 176 177 178 179 180 181 182
  def test_post_request
    assert_raise(RuntimeError) { post :raise_exception_on_post }
    post :raise_exception_on_get
    assert_equal @response.body, 'request method: POST'
  end

  def test_get_post_request_switch
    post :raise_exception_on_get
    assert_equal @response.body, 'request method: POST'
    get :raise_exception_on_post
    assert_equal @response.body, 'request method: GET'
    post :raise_exception_on_get
183
    assert_equal @response.body, 'request method: POST'
184 185
    get :raise_exception_on_post
    assert_equal @response.body, 'request method: GET'
186
  end
187

188 189
  def test_string_constraint
    with_routing do |set|
N
Neeraj Singh 已提交
190
      set.draw do
191
        get "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"}
192 193 194 195
      end
    end
  end

196 197
  def test_assert_redirect_to_named_route_failure
    with_routing do |set|
198
      set.draw do
199 200 201
        get 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one
        get 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two
        get ':controller/:action'
202 203
      end
      process :redirect_to_named_route
204
      assert_raise(ActiveSupport::TestCase::Assertion) do
205 206
        assert_redirected_to 'http://test.host/route_two'
      end
207 208 209
      assert_raise(ActiveSupport::TestCase::Assertion) do
        assert_redirected_to %r(^http://test.host/route_two)
      end
210
      assert_raise(ActiveSupport::TestCase::Assertion) do
211 212
        assert_redirected_to :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two'
      end
213
      assert_raise(ActiveSupport::TestCase::Assertion) do
214 215 216 217 218
        assert_redirected_to route_two_url
      end
    end
  end

219
  def test_assert_redirect_to_nested_named_route
C
Carlhuda 已提交
220 221
    @controller = Admin::InnerModuleController.new

222
    with_routing do |set|
223
      set.draw do
224 225
        get 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module
        get ':controller/:action'
226 227 228 229 230 231
      end
      process :redirect_to_index
      # redirection is <{"action"=>"index", "controller"=>"admin/admin/inner_module"}>
      assert_redirected_to admin_inner_module_path
    end
  end
232

233
  def test_assert_redirected_to_top_level_named_route_from_nested_controller
C
Carlhuda 已提交
234 235
    @controller = Admin::InnerModuleController.new

236
    with_routing do |set|
237
      set.draw do
238 239
        get '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level
        get ':controller/:action'
240 241
      end
      process :redirect_to_top_level_named_route
242
      # assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return
243
      assert_redirected_to "/action_pack_assertions/foo"
244
      assert_redirected_to %r(/action_pack_assertions/foo)
245 246
    end
  end
247

248
  def test_assert_redirected_to_top_level_named_route_with_same_controller_name_in_both_namespaces
C
Carlhuda 已提交
249 250
    @controller = Admin::InnerModuleController.new

251
    with_routing do |set|
252
      set.draw do
253
        # this controller exists in the admin namespace as well which is the only difference from previous test
254 255
        get '/user/:id', :to => 'user#index', :as => :top_level
        get ':controller/:action'
256 257 258 259 260 261 262
      end
      process :redirect_to_top_level_named_route
      # assert_redirected_to top_level_url('foo') would pass because of exact match early return
      assert_redirected_to top_level_path('foo')
    end
  end

263 264 265 266 267 268 269 270 271 272 273 274 275
  def test_assert_redirect_failure_message_with_protocol_relative_url
    begin
      process :redirect_external_protocol_relative
      assert_redirected_to "/foo"
    rescue ActiveSupport::TestCase::Assertion => ex
      assert_no_match(
        /#{request.protocol}#{request.host}\/\/www.rubyonrails.org/,
        ex.message,
        'protocol relative url was incorrectly normalized'
      )
    end
  end

276
  def test_template_objects_exist
D
Initial  
David Heinemeier Hansson 已提交
277
    process :assign_this
278
    assert !@controller.instance_variable_defined?(:"@hi")
279
    assert @controller.instance_variable_get(:"@howdy")
D
Initial  
David Heinemeier Hansson 已提交
280
  end
281

282
  def test_template_objects_missing
D
Initial  
David Heinemeier Hansson 已提交
283
    process :nothing
284
    assert !@controller.instance_variable_defined?(:@howdy)
D
Initial  
David Heinemeier Hansson 已提交
285
  end
286

287
  def test_empty_flash
D
Initial  
David Heinemeier Hansson 已提交
288
    process :flash_me_naked
289
    assert flash.empty?
D
Initial  
David Heinemeier Hansson 已提交
290 291
  end

292
  def test_flash_exist
D
Initial  
David Heinemeier Hansson 已提交
293
    process :flash_me
294
    assert flash.any?
295
    assert flash['hello'].present?
D
Initial  
David Heinemeier Hansson 已提交
296 297
  end

298
  def test_flash_does_not_exist
D
Initial  
David Heinemeier Hansson 已提交
299
    process :nothing
300
    assert flash.empty?
D
Initial  
David Heinemeier Hansson 已提交
301
  end
302

303 304 305 306 307 308 309 310 311 312 313
  def test_session_exist
    process :session_stuffing
    assert_equal session['xmas'], 'turkey'
  end

  def session_does_not_exist
    process :nothing
    assert session.empty?
  end

  def test_render_template_action
D
Initial  
David Heinemeier Hansson 已提交
314
    process :nothing
315
    assert_template nil
D
Initial  
David Heinemeier Hansson 已提交
316

317
    process :hello_world
318
    assert_template 'hello_world'
D
Initial  
David Heinemeier Hansson 已提交
319
  end
320

D
Initial  
David Heinemeier Hansson 已提交
321 322
  def test_redirection_location
    process :redirect_internal
323
    assert_equal 'http://test.host/nothing', @response.redirect_url
D
Initial  
David Heinemeier Hansson 已提交
324 325 326

    process :redirect_external
    assert_equal 'http://www.rubyonrails.org', @response.redirect_url
327 328 329

    process :redirect_external_protocol_relative
    assert_equal '//www.rubyonrails.org', @response.redirect_url
J
Jeremy Kemper 已提交
330
  end
D
Initial  
David Heinemeier Hansson 已提交
331

J
Jeremy Kemper 已提交
332
  def test_no_redirect_url
D
Initial  
David Heinemeier Hansson 已提交
333 334 335
    process :nothing
    assert_nil @response.redirect_url
  end
336

D
Initial  
David Heinemeier Hansson 已提交
337 338 339
  def test_server_error_response_code
    process :response500
    assert @response.server_error?
340

D
Initial  
David Heinemeier Hansson 已提交
341 342
    process :response599
    assert @response.server_error?
343

D
Initial  
David Heinemeier Hansson 已提交
344 345 346
    process :response404
    assert !@response.server_error?
  end
347

D
Initial  
David Heinemeier Hansson 已提交
348 349 350 351 352
  def test_missing_response_code
    process :response404
    assert @response.missing?
  end

353 354 355 356 357
  def test_client_error_response_code
    process :response404
    assert @response.client_error?
  end

D
Initial  
David Heinemeier Hansson 已提交
358 359 360
  def test_redirect_url_match
    process :redirect_external
    assert @response.redirect?
361
    assert_match(/rubyonrails/, @response.redirect_url)
362
    assert !/perloffrails/.match(@response.redirect_url)
D
Initial  
David Heinemeier Hansson 已提交
363
  end
364

D
Initial  
David Heinemeier Hansson 已提交
365 366 367 368 369 370 371 372 373 374
  def test_redirection
    process :redirect_internal
    assert @response.redirect?

    process :redirect_external
    assert @response.redirect?

    process :nothing
    assert !@response.redirect?
  end
375

D
Initial  
David Heinemeier Hansson 已提交
376 377 378
  def test_successful_response_code
    process :nothing
    assert @response.success?
379 380
  end

381
  def test_response_object
D
Initial  
David Heinemeier Hansson 已提交
382 383 384
    process :nothing
    assert_kind_of ActionController::TestResponse, @response
  end
385

D
Initial  
David Heinemeier Hansson 已提交
386
  def test_render_based_on_parameters
387
    process :render_based_on_parameters, "GET", "name" => "David"
D
Initial  
David Heinemeier Hansson 已提交
388 389 390
    assert_equal "Mr. David", @response.body
  end

391 392
  def test_assert_redirection_fails_with_incorrect_controller
    process :redirect_to_controller
393
    assert_raise(ActiveSupport::TestCase::Assertion) do
394 395 396 397 398 399 400 401 402
      assert_redirected_to :controller => "action_pack_assertions", :action => "flash_me"
    end
  end

  def test_assert_redirection_with_extra_controller_option
    get :redirect_to_action
    assert_redirected_to :controller => 'action_pack_assertions', :action => "flash_me", :id => 1, :params => { :panda => 'fun' }
  end

403
  def test_redirected_to_url_leading_slash
404 405 406
    process :redirect_to_path
    assert_redirected_to '/some/path'
  end
407

408
  def test_redirected_to_url_no_leading_slash_fails
409
    process :redirect_to_path
410 411 412
    assert_raise ActiveSupport::TestCase::Assertion do
      assert_redirected_to 'some/path'
    end
413
  end
414

415 416 417 418 419
  def test_redirect_invalid_external_route
    process :redirect_invalid_external_route
    assert_redirected_to "http://test.hostht_tp://www.rubyonrails.org"
  end

420 421 422 423
  def test_redirected_to_url_full_url
    process :redirect_to_path
    assert_redirected_to 'http://test.host/some/path'
  end
424

425 426 427 428 429 430 431 432 433 434 435
  def test_assert_redirection_with_symbol
    process :redirect_to_controller_with_symbol
    assert_nothing_raised {
      assert_redirected_to :controller => "elsewhere", :action => "flash_me"
    }
    process :redirect_to_controller_with_symbol
    assert_nothing_raised {
      assert_redirected_to :controller => :elsewhere, :action => :flash_me
    }
  end

436 437 438
  def test_redirected_to_with_nested_controller
    @controller = Admin::InnerModuleController.new
    get :redirect_to_absolute_controller
439
    assert_redirected_to :controller => '/content'
440

441 442
    get :redirect_to_fellow_controller
    assert_redirected_to :controller => 'admin/user'
443 444
  end

445 446 447 448 449
  def test_assert_response_uses_exception_message
    @controller = AssertResponseWithUnexpectedErrorController.new
    get :index
    assert_response :success
    flunk 'Expected non-success response'
450
  rescue RuntimeError => e
451 452
    assert e.message.include?('FAIL')
  end
453 454 455 456 457 458

  def test_assert_response_failure_response_with_no_exception
    @controller = AssertResponseWithUnexpectedErrorController.new
    get :show
    assert_response :success
    flunk 'Expected non-success response'
459 460
  rescue ActiveSupport::TestCase::Assertion
    # success
461 462 463
  rescue
    flunk "assert_response failed to handle failure response with missing, but optional, exception."
  end
D
Initial  
David Heinemeier Hansson 已提交
464 465
end

466 467 468
class AssertTemplateTest < ActionController::TestCase
  tests ActionPackAssertionsController

469 470 471 472 473 474
  def test_with_invalid_hash_keys_raises_argument_error
    assert_raise(ArgumentError) do
      assert_template foo: "bar"
    end
  end

475 476 477 478 479
  def test_with_partial
    get :partial
    assert_template :partial => '_partial'
  end

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
  def test_file_with_absolute_path_success
    get :render_file_absolute_path
    assert_template :file => File.expand_path('../../../README.rdoc', __FILE__)
  end

  def test_file_with_relative_path_success
    get :render_file_relative_path
    assert_template :file => 'README.rdoc'
  end

  def test_with_file_failure
    get :render_file_absolute_path
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template :file => 'test/hello_world'
    end
  end

497 498 499 500 501 502 503 504 505 506 507 508
  def test_with_nil_passes_when_no_template_rendered
    get :nothing
    assert_template nil
  end

  def test_with_nil_fails_when_template_rendered
    get :hello_world
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template nil
    end
  end

509 510 511 512 513 514 515
  def test_with_empty_string_fails_when_template_rendered
    get :hello_world
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template ""
    end
  end

516 517 518 519 520 521 522
  def test_with_empty_string_fails_when_no_template_rendered
    get :nothing
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template ""
    end
  end

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
  def test_passes_with_correct_string
    get :hello_world
    assert_template 'hello_world'
    assert_template 'test/hello_world'
  end

  def test_passes_with_correct_symbol
    get :hello_world
    assert_template :hello_world
  end

  def test_fails_with_incorrect_string
    get :hello_world
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template 'hello_planet'
    end
  end

541 542 543 544 545 546 547 548 549 550 551 552 553 554
  def test_fails_with_incorrect_string_that_matches
    get :hello_world
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template 'est/he'
    end
  end

  def test_fails_with_repeated_name_in_path
    get :hello_repeating_in_path
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template 'test/hello'
    end
  end

555 556 557 558 559 560
  def test_fails_with_incorrect_symbol
    get :hello_world
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template :hello_planet
    end
  end
561

562 563 564 565 566 567 568
  def test_fails_with_incorrect_symbol_that_matches
    get :hello_world
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template :"est/he"
    end
  end

569 570 571 572 573 574 575
  def test_fails_with_wrong_layout
    get :render_with_layout
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template :layout => "application"
    end
  end

576 577 578 579 580 581 582
  def test_fails_expecting_no_layout
    get :render_with_layout
    assert_raise(ActiveSupport::TestCase::Assertion) do
      assert_template :layout => nil
    end
  end

583 584 585
  def test_passes_with_correct_layout
    get :render_with_layout
    assert_template :layout => "layouts/standard"
586 587 588 589 590
  end

  def test_passes_with_layout_and_partial
    get :render_with_layout_and_partial
    assert_template :layout => "layouts/standard"
591 592
  end

593 594 595 596 597
  def test_passed_with_no_layout
    get :hello_world
    assert_template :layout => nil
  end

598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
  def test_passed_with_no_layout_false
    get :hello_world
    assert_template :layout => false
  end

  def test_passes_with_correct_layout_without_layouts_prefix
    get :render_with_layout
    assert_template :layout => "standard"
  end

  def test_passes_with_correct_layout_symbol
    get :render_with_layout
    assert_template :layout => :standard
  end

613 614 615 616 617 618 619
  def test_assert_template_reset_between_requests
    get :hello_world
    assert_template 'test/hello_world'

    get :nothing
    assert_template nil
  end
620 621
end

622 623
class ActionPackHeaderTest < ActionController::TestCase
  tests ActionPackAssertionsController
624

D
Initial  
David Heinemeier Hansson 已提交
625
  def test_rendering_xml_sets_content_type
626
    process :hello_xml_world
627
    assert_equal('application/xml; charset=utf-8', @response.headers['Content-Type'])
D
Initial  
David Heinemeier Hansson 已提交
628
  end
629

D
Initial  
David Heinemeier Hansson 已提交
630
  def test_rendering_xml_respects_content_type
631 632 633 634 635 636 637
    process :hello_xml_world_pdf
    assert_equal('application/pdf; charset=utf-8', @response.headers['Content-Type'])
  end

  def test_rendering_xml_respects_content_type_when_set_in_the_header
    process :hello_xml_world_pdf_header
    assert_equal('application/pdf; charset=utf-8', @response.headers['Content-Type'])
D
Initial  
David Heinemeier Hansson 已提交
638
  end
639 640 641

  def test_render_text_with_custom_content_type
    get :render_text_with_custom_content_type
642
    assert_equal 'application/rss+xml; charset=utf-8', @response.headers['Content-Type']
643
  end
644
end