render_test.rb 16.8 KB
Newer Older
1
# encoding: utf-8
2 3 4
require 'abstract_unit'
require 'controller/fake_models'

Y
Yehuda Katz 已提交
5 6 7
class TestController < ActionController::Base
end

8 9
module RenderTestCases
  def setup_view(paths)
10
    @assigns = { :secret => 'in the sauce' }
11
    @view = ActionView::Base.new(paths, @assigns)
12
    @controller_view = TestController.new.view_context
J
Joshua Peek 已提交
13 14 15 16

    # Reload and register danish language for testing
    I18n.reload!
    I18n.backend.store_translations 'da', {}
17
    I18n.backend.store_translations 'pt-BR', {}
J
Joshua Peek 已提交
18 19

    # Ensure original are still the same since we are reindexing view paths
20
    assert_equal ORIGINAL_LOCALES, I18n.available_locales.map {|l| l.to_s }.sort
21 22 23
  end

  def test_render_file
24
    assert_equal "Hello world!", @view.render(:file => "test/hello_world.erb")
25 26 27
  end

  def test_render_file_not_using_full_path
28
    assert_equal "Hello world!", @view.render(:file => "test/hello_world.erb")
29 30 31
  end

  def test_render_file_without_specific_extension
32
    assert_equal "Hello world!", @view.render(:file => "test/hello_world")
33 34
  end

J
Joshua Peek 已提交
35
  def test_render_file_with_localization
36
    old_locale, @view.locale = @view.locale, :da
37 38
    assert_equal "Hey verden", @view.render(:file => "test/hello_world")
  ensure
39
    @view.locale = old_locale
J
Joshua Peek 已提交
40 41
  end

42
  def test_render_file_with_dashed_locale
43
    old_locale, @view.locale = @view.locale, :"pt-BR"
44
    assert_equal "Ola mundo", @view.render(:file => "test/hello_world")
45
  ensure
46
    @view.locale = old_locale
47 48
  end

49
  def test_render_file_at_top_level
50
    assert_equal 'Elastica', @view.render(:file => '/shared')
51 52
  end

53 54
  def test_render_file_with_full_path
    template_path = File.join(File.dirname(__FILE__), '../fixtures/test/hello_world.erb')
55
    assert_equal "Hello world!", @view.render(:file => template_path)
56 57 58
  end

  def test_render_file_with_instance_variables
59
    assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_ivar.erb")
60 61 62 63
  end

  def test_render_file_with_locals
    locals = { :secret => 'in the sauce' }
64
    assert_equal "The secret is in the sauce\n", @view.render(:file => "test/render_file_with_locals.erb", :locals => locals)
65 66 67
  end

  def test_render_file_not_using_full_path_with_dot_in_path
68
    assert_equal "The secret is in the sauce\n", @view.render(:file => "test/dot.directory/render_file_with_ivar")
69 70
  end

71 72 73 74
  def test_render_partial_from_default
    assert_equal "only partial", @view.render("test/partial_only")
  end

75 76 77 78
  def test_render_partial
    assert_equal "only partial", @view.render(:partial => "test/partial_only")
  end

79 80 81 82 83 84 85 86 87 88 89 90 91 92
  def test_render_partial_with_format
    assert_equal 'partial html', @view.render(:partial => 'test/partial')
  end

  def test_render_partial_at_top_level
    # file fixtures/_top_level_partial_only.erb (not fixtures/test)
    assert_equal 'top level partial', @view.render(:partial => '/top_level_partial_only')
  end

  def test_render_partial_with_format_at_top_level
    # file fixtures/_top_level_partial.html.erb (not fixtures/test, with format extension)
    assert_equal 'top level partial html', @view.render(:partial => '/top_level_partial')
  end

93 94 95 96
  def test_render_partial_with_locals
    assert_equal "5", @view.render(:partial => "test/counter", :locals => { :counter_counter => 5 })
  end

97 98 99 100
  def test_render_partial_with_locals_from_default
    assert_equal "only partial", @view.render("test/partial_only", :counter_counter => 5)
  end

101 102 103 104 105 106 107 108 109
  def test_render_partial_with_invalid_name
    @view.render(:partial => "test/200")
    flunk "Render did not raise ArgumentError"
  rescue ArgumentError => e
    assert_equal "The partial name (test/200) is not a valid Ruby identifier; " +
                                "make sure your partial name starts with a letter or underscore, " +
                                "and is followed by any combinations of letters, numbers, or underscores.", e.message
  end

110
  def test_render_partial_with_errors
111
    @view.render(:partial => "test/raise")
C
Carlhuda 已提交
112 113
    flunk "Render did not raise Template::Error"
  rescue ActionView::Template::Error => e
114
    assert_match %r!method.*doesnt_exist!, e.message
115 116
    assert_equal "", e.sub_template_message
    assert_equal "1", e.line_number
117
    assert_equal "1: <%= doesnt_exist %>", e.annoted_source_code.strip
118 119 120 121
    assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name
  end

  def test_render_sub_template_with_errors
122
    @view.render(:template => "test/sub_template_raise")
C
Carlhuda 已提交
123 124
    flunk "Render did not raise Template::Error"
  rescue ActionView::Template::Error => e
125
    assert_match %r!method.*doesnt_exist!, e.message
126 127 128
    assert_equal "Trace of template inclusion: #{File.expand_path("#{FIXTURE_LOAD_PATH}/test/sub_template_raise.html.erb")}", e.sub_template_message
    assert_equal "1", e.line_number
    assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name
129 130
  end

131 132 133 134 135 136 137 138 139 140 141
  def test_render_file_with_errors
    @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH))
    flunk "Render did not raise Template::Error"
  rescue ActionView::Template::Error => e
    assert_match %r!method.*doesnt_exist!, e.message
    assert_equal "", e.sub_template_message
    assert_equal "1", e.line_number
    assert_equal "1: <%= doesnt_exist %>", e.annoted_source_code.strip
    assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name
  end

142 143 144 145
  def test_render_object
    assert_equal "Hello: david", @view.render(:partial => "test/customer", :object => Customer.new("david"))
  end

146 147 148 149
  def test_render_object_with_array
    assert_equal "[1, 2, 3]", @view.render(:partial => "test/object_inspector", :object => [1, 2, 3])
  end

150 151 152
  def test_render_partial_collection
    assert_equal "Hello: davidHello: mary", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ])
  end
153

154 155 156 157 158 159
  def test_render_partial_collection_as_by_string
    assert_equal "david david davidmary mary mary",
      @view.render(:partial => "test/customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => 'customer')
  end

  def test_render_partial_collection_as_by_symbol
160
    assert_equal "david david davidmary mary mary",
161 162
      @view.render(:partial => "test/customer_with_var", :collection => [ Customer.new("david"), Customer.new("mary") ], :as => :customer)
  end
163

164
  def test_render_partial_collection_without_as
165
    assert_equal "local_inspector,local_inspector_counter",
166 167
      @view.render(:partial => "test/local_inspector", :collection => [ Customer.new("mary") ])
  end
168

169 170 171 172 173 174 175 176
  def test_render_partial_with_empty_collection_should_return_nil
    assert_nil @view.render(:partial => "test/customer", :collection => [])
  end

  def test_render_partial_with_nil_collection_should_return_nil
    assert_nil @view.render(:partial => "test/customer", :collection => nil)
  end

177 178 179 180
  def test_render_partial_with_nil_values_in_collection
    assert_equal "Hello: davidHello: Anonymous", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), nil ])
  end

181 182 183 184
  def test_render_partial_with_empty_array_should_return_nil
    assert_nil @view.render(:partial => [])
  end

Y
Yehuda Katz 已提交
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
  def test_render_partial_using_string
    assert_equal "Hello: Anonymous", @controller_view.render('customer')
  end

  def test_render_partial_with_locals_using_string
    assert_equal "Hola: david", @controller_view.render('customer_greeting', :greeting => 'Hola', :customer_greeting => Customer.new("david"))
  end

  def test_render_partial_using_object
    assert_equal "Hello: lifo",
      @controller_view.render(Customer.new("lifo"), :greeting => "Hello")
  end

  def test_render_partial_using_collection
    customers = [ Customer.new("Amazon"), Customer.new("Yahoo") ]
    assert_equal "Hello: AmazonHello: Yahoo",
      @controller_view.render(customers, :greeting => "Hello")
  end

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
  class CustomerWithDeprecatedPartialPath
    attr_reader :name

    def self.model_name
      Struct.new(:partial_path).new("customers/customer")
    end

    def initialize(name)
      @name = name
    end
  end

  def test_render_partial_using_object_with_deprecated_partial_path
    assert_deprecated(/#model_name.*#partial_path.*#to_path/) do
      assert_equal "Hello: nertzy",
        @controller_view.render(CustomerWithDeprecatedPartialPath.new("nertzy"), :greeting => "Hello")
    end
  end

  def test_render_partial_using_collection_with_deprecated_partial_path
    assert_deprecated(/#model_name.*#partial_path.*#to_path/) do
      customers = [
        CustomerWithDeprecatedPartialPath.new("nertzy"),
        CustomerWithDeprecatedPartialPath.new("peeja")
      ]
      assert_equal "Hello: nertzyHello: peeja",
        @controller_view.render(customers, :greeting => "Hello")
    end
  end

234 235 236 237 238 239 240
  # TODO: The reason for this test is unclear, improve documentation
  def test_render_partial_and_fallback_to_layout
    assert_equal "Before (Josh)\n\nAfter", @view.render(:partial => "test/layout_for_partial", :locals => { :name => "Josh" })
  end

  # TODO: The reason for this test is unclear, improve documentation
  def test_render_missing_xml_partial_and_raise_missing_template
241
    @view.formats = [:xml]
242
    assert_raise(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") }
243 244
  ensure
    @view.formats = nil
245 246
  end

A
Anton Astashov 已提交
247 248 249 250 251
  def test_render_layout_with_block_and_other_partial_inside
    render = @view.render(:layout => "test/layout_with_partial_and_yield.html.erb") { "Yield!" }
    assert_equal "Before\npartial html\nYield!\nAfter\n", render
  end

252 253 254 255 256 257 258 259 260
  def test_render_inline
    assert_equal "Hello, World!", @view.render(:inline => "Hello, World!")
  end

  def test_render_inline_with_locals
    assert_equal "Hello, Josh!", @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" })
  end

  def test_render_fallbacks_to_erb_for_unknown_types
261
    assert_equal "Hello, World!", @view.render(:inline => "Hello, World!", :type => :bar)
262 263
  end

264 265 266
  CustomHandler = lambda do |template|
    "@output_buffer = ''\n" +
      "@output_buffer << 'source: #{template.source.inspect}'\n"
267 268
  end

269 270 271 272 273
  def test_render_inline_with_render_from_to_proc
    ActionView::Template.register_template_handler :ruby_handler, :source.to_proc
    assert_equal '3', @view.render(:inline => "(1 + 2).to_s", :type => :ruby_handler)
  end

274
  def test_render_inline_with_compilable_custom_type
275
    ActionView::Template.register_template_handler :foo, CustomHandler
276
    assert_equal 'source: "Hello, World!"', @view.render(:inline => "Hello, World!", :type => :foo)
277 278 279
  end

  def test_render_inline_with_locals_and_compilable_custom_type
280
    ActionView::Template.register_template_handler :foo, CustomHandler
281
    assert_equal 'source: "Hello, <%= name %>!"', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo)
282
  end
283

284 285 286 287 288 289
  def test_render_ignores_templates_with_malformed_template_handlers
    %w(malformed malformed.erb malformed.html.erb malformed.en.html.erb).each do |name|
      assert_raise(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") }
    end
  end

290 291 292 293 294
  def test_render_with_layout
    assert_equal %(<title></title>\nHello world!\n),
      @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield")
  end

295 296 297 298 299
  def test_render_with_layout_which_has_render_inline
    assert_equal %(welcome\nHello world!\n),
      @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_inline_inside")
  end

300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
  def test_render_with_layout_which_renders_another_partial
    assert_equal %(partial html\nHello world!\n),
      @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_partial_inside")
  end

  def test_render_layout_with_block_and_yield
    assert_equal %(Content from block!\n),
      @view.render(:layout => "layouts/yield_only") { "Content from block!" }
  end

  def test_render_layout_with_block_and_yield_with_params
    assert_equal %(Yield! Content from block!\n),
      @view.render(:layout => "layouts/yield_with_params") { |param| "#{param} Content from block!" }
  end

  def test_render_layout_with_block_which_renders_another_partial_and_yields
    assert_equal %(partial html\nContent from block!\n),
      @view.render(:layout => "layouts/partial_and_yield") { "Content from block!" }
  end

320 321 322 323 324 325 326 327 328 329
  def test_render_partial_and_layout_without_block_with_locals
    assert_equal %(Before (Foo!)\npartial html\nAfter),
      @view.render(:partial => 'test/partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
  end

  def test_render_partial_and_layout_without_block_with_locals_and_rendering_another_partial
    assert_equal %(Before (Foo!)\npartial html\npartial with partial\n\nAfter),
      @view.render(:partial => 'test/partial_with_partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
  end

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
  def test_render_layout_with_a_nested_render_layout_call
    assert_equal %(Before (Foo!)\nBefore (Bar!)\npartial html\nAfter\npartial with layout\n\nAfter),
      @view.render(:partial => 'test/partial_with_layout', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
  end

  def test_render_layout_with_a_nested_render_layout_call_using_block_with_render_partial
    assert_equal %(Before (Foo!)\nBefore (Bar!)\n\n  partial html\n\nAfterpartial with layout\n\nAfter),
      @view.render(:partial => 'test/partial_with_layout_block_partial', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
  end

  def test_render_layout_with_a_nested_render_layout_call_using_block_with_render_content
    assert_equal %(Before (Foo!)\nBefore (Bar!)\n\n  Content from inside layout!\n\nAfterpartial with layout\n\nAfter),
      @view.render(:partial => 'test/partial_with_layout_block_content', :layout => 'test/layout_for_partial', :locals => { :name => 'Foo!'})
  end

345
  def test_render_with_nested_layout
346
    assert_equal %(<title>title</title>\n\n<div id="column">column</div>\n<div id="content">content</div>\n),
347 348
      @view.render(:file => "test/nested_layout.erb", :layout => "layouts/yield")
  end
349

350 351 352 353
  def test_render_with_file_in_layout
    assert_equal %(\n<title>title</title>\n\n),
      @view.render(:file => "test/layout_render_file.erb")
  end
354 355 356 357 358

  def test_render_layout_with_object
    assert_equal %(<title>David</title>),
      @view.render(:file => "test/layout_render_object.erb")
  end
359
end
360

Y
Yehuda Katz 已提交
361
class CachedViewRenderTest < ActiveSupport::TestCase
362 363 364 365 366
  include RenderTestCases

  # Ensure view path cache is primed
  def setup
    view_paths = ActionController::Base.view_paths
367
    assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class
368 369
    setup_view(view_paths)
  end
W
wycats 已提交
370 371 372 373

  def teardown
    GC.start
  end
374 375
end

Y
Yehuda Katz 已提交
376
class LazyViewRenderTest < ActiveSupport::TestCase
377 378
  include RenderTestCases

379 380 381
  # Test the same thing as above, but make sure the view path
  # is not eager loaded
  def setup
382
    path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH)
383
    view_paths = ActionView::Base.process_view_paths(path)
384
    assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first
385
    setup_view(view_paths)
386
  end
W
wycats 已提交
387 388 389 390

  def teardown
    GC.start
  end
391 392 393 394 395 396

  if '1.9'.respond_to?(:force_encoding)
    def test_render_utf8_template_with_magic_comment
      with_external_encoding Encoding::ASCII_8BIT do
        result = @view.render(:file => "test/utf8_magic.html.erb", :layouts => "layouts/yield")
        assert_equal Encoding::UTF_8, result.encoding
397
        assert_equal "\nРусский \nтекст\n\nUTF-8\nUTF-8\nUTF-8\n", result
398 399 400 401 402 403 404
      end
    end

    def test_render_utf8_template_with_default_external_encoding
      with_external_encoding Encoding::UTF_8 do
        result = @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield")
        assert_equal Encoding::UTF_8, result.encoding
405
        assert_equal "Русский текст\n\nUTF-8\nUTF-8\nUTF-8\n", result
406 407 408 409
      end
    end

    def test_render_utf8_template_with_incompatible_external_encoding
410
      with_external_encoding Encoding::SHIFT_JIS do
411
        begin
412
          @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield")
413 414
          flunk 'Should have raised incompatible encoding error'
        rescue ActionView::Template::Error => error
415
          assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message
416 417 418 419
        end
      end
    end

420
    def test_render_utf8_template_with_partial_with_incompatible_encoding
421
      with_external_encoding Encoding::SHIFT_JIS do
422
        begin
423
          @view.render(:file => "test/utf8_magic_with_bare_partial.html.erb", :layouts => "layouts/yield")
424 425
          flunk 'Should have raised incompatible encoding error'
        rescue ActionView::Template::Error => error
426
          assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message
427 428 429 430
        end
      end
    end

431
    def with_external_encoding(encoding)
432 433
      old = Encoding.default_external
      silence_warnings { Encoding.default_external = encoding }
434 435
      yield
    ensure
436
      silence_warnings { Encoding.default_external = old }
437 438
    end
  end
439
end