render_test.rb 15.2 KB
Newer Older
1 2
require 'abstract_unit'
require 'controller/fake_models'
D
Initial  
David Heinemeier Hansson 已提交
3

4 5
module Fun
  class GamesController < ActionController::Base
D
Initial  
David Heinemeier Hansson 已提交
6 7
    def hello_world
    end
8 9
  end
end
D
Initial  
David Heinemeier Hansson 已提交
10

11 12
class TestController < ActionController::Base
  layout :determine_layout
D
Initial  
David Heinemeier Hansson 已提交
13

14 15
  def hello_world
  end
D
Initial  
David Heinemeier Hansson 已提交
16

17
  def conditional_hello
18 19 20 21 22 23 24 25
    response.last_modified = Time.now.utc.beginning_of_day
    response.etag = [:foo, 123]

    if request.fresh?(response)
      head :not_modified
    else
      render :action => 'hello_world'
    end
26 27
  end

28
  def render_hello_world
29
    render :template => "test/hello_world"
30
  end
D
Initial  
David Heinemeier Hansson 已提交
31

32 33 34
  def render_hello_world_with_forward_slash
    render :template => "/test/hello_world"
  end
35

36 37 38
  def render_template_in_top_directory
    render :template => 'shared'
  end
39

40 41 42
  def render_template_in_top_directory_with_slash
    render :template => '/shared'
  end
43

44 45
  def render_hello_world_from_variable
    @person = "david"
46
    render :text => "hello #{@person}"
47
  end
D
Initial  
David Heinemeier Hansson 已提交
48

49
  def render_action_hello_world
50
    render :action => "hello_world"
51
  end
52 53

  def render_action_hello_world_with_symbol
54
    render :action => :hello_world
55
  end
J
Jeremy Kemper 已提交
56

57
  def render_text_hello_world
58
    render :text => "hello world"
59
  end
60

61
  def render_json_hello_world
62
    render :json => {:hello => 'world'}.to_json
63
  end
64

65
  def render_json_hello_world_with_callback
66
    render :json => {:hello => 'world'}.to_json, :callback => 'alert'
67
  end
D
Initial  
David Heinemeier Hansson 已提交
68

69 70 71 72
  def render_json_with_custom_content_type
    render :json => {:hello => 'world'}.to_json, :content_type => 'text/javascript'
  end

73 74 75 76
  def render_symbol_json
    render :json => {:hello => 'world'}.to_json
  end

77
  def render_custom_code
78
    render :text => "hello world", :status => 404
79 80
  end

81 82 83 84 85 86
  def render_custom_code_rjs
    render :update, :status => 404 do |page|
      page.replace :foo, :partial => 'partial'
    end
  end

87 88 89 90 91 92 93 94
  def render_text_with_nil
    render :text => nil
  end

  def render_text_with_false
    render :text => false
  end

95
  def render_nothing_with_appendix
96 97
    render :text => "appended"
  end
98

99 100
  def render_invalid_args
    render("test/hello")
101 102
  end

103 104
  def render_xml_hello
    @name = "David"
105
    render :template => "test/hello"
106
  end
107

108 109 110 111
  def render_xml_with_custom_content_type
    render :xml => "<blah/>", :content_type => "application/atomsvc+xml"
  end

112
  def render_line_offset
113
    render :inline => '<% raise %>', :locals => {:foo => 'bar'}
114 115
  end

116 117 118 119
  def heading
    head :ok
  end

120 121
  def greeting
    # let's just rely on the template
122 123
  end

124
  def layout_test
125
    render :action => "hello_world"
126
  end
J
Jeremy Kemper 已提交
127

128
  def builder_layout_test
129
    render :action => "hello"
130 131
  end

132
  def builder_partial_test
133
    render :action => "hello_world_container"
134 135
  end

136
  def partials_list
137
    @test_unchanged = 'hello'
138
    @customers = [ Customer.new("david"), Customer.new("mary") ]
139
    render :action => "list"
140 141
  end

142
  def partial_only
143
    render :partial => true
144 145
  end

146 147
  def hello_in_a_string
    @customers = [ Customer.new("david"), Customer.new("mary") ]
148
    render :text => "How's there? " + render_to_string(:template => "test/list")
149
  end
J
Jeremy Kemper 已提交
150

151
  def accessing_params_in_template
152
    render :inline => "Hello: <%= params[:name] %>"
153
  end
154

155 156
  def accessing_local_assigns_in_inline_template
    name = params[:local_name]
157 158
    render :inline => "<%= 'Goodbye, ' + local_name %>",
           :locals => { :local_name => name }
159
  end
J
Jeremy Kemper 已提交
160

161 162 163 164 165 166
  def formatted_html_erb
  end

  def formatted_xml_erb
  end

167 168 169 170
  def render_to_string_test
    @foo = render_to_string :inline => "this is a test"
  end

171 172 173
  def partial
    render :partial => 'partial'
  end
174 175 176 177

  def partial_dot_html
    render :partial => 'partial.html.erb'
  end
178

179 180 181 182 183 184
  def partial_as_rjs
    render :update do |page|
      page.replace :foo, :partial => 'partial'
    end
  end

185 186 187 188 189 190 191 192 193 194
  def respond_to_partial_as_rjs
    respond_to do |format|
      format.js do
        render :update do |page|
          page.replace :foo, :partial => 'partial'
        end
      end
    end
  end

195 196 197 198 199 200 201 202 203 204
  def default_render
    if @alternate_default_render
      @alternate_default_render.call
    else
      render
    end
  end

  def render_alternate_default
    # For this test, the method "default_render" is overridden:
205 206 207 208 209
    @alternate_default_render = lambda do
      render :update do |page|
        page.replace :foo, :partial => 'partial'
      end
    end
210 211
  end

212
  def rescue_action(e) raise end
J
Jeremy Kemper 已提交
213

214 215
  private
    def determine_layout
J
Jeremy Kemper 已提交
216
      case action_name
217 218 219
        when "layout_test";         "layouts/standard"
        when "builder_layout_test"; "layouts/builder"
        when "render_symbol_json";  "layouts/standard"  # to make sure layouts don't interfere
220
      end
D
Initial  
David Heinemeier Hansson 已提交
221
    end
222
end
223

224
class RenderTest < Test::Unit::TestCase
D
Initial  
David Heinemeier Hansson 已提交
225 226 227
  def setup
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
228
    @controller = TestController.new
D
Initial  
David Heinemeier Hansson 已提交
229 230 231 232 233

    @request.host = "www.nextangle.com"
  end

  def test_simple_show
234
    get :hello_world
235 236
    assert_response 200
    assert_template "test/hello_world"
D
Initial  
David Heinemeier Hansson 已提交
237 238
  end

239
  def test_render
240
    get :render_hello_world
241
    assert_template "test/hello_world"
D
Initial  
David Heinemeier Hansson 已提交
242 243
  end

244
  def test_line_offset
245 246 247 248 249 250 251 252 253
    begin
      get :render_line_offset
      flunk "the action should have raised an exception"
    rescue RuntimeError => exc
      line = exc.backtrace.first
      assert(line =~ %r{:(\d+):})
      assert_equal "1", $1,
        "The line offset is wrong, perhaps the wrong exception has been raised, exception was: #{exc.inspect}"
    end
254 255
  end

256 257 258 259
  def test_render_with_forward_slash
    get :render_hello_world_with_forward_slash
    assert_template "test/hello_world"
  end
260

261 262 263 264 265
  def test_render_in_top_directory
    get :render_template_in_top_directory
    assert_template "shared"
    assert_equal "Elastica", @response.body
  end
266

267 268 269 270 271
  def test_render_in_top_directory_with_slash
    get :render_template_in_top_directory_with_slash
    assert_template "shared"
    assert_equal "Elastica", @response.body
  end
272

273
  def test_render_from_variable
274
    get :render_hello_world_from_variable
275
    assert_equal "hello david", @response.body
D
Initial  
David Heinemeier Hansson 已提交
276 277
  end

278
  def test_render_action
279
    get :render_action_hello_world
280
    assert_template "test/hello_world"
D
Initial  
David Heinemeier Hansson 已提交
281 282
  end

283
  def test_render_action_with_symbol
284
    get :render_action_hello_world_with_symbol
285
    assert_template "test/hello_world"
286 287
  end

288
  def test_render_text
289
    get :render_text_hello_world
290
    assert_equal "hello world", @response.body
D
Initial  
David Heinemeier Hansson 已提交
291
  end
292

293
  def test_render_json
294
    get :render_json_hello_world
295
    assert_equal '{"hello": "world"}', @response.body
296
    assert_equal 'application/json', @response.content_type
297
  end
298

299
  def test_render_json_with_callback
300
    get :render_json_hello_world_with_callback
301
    assert_equal 'alert({"hello": "world"})', @response.body
302
    assert_equal 'application/json', @response.content_type
303
  end
D
Initial  
David Heinemeier Hansson 已提交
304

305 306 307 308 309 310 311
  def test_render_json_with_custom_content_type
    get :render_json_with_custom_content_type
    assert_equal '{"hello": "world"}', @response.body
    assert_equal 'text/javascript', @response.content_type
  end

  def test_render_symbol_json
312
    get :render_symbol_json
313
    assert_equal '{"hello": "world"}', @response.body
314 315 316
    assert_equal 'application/json', @response.content_type
  end

317
  def test_render_custom_code
318
    get :render_custom_code
319
    assert_response 404
320
    assert_equal 'hello world', @response.body
321 322
  end

323 324 325 326 327 328
  def test_render_custom_code_rjs
    get :render_custom_code_rjs
    assert_response 404
    assert_equal %(Element.replace("foo", "partial html");), @response.body
  end

329 330 331 332 333 334 335 336 337 338 339
  def test_render_text_with_nil
    get :render_text_with_nil
    assert_response 200
    assert_equal '', @response.body
  end

  def test_render_text_with_false
    get :render_text_with_false
    assert_equal 'false', @response.body
  end

340
  def test_render_nothing_with_appendix
341 342 343 344
    get :render_nothing_with_appendix
    assert_response 200
    assert_equal 'appended', @response.body
  end
345

346 347 348
  def test_attempt_to_render_with_invalid_arguments
    assert_raises(ActionController::RenderError) { get :render_invalid_args }
  end
349

D
Initial  
David Heinemeier Hansson 已提交
350
  def test_attempt_to_access_object_method
351
    assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
D
Initial  
David Heinemeier Hansson 已提交
352 353
  end

354
  def test_private_methods
355
    assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
356 357
  end

D
Initial  
David Heinemeier Hansson 已提交
358
  def test_render_xml
359
    get :render_xml_hello
360
    assert_equal "<html>\n  <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
361
    assert_equal "application/xml", @response.content_type
D
Initial  
David Heinemeier Hansson 已提交
362 363 364
  end

  def test_render_xml_with_default
365
    get :greeting
366
    assert_equal "<p>This is grand!</p>\n", @response.body
D
Initial  
David Heinemeier Hansson 已提交
367 368
  end

369 370 371 372 373
  def test_render_xml_with_partial
    get :builder_partial_test
    assert_equal "<test>\n  <hello/>\n</test>\n", @response.body
  end

D
Initial  
David Heinemeier Hansson 已提交
374
  def test_layout_rendering
375
    get :layout_test
376
    assert_equal "<html>Hello world!</html>", @response.body
D
Initial  
David Heinemeier Hansson 已提交
377 378 379
  end

  def test_render_xml_with_layouts
380
    get :builder_layout_test
381
    assert_equal "<wrapper>\n<html>\n  <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
D
Initial  
David Heinemeier Hansson 已提交
382 383
  end

384
  # def test_partials_list
385
  #   get :partials_list
386 387
  #   assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body
  # end
D
Initial  
David Heinemeier Hansson 已提交
388

389
  def test_partial_only
390
    get :partial_only
391
    assert_equal "only partial", @response.body
392 393
  end

394
  def test_render_to_string
395
    get :hello_in_a_string
396
    assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body
397 398 399
  end

  def test_render_to_string_resets_assigns
400
    get :render_to_string_test
401
    assert_equal "The value of foo is: ::this is a test::\n", @response.body
402 403
  end

404
  def test_nested_rendering
405 406 407
    @controller = Fun::GamesController.new
    get :hello_world
    assert_equal "Living in a nested world", @response.body
D
Initial  
David Heinemeier Hansson 已提交
408 409
  end

410
  def test_accessing_params_in_template
411
    get :accessing_params_in_template, :name => "David"
412
    assert_equal "Hello: David", @response.body
413 414
  end

415
  def test_accessing_local_assigns_in_inline_template
416
    get :accessing_local_assigns_in_inline_template, :local_name => "Local David"
417
    assert_equal "Goodbye, Local David", @response.body
418
  end
J
Jeremy Kemper 已提交
419

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
  def test_should_render_formatted_template
    get :formatted_html_erb
    assert_equal 'formatted html erb', @response.body
  end

  def test_should_render_formatted_xml_erb_template
    get :formatted_xml_erb, :format => :xml
    assert_equal '<test>passed formatted xml erb</test>', @response.body
  end

  def test_should_render_formatted_html_erb_template
    get :formatted_xml_erb
    assert_equal '<test>passed formatted html erb</test>', @response.body
  end

  def test_should_render_formatted_html_erb_template_with_faulty_accepts_header
    @request.env["HTTP_ACCEPT"] = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*"
    get :formatted_xml_erb
    assert_equal '<test>passed formatted html erb</test>', @response.body
  end

  def test_should_render_html_formatted_partial
    get :partial
    assert_equal 'partial html', @response.body
  end

  def test_should_render_html_partial_with_dot
    get :partial_dot_html
    assert_equal 'partial html', @response.body
  end

  def test_should_render_html_formatted_partial_with_rjs
    xhr :get, :partial_as_rjs
    assert_equal %(Element.replace("foo", "partial html");), @response.body
  end

  def test_should_render_html_formatted_partial_with_rjs_and_js_format
    xhr :get, :respond_to_partial_as_rjs
    assert_equal %(Element.replace("foo", "partial html");), @response.body
  end

  def test_should_render_js_partial
    xhr :get, :partial, :format => 'js'
    assert_equal 'partial js', @response.body
  end

  def test_should_render_with_alternate_default_render
    xhr :get, :render_alternate_default
    assert_equal %(Element.replace("foo", "partial html");), @response.body
  end

  def test_should_render_xml_but_keep_custom_content_type
    get :render_xml_with_custom_content_type
    assert_equal "application/atomsvc+xml", @response.content_type
  end
475 476 477 478 479

  def test_should_use_implicit_content_type
    get :implicit_content_type, :format => 'atom'
    assert_equal Mime::ATOM, @response.content_type
  end
480 481 482 483 484 485 486 487 488 489 490
end

class EtagRenderTest < Test::Unit::TestCase
  def setup
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    @controller = TestController.new

    @request.host = "www.nextangle.com"
  end

491 492
  def test_render_200_should_set_etag
    get :render_hello_world_from_variable
D
David Heinemeier Hansson 已提交
493
    assert_equal etag_for("hello david"), @response.headers['ETag']
494
    assert_equal "private, max-age=0, must-revalidate", @response.headers['Cache-Control']
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
  end

  def test_render_against_etag_request_should_304_when_match
    @request.headers["HTTP_IF_NONE_MATCH"] = etag_for("hello david")
    get :render_hello_world_from_variable
    assert_equal "304 Not Modified", @response.headers['Status']
    assert @response.body.empty?
  end

  def test_render_against_etag_request_should_200_when_no_match
    @request.headers["HTTP_IF_NONE_MATCH"] = etag_for("hello somewhere else")
    get :render_hello_world_from_variable
    assert_equal "200 OK", @response.headers['Status']
    assert !@response.body.empty?
  end

  def test_render_with_etag
    get :render_hello_world_from_variable
513
    expected_etag = etag_for('hello david')
D
David Heinemeier Hansson 已提交
514
    assert_equal expected_etag, @response.headers['ETag']
515

516 517 518
    @request.headers["HTTP_IF_NONE_MATCH"] = expected_etag
    get :render_hello_world_from_variable
    assert_equal "304 Not Modified", @response.headers['Status']
519

520 521 522 523 524 525 526
    @request.headers["HTTP_IF_NONE_MATCH"] = "\"diftag\""
    get :render_hello_world_from_variable
    assert_equal "200 OK", @response.headers['Status']
  end

  def render_with_404_shouldnt_have_etag
    get :render_custom_code
D
David Heinemeier Hansson 已提交
527
    assert_nil @response.headers['ETag']
528 529
  end

530 531
  def test_etag_should_not_be_changed_when_already_set
    expected_etag = etag_for("hello somewhere else")
D
David Heinemeier Hansson 已提交
532
    @response.headers["ETag"] = expected_etag
533
    get :render_hello_world_from_variable
D
David Heinemeier Hansson 已提交
534
    assert_equal expected_etag, @response.headers['ETag']
535 536
  end

537 538
  def test_etag_should_govern_renders_with_layouts_too
    get :builder_layout_test
539
    assert_equal "<wrapper>\n<html>\n  <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body
D
David Heinemeier Hansson 已提交
540
    assert_equal etag_for("<wrapper>\n<html>\n  <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n"), @response.headers['ETag']
541 542
  end

543 544 545 546 547
  protected
    def etag_for(text)
      %("#{Digest::MD5.hexdigest(text)}")
    end
end
548

549 550 551 552 553
class LastModifiedRenderTest < Test::Unit::TestCase
  def setup
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    @controller = TestController.new
554

555 556
    @request.host = "www.nextangle.com"
    @last_modified = Time.now.utc.beginning_of_day.httpdate
557 558
  end

559 560 561
  def test_responds_with_last_modified
    get :conditional_hello
    assert_equal @last_modified, @response.headers['Last-Modified']
562 563
  end

564 565 566 567 568 569
  def test_request_not_modified
    @request.headers["HTTP_IF_MODIFIED_SINCE"] = @last_modified
    get :conditional_hello
    assert_equal "304 Not Modified", @response.headers['Status']
    assert @response.body.blank?, @response.body
    assert_equal @last_modified, @response.headers['Last-Modified']
570 571
  end

572 573 574 575 576 577
  def test_request_modified
    @request.headers["HTTP_IF_MODIFIED_SINCE"] = 'Thu, 16 Jul 2008 00:00:00 GMT'
    get :conditional_hello
    assert_equal "200 OK", @response.headers['Status']
    assert !@response.body.blank?
    assert_equal @last_modified, @response.headers['Last-Modified']
578
  end
579
end