render_test.rb 15.0 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 18 19 20 21 22
  def conditional_hello
    etag! [:foo, 123]
    last_modified! Time.now.utc.beginning_of_day
    render :action => 'hello_world' unless performed?
  end

23
  def render_hello_world
24
    render :template => "test/hello_world"
25
  end
D
Initial  
David Heinemeier Hansson 已提交
26

27 28 29
  def render_hello_world_with_forward_slash
    render :template => "/test/hello_world"
  end
30

31 32 33
  def render_template_in_top_directory
    render :template => 'shared'
  end
34

35 36 37
  def render_template_in_top_directory_with_slash
    render :template => '/shared'
  end
38

39 40
  def render_hello_world_from_variable
    @person = "david"
41
    render :text => "hello #{@person}"
42
  end
D
Initial  
David Heinemeier Hansson 已提交
43

44
  def render_action_hello_world
45
    render :action => "hello_world"
46
  end
47 48

  def render_action_hello_world_with_symbol
49
    render :action => :hello_world
50
  end
J
Jeremy Kemper 已提交
51

52
  def render_text_hello_world
53
    render :text => "hello world"
54
  end
55

56
  def render_json_hello_world
57
    render :json => {:hello => 'world'}.to_json
58
  end
59

60
  def render_json_hello_world_with_callback
61
    render :json => {:hello => 'world'}.to_json, :callback => 'alert'
62
  end
D
Initial  
David Heinemeier Hansson 已提交
63

64 65 66 67
  def render_json_with_custom_content_type
    render :json => {:hello => 'world'}.to_json, :content_type => 'text/javascript'
  end

68 69 70 71
  def render_symbol_json
    render :json => {:hello => 'world'}.to_json
  end

72
  def render_custom_code
73
    render :text => "hello world", :status => 404
74 75
  end

76 77 78 79 80 81
  def render_custom_code_rjs
    render :update, :status => 404 do |page|
      page.replace :foo, :partial => 'partial'
    end
  end

82 83 84 85 86 87 88 89
  def render_text_with_nil
    render :text => nil
  end

  def render_text_with_false
    render :text => false
  end

90
  def render_nothing_with_appendix
91 92
    render :text => "appended"
  end
93

94 95
  def render_invalid_args
    render("test/hello")
96 97
  end

98 99
  def render_xml_hello
    @name = "David"
100
    render :template => "test/hello"
101
  end
102

103 104 105 106
  def render_xml_with_custom_content_type
    render :xml => "<blah/>", :content_type => "application/atomsvc+xml"
  end

107
  def render_line_offset
108
    render :inline => '<% raise %>', :locals => {:foo => 'bar'}
109 110
  end

111 112 113 114
  def heading
    head :ok
  end

115 116
  def greeting
    # let's just rely on the template
117 118
  end

119
  def layout_test
120
    render :action => "hello_world"
121
  end
J
Jeremy Kemper 已提交
122

123
  def builder_layout_test
124
    render :action => "hello"
125 126
  end

127
  def builder_partial_test
128
    render :action => "hello_world_container"
129 130
  end

131
  def partials_list
132
    @test_unchanged = 'hello'
133
    @customers = [ Customer.new("david"), Customer.new("mary") ]
134
    render :action => "list"
135 136
  end

137
  def partial_only
138
    render :partial => true
139 140
  end

141 142
  def hello_in_a_string
    @customers = [ Customer.new("david"), Customer.new("mary") ]
143
    render :text => "How's there? " + render_to_string(:template => "test/list")
144
  end
J
Jeremy Kemper 已提交
145

146
  def accessing_params_in_template
147
    render :inline => "Hello: <%= params[:name] %>"
148
  end
149

150 151
  def accessing_local_assigns_in_inline_template
    name = params[:local_name]
152 153
    render :inline => "<%= 'Goodbye, ' + local_name %>",
           :locals => { :local_name => name }
154
  end
J
Jeremy Kemper 已提交
155

156 157 158 159 160 161
  def formatted_html_erb
  end

  def formatted_xml_erb
  end

162 163 164 165
  def render_to_string_test
    @foo = render_to_string :inline => "this is a test"
  end

166 167 168
  def partial
    render :partial => 'partial'
  end
169 170 171 172

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

174 175 176 177 178 179
  def partial_as_rjs
    render :update do |page|
      page.replace :foo, :partial => 'partial'
    end
  end

180 181 182 183 184 185 186 187 188 189
  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

190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
  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:
    @alternate_default_render = lambda {
	render :update do |page|
	  page.replace :foo, :partial => 'partial'
	end
      }
  end

207
  def rescue_action(e) raise end
J
Jeremy Kemper 已提交
208

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

219
class RenderTest < Test::Unit::TestCase
D
Initial  
David Heinemeier Hansson 已提交
220 221 222
  def setup
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
223
    @controller = TestController.new
D
Initial  
David Heinemeier Hansson 已提交
224 225 226 227 228

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

  def test_simple_show
229
    get :hello_world
230 231
    assert_response 200
    assert_template "test/hello_world"
D
Initial  
David Heinemeier Hansson 已提交
232 233
  end

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

239
  def test_line_offset
240 241 242 243 244 245 246 247 248
    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
249 250
  end

251 252 253 254
  def test_render_with_forward_slash
    get :render_hello_world_with_forward_slash
    assert_template "test/hello_world"
  end
255

256 257 258 259 260
  def test_render_in_top_directory
    get :render_template_in_top_directory
    assert_template "shared"
    assert_equal "Elastica", @response.body
  end
261

262 263 264 265 266
  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
267

268
  def test_render_from_variable
269
    get :render_hello_world_from_variable
270
    assert_equal "hello david", @response.body
D
Initial  
David Heinemeier Hansson 已提交
271 272
  end

273
  def test_render_action
274
    get :render_action_hello_world
275
    assert_template "test/hello_world"
D
Initial  
David Heinemeier Hansson 已提交
276 277
  end

278
  def test_render_action_with_symbol
279
    get :render_action_hello_world_with_symbol
280
    assert_template "test/hello_world"
281 282
  end

283
  def test_render_text
284
    get :render_text_hello_world
285
    assert_equal "hello world", @response.body
D
Initial  
David Heinemeier Hansson 已提交
286
  end
287

288
  def test_render_json
289
    get :render_json_hello_world
290
    assert_equal '{"hello": "world"}', @response.body
291
    assert_equal 'application/json', @response.content_type
292
  end
293

294
  def test_render_json_with_callback
295
    get :render_json_hello_world_with_callback
296
    assert_equal 'alert({"hello": "world"})', @response.body
297
    assert_equal 'application/json', @response.content_type
298
  end
D
Initial  
David Heinemeier Hansson 已提交
299

300 301 302 303 304 305 306
  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
307
    get :render_symbol_json
308
    assert_equal '{"hello": "world"}', @response.body
309 310 311
    assert_equal 'application/json', @response.content_type
  end

312
  def test_render_custom_code
313
    get :render_custom_code
314
    assert_response 404
315
    assert_equal 'hello world', @response.body
316 317
  end

318 319 320 321 322 323
  def test_render_custom_code_rjs
    get :render_custom_code_rjs
    assert_response 404
    assert_equal %(Element.replace("foo", "partial html");), @response.body
  end

324 325 326 327 328 329 330 331 332 333 334
  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

335
  def test_render_nothing_with_appendix
336 337 338 339
    get :render_nothing_with_appendix
    assert_response 200
    assert_equal 'appended', @response.body
  end
340

341 342 343
  def test_attempt_to_render_with_invalid_arguments
    assert_raises(ActionController::RenderError) { get :render_invalid_args }
  end
344

D
Initial  
David Heinemeier Hansson 已提交
345
  def test_attempt_to_access_object_method
346
    assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone }
D
Initial  
David Heinemeier Hansson 已提交
347 348
  end

349
  def test_private_methods
350
    assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout }
351 352
  end

D
Initial  
David Heinemeier Hansson 已提交
353
  def test_render_xml
354
    get :render_xml_hello
355
    assert_equal "<html>\n  <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body
356
    assert_equal "application/xml", @response.content_type
D
Initial  
David Heinemeier Hansson 已提交
357 358 359
  end

  def test_render_xml_with_default
360
    get :greeting
361
    assert_equal "<p>This is grand!</p>\n", @response.body
D
Initial  
David Heinemeier Hansson 已提交
362 363
  end

364 365 366 367 368
  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 已提交
369
  def test_layout_rendering
370
    get :layout_test
371
    assert_equal "<html>Hello world!</html>", @response.body
D
Initial  
David Heinemeier Hansson 已提交
372 373 374
  end

  def test_render_xml_with_layouts
375
    get :builder_layout_test
376
    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 已提交
377 378
  end

379
  # def test_partials_list
380
  #   get :partials_list
381 382
  #   assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body
  # end
D
Initial  
David Heinemeier Hansson 已提交
383

384
  def test_partial_only
385
    get :partial_only
386
    assert_equal "only partial", @response.body
387 388
  end

389
  def test_render_to_string
390
    get :hello_in_a_string
391
    assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body
392 393 394
  end

  def test_render_to_string_resets_assigns
395
    get :render_to_string_test
396
    assert_equal "The value of foo is: ::this is a test::\n", @response.body
397 398
  end

399
  def test_nested_rendering
400 401 402
    @controller = Fun::GamesController.new
    get :hello_world
    assert_equal "Living in a nested world", @response.body
D
Initial  
David Heinemeier Hansson 已提交
403 404
  end

405
  def test_accessing_params_in_template
406
    get :accessing_params_in_template, :name => "David"
407
    assert_equal "Hello: David", @response.body
408 409
  end

410
  def test_accessing_local_assigns_in_inline_template
411
    get :accessing_local_assigns_in_inline_template, :local_name => "Local David"
412
    assert_equal "Goodbye, Local David", @response.body
413
  end
J
Jeremy Kemper 已提交
414

415 416 417 418 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 475 476 477 478 479 480
  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
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

481 482
  def test_render_200_should_set_etag
    get :render_hello_world_from_variable
D
David Heinemeier Hansson 已提交
483
    assert_equal etag_for("hello david"), @response.headers['ETag']
484
    assert_equal "private, max-age=0, must-revalidate", @response.headers['Cache-Control']
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
  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
503
    expected_etag = etag_for('hello david')
D
David Heinemeier Hansson 已提交
504
    assert_equal expected_etag, @response.headers['ETag']
505

506 507 508
    @request.headers["HTTP_IF_NONE_MATCH"] = expected_etag
    get :render_hello_world_from_variable
    assert_equal "304 Not Modified", @response.headers['Status']
509

510 511 512 513 514 515 516
    @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 已提交
517
    assert_nil @response.headers['ETag']
518 519
  end

520 521
  def test_etag_should_not_be_changed_when_already_set
    expected_etag = etag_for("hello somewhere else")
D
David Heinemeier Hansson 已提交
522
    @response.headers["ETag"] = expected_etag
523
    get :render_hello_world_from_variable
D
David Heinemeier Hansson 已提交
524
    assert_equal expected_etag, @response.headers['ETag']
525 526
  end

527 528
  def test_etag_should_govern_renders_with_layouts_too
    get :builder_layout_test
529
    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 已提交
530
    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']
531 532
  end

533 534 535 536 537
  protected
    def etag_for(text)
      %("#{Digest::MD5.hexdigest(text)}")
    end
end
538

539 540 541 542 543
class LastModifiedRenderTest < Test::Unit::TestCase
  def setup
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    @controller = TestController.new
544

545 546
    @request.host = "www.nextangle.com"
    @last_modified = Time.now.utc.beginning_of_day.httpdate
547 548
  end

549 550 551
  def test_responds_with_last_modified
    get :conditional_hello
    assert_equal @last_modified, @response.headers['Last-Modified']
552 553
  end

554 555 556 557 558 559
  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']
560 561
  end

562 563 564 565 566 567
  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']
568
  end
569
end