diff options
Diffstat (limited to 'actionview/test/template')
22 files changed, 756 insertions, 312 deletions
diff --git a/actionview/test/template/asset_tag_helper_test.rb b/actionview/test/template/asset_tag_helper_test.rb index 6e6ce20924..8592a2a083 100644 --- a/actionview/test/template/asset_tag_helper_test.rb +++ b/actionview/test/template/asset_tag_helper_test.rb @@ -27,6 +27,8 @@ class AssetTagHelperTest < ActionView::TestCase end AssetPathToTag = { + %(asset_path("")) => %(), + %(asset_path(" ")) => %(), %(asset_path("foo")) => %(/foo), %(asset_path("style.css")) => %(/style.css), %(asset_path("xmlhr.js")) => %(/xmlhr.js), @@ -97,6 +99,7 @@ class AssetTagHelperTest < ActionView::TestCase %(javascript_include_tag("bank")) => %(<script src="/javascripts/bank.js" ></script>), %(javascript_include_tag("bank.js")) => %(<script src="/javascripts/bank.js" ></script>), %(javascript_include_tag("bank", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/bank.js" ></script>), + %(javascript_include_tag("bank", :host => "assets.example.com")) => %(<script src="http://assets.example.com/javascripts/bank.js"></script>), %(javascript_include_tag("http://example.com/all")) => %(<script src="http://example.com/all"></script>), %(javascript_include_tag("http://example.com/all.js")) => %(<script src="http://example.com/all.js"></script>), @@ -141,6 +144,7 @@ class AssetTagHelperTest < ActionView::TestCase %(stylesheet_link_tag("/elsewhere/file")) => %(<link href="/elsewhere/file.css" media="screen" rel="stylesheet" />), %(stylesheet_link_tag("subdir/subdir")) => %(<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />), %(stylesheet_link_tag("bank", :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" />), + %(stylesheet_link_tag("bank", :host => "assets.example.com")) => %(<link href="http://assets.example.com/stylesheets/bank.css" media="screen" rel="stylesheet" />), %(stylesheet_link_tag("http://www.example.com/styles/style")) => %(<link href="http://www.example.com/styles/style" media="screen" rel="stylesheet" />), %(stylesheet_link_tag("http://www.example.com/styles/style.css")) => %(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" />), @@ -191,7 +195,8 @@ class AssetTagHelperTest < ActionView::TestCase %(image_tag("//www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="//www.rubyonrails.com/images/rails.png" />), %(image_tag("mouse.png", :alt => nil)) => %(<img src="/images/mouse.png" />), %(image_tag("data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==", :alt => nil)) => %(<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />), - %(image_tag("")) => %(<img src="" />) + %(image_tag("")) => %(<img src="" />), + %(image_tag("gold.png", data: { title: 'Rails Application' })) => %(<img data-title="Rails Application" src="/images/gold.png" alt="Gold" />) } FaviconLinkToTag = { @@ -310,6 +315,11 @@ class AssetTagHelperTest < ActionView::TestCase AssetPathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end + def test_asset_path_tag_raises_an_error_for_nil_source + e = assert_raise(ArgumentError) { asset_path(nil) } + assert_equal("nil is not a valid asset source", e.message) + end + def test_asset_path_tag_to_not_create_duplicate_slashes @controller.config.asset_host = "host/" assert_dom_equal('http://host/foo', asset_path("foo")) @@ -583,11 +593,13 @@ class AssetTagHelperTest < ActionView::TestCase end end - @controller.request.stubs(:ssl?).returns(false) - assert_equal "http://assets15.example.com/images/xml.png", image_path("xml.png") + @controller.request.stub(:ssl?, false) do + assert_equal "http://assets15.example.com/images/xml.png", image_path("xml.png") + end - @controller.request.stubs(:ssl?).returns(true) - assert_equal "http://localhost/images/xml.png", image_path("xml.png") + @controller.request.stub(:ssl?, true) do + assert_equal "http://localhost/images/xml.png", image_path("xml.png") + end end end diff --git a/actionview/test/template/date_helper_i18n_test.rb b/actionview/test/template/date_helper_i18n_test.rb index 21fca35185..52aef56a61 100644 --- a/actionview/test/template/date_helper_i18n_test.rb +++ b/actionview/test/template/date_helper_i18n_test.rb @@ -46,8 +46,9 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase end def test_time_ago_in_words_passes_locale - I18n.expects(:t).with(:less_than_x_minutes, :scope => :'datetime.distance_in_words', :count => 1, :locale => 'ru') - time_ago_in_words(15.seconds.ago, :locale => 'ru') + assert_called_with(I18n, :t, [:less_than_x_minutes, :scope => :'datetime.distance_in_words', :count => 1, :locale => 'ru']) do + time_ago_in_words(15.seconds.ago, :locale => 'ru') + end end def test_distance_of_time_pluralizations @@ -80,8 +81,9 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase options = { locale: 'en', scope: :'datetime.distance_in_words' }.merge!(expected_options) options[:count] = count if count - I18n.expects(:t).with(key, options) - distance_of_time_in_words(@from, to, passed_options.merge(locale: 'en')) + assert_called_with(I18n, :t, [key, options]) do + distance_of_time_in_words(@from, to, passed_options.merge(locale: 'en')) + end end end @@ -89,60 +91,74 @@ class DateHelperSelectTagsI18nTests < ActiveSupport::TestCase include ActionView::Helpers::DateHelper attr_reader :request - def setup - @prompt_defaults = {:year => 'Year', :month => 'Month', :day => 'Day', :hour => 'Hour', :minute => 'Minute', :second => 'Seconds'} - - I18n.stubs(:translate).with(:'date.month_names', :locale => 'en').returns Date::MONTHNAMES - end - # select_month def test_select_month_given_use_month_names_option_does_not_translate_monthnames - I18n.expects(:translate).never - select_month(8, :locale => 'en', :use_month_names => Date::MONTHNAMES) + assert_not_called(I18n, :translate) do + select_month(8, :locale => 'en', :use_month_names => Date::MONTHNAMES) + end end def test_select_month_translates_monthnames - I18n.expects(:translate).with(:'date.month_names', :locale => 'en').returns Date::MONTHNAMES - select_month(8, :locale => 'en') + assert_called_with(I18n, :translate, [:'date.month_names', :locale => 'en'], returns: Date::MONTHNAMES) do + select_month(8, :locale => 'en') + end end def test_select_month_given_use_short_month_option_translates_abbr_monthnames - I18n.expects(:translate).with(:'date.abbr_month_names', :locale => 'en').returns Date::ABBR_MONTHNAMES - select_month(8, :locale => 'en', :use_short_month => true) + assert_called_with(I18n, :translate, [:'date.abbr_month_names', :locale => 'en'], returns: Date::ABBR_MONTHNAMES) do + select_month(8, :locale => 'en', :use_short_month => true) + end end def test_date_or_time_select_translates_prompts - @prompt_defaults.each do |key, prompt| - I18n.expects(:translate).with(('datetime.prompts.' + key.to_s).to_sym, :locale => 'en').returns prompt + prompt_defaults = {:year => 'Year', :month => 'Month', :day => 'Day', :hour => 'Hour', :minute => 'Minute', :second => 'Seconds'} + defaults = {[:'date.order', :locale => 'en', :default => []] => %w(year month day)} + + prompt_defaults.each do |key, prompt| + defaults[[('datetime.prompts.' + key.to_s).to_sym, :locale => 'en']] = prompt + end + + prompts_check = -> (prompt, x) do + @prompt_called ||= 0 + + return_value = defaults[[prompt, x]] + @prompt_called += 1 if return_value.present? + + return_value end - I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns %w(year month day) - datetime_select('post', 'updated_at', :locale => 'en', :include_seconds => true, :prompt => true) + I18n.stub(:translate, prompts_check) do + datetime_select('post', 'updated_at', :locale => 'en', :include_seconds => true, :prompt => true, :use_month_names => Date::MONTHNAMES) + end + assert_equal defaults.count, @prompt_called end # date_or_time_select def test_date_or_time_select_given_an_order_options_does_not_translate_order - I18n.expects(:translate).never - datetime_select('post', 'updated_at', :order => [:year, :month, :day], :locale => 'en') + assert_not_called(I18n, :translate) do + datetime_select('post', 'updated_at', :order => [:year, :month, :day], :locale => 'en', :use_month_names => Date::MONTHNAMES) + end end def test_date_or_time_select_given_no_order_options_translates_order - I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns %w(year month day) - datetime_select('post', 'updated_at', :locale => 'en') + assert_called_with(I18n, :translate, [ [:'date.order', :locale => 'en', :default => []], [:"date.month_names", {:locale=>"en"}] ], returns: %w(year month day)) do + datetime_select('post', 'updated_at', :locale => 'en') + end end def test_date_or_time_select_given_invalid_order - I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns %w(invalid month day) - - assert_raise StandardError do - datetime_select('post', 'updated_at', :locale => 'en') + assert_called_with(I18n, :translate, [:'date.order', :locale => 'en', :default => []], returns: %w(invalid month day)) do + assert_raise StandardError do + datetime_select('post', 'updated_at', :locale => 'en') + end end end def test_date_or_time_select_given_symbol_keys - I18n.expects(:translate).with(:'date.order', :locale => 'en', :default => []).returns [:year, :month, :day] - datetime_select('post', 'updated_at', :locale => 'en') + assert_called_with(I18n, :translate, [ [:'date.order', :locale => 'en', :default => []], [:"date.month_names", {:locale=>"en"}] ], returns: [:year, :month, :day]) do + datetime_select('post', 'updated_at', :locale => 'en') + end end end diff --git a/actionview/test/template/date_helper_test.rb b/actionview/test/template/date_helper_test.rb index 9212420ec9..92e77599f4 100644 --- a/actionview/test/template/date_helper_test.rb +++ b/actionview/test/template/date_helper_test.rb @@ -390,11 +390,6 @@ class DateHelperTest < ActionView::TestCase expected << "</select>\n" assert_dom_equal expected, select_month(Time.mktime(2003, 8, 16), {}, :class => 'selector', :accesskey => 'M') - #result = select_month(Time.mktime(2003, 8, 16), {}, :class => 'selector', :accesskey => 'M') - #assert result.include?('<select id="date_month" name="date[month]"') - #assert result.include?('class="selector"') - #assert result.include?('accesskey="M"') - #assert result.include?('<option value="1">January') end def test_select_month_with_default_prompt @@ -474,11 +469,6 @@ class DateHelperTest < ActionView::TestCase expected << "</select>\n" assert_dom_equal expected, select_year(Time.mktime(2003, 8, 16), {:start_year => 2003, :end_year => 2005}, :class => 'selector', :accesskey => 'M') - #result = select_year(Time.mktime(2003, 8, 16), {:start_year => 2003, :end_year => 2005}, :class => 'selector', :accesskey => 'M') - #assert result.include?('<select id="date_year" name="date[year]"') - #assert result.include?('class="selector"') - #assert result.include?('accesskey="M"') - #assert result.include?('<option value="2003"') end def test_select_year_with_default_prompt @@ -639,12 +629,6 @@ class DateHelperTest < ActionView::TestCase expected << "</select>\n" assert_dom_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector', :accesskey => 'M') - - #result = select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector', :accesskey => 'M') - #assert result.include?('<select id="date_minute" name="date[minute]"') - #assert result.include?('class="selector"') - #assert result.include?('accesskey="M"') - #assert result.include?('<option value="00">00') end def test_select_minute_with_default_prompt @@ -709,12 +693,6 @@ class DateHelperTest < ActionView::TestCase expected << "</select>\n" assert_dom_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector', :accesskey => 'M') - - #result = select_second(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector', :accesskey => 'M') - #assert result.include?('<select id="date_second" name="date[second]"') - #assert result.include?('class="selector"') - #assert result.include?('accesskey="M"') - #assert result.include?('<option value="00">00') end def test_select_second_with_default_prompt @@ -1559,6 +1537,26 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, date_select("post", "written_on", :selected => Date.new(2004, 07, 10)) end + def test_date_select_with_selected_in_hash + @post = Post.new + @post.written_on = Date.new(2004, 6, 15) + + expected = %{<select id="post_written_on_1i" name="post[written_on(1i)]">\n} + expected << %{<option value="1999">1999</option>\n<option value="2000">2000</option>\n<option value="2001">2001</option>\n<option value="2002">2002</option>\n<option value="2003">2003</option>\n<option selected="selected" value="2004">2004</option>\n<option value="2005">2005</option>\n<option value="2006">2006</option>\n<option value="2007">2007</option>\n<option value="2008">2008</option>\n<option value="2009">2009</option>\n} + expected << "</select>\n" + + expected << %{<select id="post_written_on_2i" name="post[written_on(2i)]">\n} + expected << %{<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7" selected="selected">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n} + expected << "</select>\n" + + expected << %{<select id="post_written_on_3i" name="post[written_on(3i)]">\n} + expected << %{<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10" selected="selected">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n} + + expected << "</select>\n" + + assert_dom_equal expected, date_select("post", "written_on", :selected => {day: 10, month: 07, year: 2004}) + end + def test_date_select_with_selected_nil @post = Post.new @post.written_on = Date.new(2004, 6, 15) diff --git a/actionview/test/template/dependency_tracker_test.rb b/actionview/test/template/dependency_tracker_test.rb index 672b4747ec..3ece9e50cd 100644 --- a/actionview/test/template/dependency_tracker_test.rb +++ b/actionview/test/template/dependency_tracker_test.rb @@ -1,4 +1,3 @@ - require 'abstract_unit' require 'action_view/dependency_tracker' diff --git a/actionview/test/template/digestor_test.rb b/actionview/test/template/digestor_test.rb index c2b8439df3..dde757b5a2 100644 --- a/actionview/test/template/digestor_test.rb +++ b/actionview/test/template/digestor_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'fileutils' +require 'action_view/dependency_tracker' class FixtureTemplate attr_reader :source, :handler @@ -15,12 +16,13 @@ end class FixtureFinder FIXTURES_DIR = "#{File.dirname(__FILE__)}/../fixtures/digestor" - attr_reader :details + attr_reader :details, :view_paths attr_accessor :formats attr_accessor :variants def initialize @details = {} + @view_paths = ActionView::PathSet.new(['digestor']) @formats = [] @variants = [] end @@ -75,6 +77,34 @@ class TemplateDigestorTest < ActionView::TestCase end end + def test_explicit_dependency_wildcard + assert_digest_difference("events/index") do + change_template("events/_completed") + end + end + + def test_explicit_dependency_wildcard_picks_up_added_file + old_caching, ActionView::Resolver.caching = ActionView::Resolver.caching, false + + assert_digest_difference("events/index") do + add_template("events/_uncompleted") + end + ensure + remove_template("events/_uncompleted") + ActionView::Resolver.caching = old_caching + end + + def test_explicit_dependency_wildcard_picks_up_removed_file + old_caching, ActionView::Resolver.caching = ActionView::Resolver.caching, false + add_template("events/_subscribers_changed") + + assert_digest_difference("events/index") do + remove_template("events/_subscribers_changed") + end + ensure + ActionView::Resolver.caching = old_caching + end + def test_second_level_dependency assert_digest_difference("messages/show") do change_template("comments/_comments") @@ -111,6 +141,18 @@ class TemplateDigestorTest < ActionView::TestCase end end + def test_logging_of_missing_template_for_dependencies + assert_logged "'messages/something_missing' file doesn't exist, so no dependencies" do + dependencies("messages/something_missing") + end + end + + def test_logging_of_missing_template_for_nested_dependencies + assert_logged "'messages/something_missing' file doesn't exist, so no dependencies" do + nested_dependencies("messages/something_missing") + end + end + def test_nested_template_directory assert_digest_difference("messages/show") do change_template("messages/actions/_move") @@ -207,7 +249,7 @@ class TemplateDigestorTest < ActionView::TestCase end def test_variants - assert_digest_difference("messages/new", false, variants: [:iphone]) do + assert_digest_difference("messages/new", variants: [:iphone]) do change_template("messages/new", :iphone) change_template("messages/_header", :iphone) end @@ -227,16 +269,6 @@ class TemplateDigestorTest < ActionView::TestCase assert_not_equal digest_phone, digest_fridge_phone end - def test_cache_template_loading - resolver_before = ActionView::Resolver.caching - ActionView::Resolver.caching = false - assert_digest_difference("messages/edit", true) do - change_template("comments/_comment") - end - ensure - ActionView::Resolver.caching = resolver_before - end - def test_digest_cache_cleanup_with_recursion first_digest = digest("level/_recursion") second_digest = digest("level/_recursion") @@ -279,9 +311,9 @@ class TemplateDigestorTest < ActionView::TestCase end end - def assert_digest_difference(template_name, persistent = false, options = {}) + def assert_digest_difference(template_name, options = {}) previous_digest = digest(template_name, options) - ActionView::Digestor.cache.clear unless persistent + ActionView::Digestor.cache.clear yield @@ -298,6 +330,14 @@ class TemplateDigestorTest < ActionView::TestCase ActionView::Digestor.digest({ name: template_name, finder: finder }.merge(options)) end + def dependencies(template_name) + ActionView::Digestor.new({ name: template_name, finder: finder }).dependencies + end + + def nested_dependencies(template_name) + ActionView::Digestor.new({ name: template_name, finder: finder }).nested_dependencies + end + def finder @finder ||= FixtureFinder.new end @@ -309,4 +349,9 @@ class TemplateDigestorTest < ActionView::TestCase f.write "\nTHIS WAS CHANGED!" end end + alias_method :add_template, :change_template + + def remove_template(template_name) + File.delete("digestor/#{template_name}.html.erb") + end end diff --git a/actionview/test/template/form_collections_helper_test.rb b/actionview/test/template/form_collections_helper_test.rb index b193d387c3..4f7ea88169 100644 --- a/actionview/test/template/form_collections_helper_test.rb +++ b/actionview/test/template/form_collections_helper_test.rb @@ -198,6 +198,41 @@ class FormCollectionsHelperTest < ActionView::TestCase assert_select 'input[type=radio][value=false][checked=checked]' end + test 'collection radio buttons generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_radio_buttons :user, :category_ids, collection, :id, :name + + assert_select "input[type=hidden][name='user[category_ids]'][value='']", count: 1 + end + + test 'collection radio buttons generates a hidden field using the given :name in :html_options' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_radio_buttons :user, :category_ids, collection, :id, :name, {}, { name: "user[other_category_ids]" } + + assert_select "input[type=hidden][name='user[other_category_ids]'][value='']", count: 1 + end + + test 'collection radio buttons generates a hidden field with index if it was provided' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_radio_buttons :user, :category_ids, collection, :id, :name, { index: 322 } + + assert_select "input[type=hidden][name='user[322][category_ids]'][value='']", count: 1 + end + + test 'collection radio buttons does not generate a hidden field if include_hidden option is false' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_radio_buttons :user, :category_ids, collection, :id, :name, include_hidden: false + + assert_select "input[type=hidden][name='user[category_ids]'][value='']", count: 0 + end + + test 'collection radio buttons does not generate a hidden field if include_hidden option is false with key as string' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_radio_buttons :user, :category_ids, collection, :id, :name, 'include_hidden' => false + + assert_select "input[type=hidden][name='user[category_ids]'][value='']", count: 0 + end + # COLLECTION CHECK BOXES test 'collection check boxes accepts a collection and generate a series of checkboxes for value method' do collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] @@ -235,6 +270,13 @@ class FormCollectionsHelperTest < ActionView::TestCase assert_select "input[type=hidden][name='user[category_ids][]'][value='']", :count => 0 end + test 'collection check boxes does not generate a hidden field if include_hidden option is false with key as string' do + collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] + with_collection_check_boxes :user, :category_ids, collection, :id, :name, 'include_hidden' => false + + assert_select "input[type=hidden][name='user[category_ids][]'][value='']", count: 0 + end + test 'collection check boxes accepts a collection and generate a series of checkboxes with labels for label method' do collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')] with_collection_check_boxes :user, :category_ids, collection, :id, :name @@ -264,6 +306,17 @@ class FormCollectionsHelperTest < ActionView::TestCase assert_select 'input[type=checkbox][value="2"].bar' end + test 'collection check boxes propagates input id to the label for attribute' do + collection = [[1, 'Category 1', {id: 'foo'}], [2, 'Category 2', {id: 'bar'}]] + with_collection_check_boxes :user, :active, collection, :first, :second + + assert_select 'input[type=checkbox][value="1"]#foo' + assert_select 'input[type=checkbox][value="2"]#bar' + + assert_select 'label[for=foo]' + assert_select 'label[for=bar]' + end + test 'collection check boxes sets the label class defined inside the block' do collection = [[1, 'Category 1', {class: 'foo'}], [2, 'Category 2', {class: 'bar'}]] with_collection_check_boxes :user, :active, collection, :second, :first do |b| diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb index b8cb5bd746..1be1c68c14 100644 --- a/actionview/test/template/form_helper_test.rb +++ b/actionview/test/template/form_helper_test.rb @@ -128,6 +128,8 @@ class FormHelperTest < ActionView::TestCase @post_delegator.title = 'Hello World' @car = Car.new("#000FFF") + + @ticket_type = TicketType.new end Routes = ActionDispatch::Routing::RouteSet.new @@ -136,6 +138,8 @@ class FormHelperTest < ActionView::TestCase resources :comments end + resources :ticket_types + namespace :admin do resources :posts do resources :comments @@ -366,7 +370,7 @@ class FormHelperTest < ActionView::TestCase ) end - def test_label_with_to_model_and_overriden_model_name + def test_label_with_to_model_and_overridden_model_name with_locale :label do assert_dom_equal( %{<label for="post_delegator_title">Delegate model_name title</label>}, @@ -1281,7 +1285,7 @@ class FormHelperTest < ActionView::TestCase end def test_week_field - expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W24" />} + expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W25" />} assert_dom_equal(expected, week_field("post", "written_on")) end @@ -1292,13 +1296,13 @@ class FormHelperTest < ActionView::TestCase end def test_week_field_with_datetime_value - expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W24" />} + expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W25" />} @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) assert_dom_equal(expected, week_field("post", "written_on")) end def test_week_field_with_extra_attrs - expected = %{<input id="post_written_on" step="2" max="2010-W51" min="2000-W06" name="post[written_on]" type="week" value="2004-W24" />} + expected = %{<input id="post_written_on" step="2" max="2010-W51" min="2000-W06" name="post[written_on]" type="week" value="2004-W25" />} @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) min_value = DateTime.new(2000, 2, 13) max_value = DateTime.new(2010, 12, 23) @@ -1308,13 +1312,19 @@ class FormHelperTest < ActionView::TestCase def test_week_field_with_timewithzone_value previous_time_zone, Time.zone = Time.zone, 'UTC' - expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W24" />} + expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W25" />} @post.written_on = Time.zone.parse('2004-06-15 15:30:45') assert_dom_equal(expected, week_field("post", "written_on")) ensure Time.zone = previous_time_zone end + def test_week_field_week_number_base + expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2015-W01" />} + @post.written_on = DateTime.new(2015, 1, 1, 1, 2, 3) + assert_dom_equal(expected, week_field("post", "written_on")) + end + def test_url_field expected = %{<input id="user_homepage" name="user[homepage]" type="url" />} assert_dom_equal(expected, url_field("user", "homepage")) @@ -1539,9 +1549,10 @@ class FormHelperTest < ActionView::TestCase end def test_form_for_requires_block - assert_raises(ArgumentError) do - form_for(:post, @post, html: { id: 'create-post' }) + error = assert_raises(ArgumentError) do + form_for(@post, html: { id: 'create-post' }) end + assert_equal "Missing block", error.message end def test_form_for_requires_arguments @@ -1577,7 +1588,7 @@ class FormHelperTest < ActionView::TestCase "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + - "<input name='commit' type='submit' value='Create post' />" + + "<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />" + "<button name='button' type='submit'>Create post</button>" + "<button name='button' type='submit'><span>Create post</span></button>" end @@ -1593,6 +1604,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post", "new_post") do + "<input type='hidden' name='post[active]' value='' />" + "<input id='post_active_true' name='post[active]' type='radio' value='true' />" + "<label for='post_active_true'>true</label>" + "<input checked='checked' id='post_active_false' name='post[active]' type='radio' value='false' />" + @@ -1614,6 +1626,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post", "new_post") do + "<input type='hidden' name='post[active]' value='' />" + "<label for='post_active_true'>"+ "<input id='post_active_true' name='post[active]' type='radio' value='true' />" + "true</label>" + @@ -1639,6 +1652,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post_1", "new_post") do + "<input type='hidden' name='post[active]' value='' />" + "<label for='post_active_true'>"+ "<input id='post_active_true' name='post[active]' type='radio' value='true' />" + "true</label>" + @@ -1660,6 +1674,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "foo_new_post", "new_post") do + "<input type='hidden' name='post[active]' value='' />" + "<input id='foo_post_active_true' name='post[active]' type='radio' value='true' />" + "<label for='foo_post_active_true'>true</label>" + "<input checked='checked' id='foo_post_active_false' name='post[active]' type='radio' value='false' />" + @@ -1678,6 +1693,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post", "new_post") do + "<input type='hidden' name='post[1][active]' value='' />" + "<input id='post_1_active_true' name='post[1][active]' type='radio' value='true' />" + "<label for='post_1_active_true'>true</label>" + "<input checked='checked' id='post_1_active_false' name='post[1][active]' type='radio' value='false' />" + @@ -1696,13 +1712,13 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post", "new_post") do + "<input name='post[tag_ids][]' type='hidden' value='' />" + "<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" + "<label for='post_tag_ids_1'>Tag 1</label>" + "<input id='post_tag_ids_2' name='post[tag_ids][]' type='checkbox' value='2' />" + "<label for='post_tag_ids_2'>Tag 2</label>" + "<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" + - "<label for='post_tag_ids_3'>Tag 3</label>" + - "<input name='post[tag_ids][]' type='hidden' value='' />" + "<label for='post_tag_ids_3'>Tag 3</label>" end assert_dom_equal expected, output_buffer @@ -1720,6 +1736,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post", "new_post") do + "<input name='post[tag_ids][]' type='hidden' value='' />" + "<label for='post_tag_ids_1'>" + "<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" + "Tag 1</label>" + @@ -1728,8 +1745,7 @@ class FormHelperTest < ActionView::TestCase "Tag 2</label>" + "<label for='post_tag_ids_3'>" + "<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" + - "Tag 3</label>" + - "<input name='post[tag_ids][]' type='hidden' value='' />" + "Tag 3</label>" end assert_dom_equal expected, output_buffer @@ -1750,6 +1766,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post_1", "new_post") do + "<input name='post[tag_ids][]' type='hidden' value='' />"+ "<label for='post_tag_ids_1'>" + "<input checked='checked' id='post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" + "Tag 1</label>" + @@ -1759,7 +1776,6 @@ class FormHelperTest < ActionView::TestCase "<label for='post_tag_ids_3'>" + "<input checked='checked' id='post_tag_ids_3' name='post[tag_ids][]' type='checkbox' value='3' />" + "Tag 3</label>" + - "<input name='post[tag_ids][]' type='hidden' value='' />"+ "<input id='post_id' name='post[id]' type='hidden' value='1' />" end @@ -1776,9 +1792,9 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "foo_new_post", "new_post") do + "<input name='post[tag_ids][]' type='hidden' value='' />" + "<input checked='checked' id='foo_post_tag_ids_1' name='post[tag_ids][]' type='checkbox' value='1' />" + - "<label for='foo_post_tag_ids_1'>Tag 1</label>" + - "<input name='post[tag_ids][]' type='hidden' value='' />" + "<label for='foo_post_tag_ids_1'>Tag 1</label>" end assert_dom_equal expected, output_buffer @@ -1794,9 +1810,9 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", "new_post", "new_post") do + "<input name='post[1][tag_ids][]' type='hidden' value='' />" + "<input checked='checked' id='post_1_tag_ids_1' name='post[1][tag_ids][]' type='checkbox' value='1' />" + - "<label for='post_1_tag_ids_1'>Tag 1</label>" + - "<input name='post[1][tag_ids][]' type='hidden' value='' />" + "<label for='post_1_tag_ids_1'>Tag 1</label>" end assert_dom_equal expected, output_buffer @@ -1854,9 +1870,23 @@ class FormHelperTest < ActionView::TestCase expected = whole_form("/posts/44", "edit_post_44", "edit_post", method: "patch") do "<input name='post[title]' type='text' id='post_title' value='And his name will be forty and four.' />" + - "<input name='commit' type='submit' value='Edit post' />" + "<input name='commit' data-disable-with='Edit post' type='submit' value='Edit post' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_lowercase_model_name_default_submit_button_value + form_for(@ticket_type) do |f| + concat f.submit end + expected = + '<form class="new_ticket_type" id="new_ticket_type" action="/ticket_types" accept-charset="UTF-8" method="post">' + + hidden_fields + + '<input type="submit" name="commit" value="Create ticket type" data-disable-with="Create ticket type" />' + + '</form>' + assert_dom_equal expected, output_buffer end @@ -1875,7 +1905,7 @@ class FormHelperTest < ActionView::TestCase "<textarea name='other_name[body]' id='other_name_body'>\nBack to the hill and over it again!</textarea>" + "<input name='other_name[secret]' value='0' type='hidden' />" + "<input name='other_name[secret]' checked='checked' id='other_name_secret' value='1' type='checkbox' />" + - "<input name='commit' value='Create post' type='submit' />" + "<input name='commit' value='Create post' data-disable-with='Create post' type='submit' />" end assert_dom_equal expected, output_buffer @@ -2003,21 +2033,22 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_remote_without_html @post.persisted = false - @post.stubs(:to_key).returns(nil) - form_for(@post, remote: true) do |f| - concat f.text_field(:title) - concat f.text_area(:body) - concat f.check_box(:secret) - end + @post.stub(:to_key, nil) do + form_for(@post, remote: true) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end - expected = whole_form("/posts", "new_post", "new_post", remote: true) do - "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + - "<input name='post[secret]' type='hidden' value='0' />" + - "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" - end + expected = whole_form("/posts", "new_post", "new_post", remote: true) do + "<input name='post[title]' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea>" + + "<input name='post[secret]' type='hidden' value='0' />" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + end - assert_dom_equal expected, output_buffer + assert_dom_equal expected, output_buffer + end end def test_form_for_without_object @@ -2083,7 +2114,7 @@ class FormHelperTest < ActionView::TestCase expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', method: 'patch') do "<div class='field_with_errors'><label for='post_author_name' class='label'>Author name</label></div>" + "<div class='field_with_errors'><input name='post[author_name]' type='text' id='post_author_name' value='' /></div>" + - "<input name='commit' type='submit' value='Create post' />" + "<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />" end assert_dom_equal expected, output_buffer @@ -2101,7 +2132,7 @@ class FormHelperTest < ActionView::TestCase expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', method: 'patch') do "<div class='field_with_errors'><label for='post_author_name' class='label'>Author name</label></div>" + "<div class='field_with_errors'><input name='post[author_name]' type='text' id='post_author_name' value='' /></div>" + - "<input name='commit' type='submit' value='Create post' />" + "<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />" end assert_dom_equal expected, output_buffer @@ -2220,16 +2251,17 @@ class FormHelperTest < ActionView::TestCase def test_submit_with_object_as_new_record_and_locale_strings with_locale :submit do @post.persisted = false - @post.stubs(:to_key).returns(nil) - form_for(@post) do |f| - concat f.submit - end + @post.stub(:to_key, nil) do + form_for(@post) do |f| + concat f.submit + end - expected = whole_form('/posts', 'new_post', 'new_post') do - "<input name='commit' type='submit' value='Create Post' />" - end + expected = whole_form('/posts', 'new_post', 'new_post') do + "<input name='commit' data-disable-with='Create post' type='submit' value='Create post' />" + end - assert_dom_equal expected, output_buffer + assert_dom_equal expected, output_buffer + end end end @@ -2240,7 +2272,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', method: 'patch') do - "<input name='commit' type='submit' value='Confirm Post changes' />" + "<input name='commit' data-disable-with='Confirm post changes' type='submit' value='Confirm post changes' />" end assert_dom_equal expected, output_buffer @@ -2254,7 +2286,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form do - "<input name='commit' class='extra' type='submit' value='Save changes' />" + "<input name='commit' class='extra' data-disable-with='Save changes' type='submit' value='Save changes' />" end assert_dom_equal expected, output_buffer @@ -2268,7 +2300,7 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form('/posts/123', 'edit_another_post', 'edit_another_post', method: 'patch') do - "<input name='commit' type='submit' value='Update your Post' />" + "<input name='commit' data-disable-with='Update your post' type='submit' value='Update your post' />" end assert_dom_equal expected, output_buffer @@ -2290,6 +2322,27 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_deep_nested_fields_for + @comment.save + form_for(:posts) do |f| + f.fields_for('post[]', @post) do |f2| + f2.text_field(:id) + @post.comments.each do |comment| + concat f2.fields_for('comment[]', comment) { |c| + concat c.text_field(:name) + } + end + end + end + + expected = whole_form do + "<input name='posts[post][0][comment][1][name]' type='text' id='posts_post_0_comment_1_name' value='comment #1' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_nested_fields_for_with_nested_collections form_for(@post, as: 'post[]') do |f| concat f.text_field(:title) @@ -2807,11 +2860,12 @@ class FormHelperTest < ActionView::TestCase def test_nested_fields_label_translation_with_more_than_10_records @post.comments = Array.new(11) { |id| Comment.new(id + 1) } - I18n.expects(:t).with('post.comments.body', default: [:"comment.body", ''], scope: "helpers.label").times(11).returns "Write body here" - - form_for(@post) do |f| - f.fields_for(:comments) do |cf| - concat cf.label(:body) + params = 11.times.map { ['post.comments.body', default: [:"comment.body", ''], scope: "helpers.label"] } + assert_called_with(I18n, :t, params, returns: "Write body here") do + form_for(@post) do |f| + f.fields_for(:comments) do |cf| + concat cf.label(:body) + end end end end diff --git a/actionview/test/template/form_options_helper_i18n_test.rb b/actionview/test/template/form_options_helper_i18n_test.rb index 4972ea6511..26ede09a5f 100644 --- a/actionview/test/template/form_options_helper_i18n_test.rb +++ b/actionview/test/template/form_options_helper_i18n_test.rb @@ -14,8 +14,9 @@ class FormOptionsHelperI18nTests < ActionView::TestCase end def test_select_with_prompt_true_translates_prompt_message - I18n.expects(:translate).with('helpers.select.prompt', { :default => 'Please select' }) - select('post', 'category', [], :prompt => true) + assert_called_with(I18n, :translate, ['helpers.select.prompt', { :default => 'Please select' }]) do + select('post', 'category', [], :prompt => true) + end end def test_select_with_translated_prompt diff --git a/actionview/test/template/form_options_helper_test.rb b/actionview/test/template/form_options_helper_test.rb index d25fa3706f..6b97cec34c 100644 --- a/actionview/test/template/form_options_helper_test.rb +++ b/actionview/test/template/form_options_helper_test.rb @@ -17,13 +17,37 @@ class FormOptionsHelperTest < ActionView::TestCase Album = Struct.new('Album', :id, :title, :genre) end - def setup - @fake_timezones = %w(A B C D E).map do |id| - tz = stub(:name => id, :to_s => id) - ActiveSupport::TimeZone.stubs(:[]).with(id).returns(tz) - tz + module FakeZones + FakeZone = Struct.new(:name) do + def to_s; name; end end - ActiveSupport::TimeZone.stubs(:all).returns(@fake_timezones) + + module ClassMethods + def [](id); fake_zones ? fake_zones[id] : super; end + def all; fake_zones ? fake_zones.values : super; end + def dummy; :test; end + end + + def self.prepended(base) + class << base + mattr_accessor(:fake_zones) + prepend ClassMethods + end + end + end + + ActiveSupport::TimeZone.prepend FakeZones + + setup do + ActiveSupport::TimeZone.fake_zones = %w(A B C D E).map do |id| + [ id, FakeZones::FakeZone.new(id) ] + end.to_h + + @fake_timezones = ActiveSupport::TimeZone.all + end + + teardown do + ActiveSupport::TimeZone.fake_zones = nil end def test_collection_options @@ -645,6 +669,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_include_blank_false_and_required + @post = Post.new + @post.category = "<mus>" + e = assert_raises(ArgumentError) { select("post", "category", %w( abe <mus> hest), { include_blank: false }, required: 'required') } + assert_match(/include_blank cannot be false for a required field./, e.message) + end + def test_select_with_blank_as_string @post = Post.new @post.category = "<mus>" @@ -1156,8 +1187,8 @@ class FormOptionsHelperTest < ActionView::TestCase def test_time_zone_select_with_priority_zones_as_regexp @firm = Firm.new("D") - @fake_timezones.each_with_index do |tz, i| - tz.stubs(:=~).returns(i.zero? || i == 3) + @fake_timezones.each do |tz| + def tz.=~(re); %(A D).include?(name) end end html = time_zone_select("firm", "time_zone", /A|D/) @@ -1172,15 +1203,16 @@ class FormOptionsHelperTest < ActionView::TestCase html end - def test_time_zone_select_with_priority_zones_as_regexp_using_grep_finds_no_zones + def test_time_zone_select_with_priority_zones_is_not_implemented_with_grep @firm = Firm.new("D") - priority_zones = /A|D/ + # `time_zone_select` can't be written with `grep` because Active Support + # time zones don't support implicit string coercion with `to_str`. @fake_timezones.each do |tz| - priority_zones.stubs(:===).with(tz).raises(Exception) + def tz.===(zone); raise Exception; end end - html = time_zone_select("firm", "time_zone", priority_zones) + html = time_zone_select("firm", "time_zone", /A|D/) assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" + "<option value=\"\" disabled=\"disabled\">-------------</option>\n" + "<option value=\"A\">A</option>\n" + diff --git a/actionview/test/template/form_tag_helper_test.rb b/actionview/test/template/form_tag_helper_test.rb index cad1c82309..359ecbc637 100644 --- a/actionview/test/template/form_tag_helper_test.rb +++ b/actionview/test/template/form_tag_helper_test.rb @@ -64,6 +64,18 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal expected, actual end + def test_check_box_tag_disabled + actual = check_box_tag "admin","1", false, disabled: true + expected = %(<input id="admin" disabled="disabled" name="admin" type="checkbox" value="1" />) + assert_dom_equal expected, actual + end + + def test_check_box_tag_default_checked + actual = check_box_tag "admin","1", true + expected = %(<input id="admin" checked="checked" name="admin" type="checkbox" value="1" />) + assert_dom_equal expected, actual + end + def test_check_box_tag_id_sanitized label_elem = root_elem(check_box_tag("project[2][admin]")) assert_match VALID_HTML_ID, label_elem['id'] @@ -351,12 +363,18 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal expected, actual end - def test_text_field_disabled + def test_text_field_tag_disabled actual = text_field_tag "title", "Hello!", disabled: true expected = %(<input id="title" name="title" disabled="disabled" type="text" value="Hello!" />) assert_dom_equal expected, actual end + def test_text_field_tag_with_placeholder_option + actual = text_field_tag "title", "Hello!", placeholder: 'Enter search term...' + expected = %(<input id="title" name="title" placeholder="Enter search term..." type="text" value="Hello!" />) + assert_dom_equal expected, actual + end + def test_text_field_tag_with_multiple_options actual = text_field_tag "title", "Hello!", :size => 70, :maxlength => 80 expected = %(<input id="title" name="title" size="70" maxlength="80" type="text" value="Hello!" />) @@ -433,6 +451,44 @@ class FormTagHelperTest < ActionView::TestCase ) end + def test_empty_submit_tag + assert_dom_equal( + %(<input data-disable-with="Save" name='commit' type="submit" value="Save" />), + submit_tag("Save") + ) + end + + def test_empty_submit_tag_with_opt_out + ActionView::Base.automatically_disable_submit_tag = false + assert_dom_equal( + %(<input name='commit' type="submit" value="Save" />), + submit_tag("Save") + ) + ensure + ActionView::Base.automatically_disable_submit_tag = true + end + + def test_submit_tag_having_data_disable_with_string + assert_dom_equal( + %(<input data-disable-with="Processing..." data-confirm="Are you sure?" name='commit' type="submit" value="Save" />), + submit_tag("Save", { "data-disable-with" => "Processing...", "data-confirm" => "Are you sure?" }) + ) + end + + def test_submit_tag_having_data_disable_with_boolean + assert_dom_equal( + %(<input data-confirm="Are you sure?" name='commit' type="submit" value="Save" />), + submit_tag("Save", { "data-disable-with" => false, "data-confirm" => "Are you sure?" }) + ) + end + + def test_submit_tag_having_data_hash_disable_with_boolean + assert_dom_equal( + %(<input data-confirm="Are you sure?" name='commit' type="submit" value="Save" />), + submit_tag("Save", { :data => { :confirm => "Are you sure?", :disable_with => false } }) + ) + end + def test_submit_tag_with_no_onclick_options assert_dom_equal( %(<input name='commit' data-disable-with="Saving..." type="submit" value="Save" />), @@ -442,11 +498,26 @@ class FormTagHelperTest < ActionView::TestCase def test_submit_tag_with_confirmation assert_dom_equal( - %(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />), + %(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" data-disable-with="Save" />), submit_tag("Save", :data => { :confirm => "Are you sure?" }) ) end + def test_submit_tag_doesnt_have_data_disable_with_twice + assert_equal( + %(<input type="submit" name="commit" value="Save" data-confirm="Are you sure?" data-disable-with="Processing..." />), + submit_tag("Save", { "data-disable-with" => "Processing...", "data-confirm" => "Are you sure?" }) + ) + end + + def test_submit_tag_with_symbol_value + assert_dom_equal( + %(<input data-disable-with="Save" name='commit' type="submit" value="Save" />), + submit_tag(:Save) + ) + end + + def test_button_tag assert_dom_equal( %(<button name="button" type="submit">Button</button>), @@ -510,6 +581,13 @@ class FormTagHelperTest < ActionView::TestCase ) end + def test_button_tag_with_data_disable_with_option + assert_dom_equal( + %(<button name="button" type="submit" data-disable-with="Please wait...">Checkout</button>), + button_tag("Checkout", data: { disable_with: "Please wait..." }) + ) + end + def test_image_submit_tag_with_confirmation assert_dom_equal( %(<input alt="Save" type="image" src="/images/save.gif" data-confirm="Are you sure?" />), diff --git a/actionview/test/template/log_subscriber_test.rb b/actionview/test/template/log_subscriber_test.rb index 7f4c84929f..4776c18b0b 100644 --- a/actionview/test/template/log_subscriber_test.rb +++ b/actionview/test/template/log_subscriber_test.rb @@ -12,13 +12,18 @@ class AVLogSubscriberTest < ActiveSupport::TestCase lookup_context = ActionView::LookupContext.new(view_paths, {}, ["test"]) renderer = ActionView::Renderer.new(lookup_context) @view = ActionView::Base.new(renderer, {}) - Rails.stubs(:root).returns(File.expand_path(FIXTURE_LOAD_PATH)) ActionView::LogSubscriber.attach_to :action_view + unless Rails.respond_to?(:root) + @defined_root = true + def Rails.root; :defined_root; end # Minitest `stub` expects the method to be defined. + end end def teardown super ActiveSupport::LogSubscriber.log_subscribers.clear + # We need to undef `root`, RenderTestCases don't want this to be defined + Rails.instance_eval { undef :root } if @defined_root end def set_logger(logger) @@ -26,66 +31,82 @@ class AVLogSubscriberTest < ActiveSupport::TestCase end def test_render_file_template - @view.render(:file => "test/hello_world") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render(:file => "test/hello_world") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered test\/hello_world\.erb/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered test\/hello_world\.erb/, @logger.logged(:info).last) + end end def test_render_text_template - @view.render(:text => "TEXT") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render(:text => "TEXT") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered text template/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered text template/, @logger.logged(:info).last) + end end def test_render_inline_template - @view.render(:inline => "<%= 'TEXT' %>") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render(:inline => "<%= 'TEXT' %>") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered inline template/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered inline template/, @logger.logged(:info).last) + end end def test_render_partial_template - @view.render(:partial => "test/customer") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render(:partial => "test/customer") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered test\/_customer.erb/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered test\/_customer.erb/, @logger.logged(:info).last) + end end def test_render_partial_with_implicit_path - @view.render(Customer.new("david"), :greeting => "hi") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render(Customer.new("david"), :greeting => "hi") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered customers\/_customer\.html\.erb/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered customers\/_customer\.html\.erb/, @logger.logged(:info).last) + end end def test_render_collection_template - @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ]) - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), Customer.new("mary") ]) + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered test\/_customer.erb/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered test\/_customer.erb/, @logger.logged(:info).last) + end end def test_render_collection_with_implicit_path - @view.render([ Customer.new("david"), Customer.new("mary") ], :greeting => "hi") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render([ Customer.new("david"), Customer.new("mary") ], :greeting => "hi") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered customers\/_customer\.html\.erb/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered customers\/_customer\.html\.erb/, @logger.logged(:info).last) + end end def test_render_collection_template_without_path - @view.render([ GoodCustomer.new("david"), Customer.new("mary") ], :greeting => "hi") - wait + Rails.stub(:root, File.expand_path(FIXTURE_LOAD_PATH)) do + @view.render([ GoodCustomer.new("david"), Customer.new("mary") ], :greeting => "hi") + wait - assert_equal 1, @logger.logged(:info).size - assert_match(/Rendered collection/, @logger.logged(:info).last) + assert_equal 1, @logger.logged(:info).size + assert_match(/Rendered collection/, @logger.logged(:info).last) + end end end diff --git a/actionview/test/template/lookup_context_test.rb b/actionview/test/template/lookup_context_test.rb index 4f7823045e..2e3a3f9bae 100644 --- a/actionview/test/template/lookup_context_test.rb +++ b/actionview/test/template/lookup_context_test.rb @@ -27,7 +27,7 @@ class LookupContextTest < ActiveSupport::TestCase end test "normalizes details on initialization" do - assert_equal Mime::SET, @lookup_context.formats + assert_equal Mime::SET.to_a, @lookup_context.formats assert_equal :en, @lookup_context.locale end @@ -48,7 +48,7 @@ class LookupContextTest < ActiveSupport::TestCase test "handles */* formats" do @lookup_context.formats = ["*/*"] - assert_equal Mime::SET, @lookup_context.formats + assert_equal Mime::SET.to_a, @lookup_context.formats end test "handles explicitly defined */* formats fallback to :js" do @@ -108,10 +108,11 @@ class LookupContextTest < ActiveSupport::TestCase end test "found templates respects given formats if one cannot be found from template or handler" do - ActionView::Template::Handlers::Builder.expects(:default_format).returns(nil) - @lookup_context.formats = [:text] - template = @lookup_context.find("hello", %w(test)) - assert_equal [:text], template.formats + assert_called(ActionView::Template::Handlers::Builder, :default_format, returns: nil) do + @lookup_context.formats = [:text] + template = @lookup_context.find("hello", %w(test)) + assert_equal [:text], template.formats + end end test "adds fallbacks to view paths when required" do @@ -210,45 +211,50 @@ end class LookupContextWithFalseCaching < ActiveSupport::TestCase def setup @resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)]) - ActionView::Resolver.stubs(:caching?).returns(false) @lookup_context = ActionView::LookupContext.new(@resolver, {}) end test "templates are always found in the resolver but timestamp is checked before being compiled" do - template = @lookup_context.find("foo", %w(test), true) - assert_equal "Foo", template.source - - # Now we are going to change the template, but it won't change the returned template - # since the timestamp is the same. - @resolver.hash["test/_foo.erb"][0] = "Bar" - template = @lookup_context.find("foo", %w(test), true) - assert_equal "Foo", template.source - - # Now update the timestamp. - @resolver.hash["test/_foo.erb"][1] = Time.now.utc - template = @lookup_context.find("foo", %w(test), true) - assert_equal "Bar", template.source + ActionView::Resolver.stub(:caching?, false) do + template = @lookup_context.find("foo", %w(test), true) + assert_equal "Foo", template.source + + # Now we are going to change the template, but it won't change the returned template + # since the timestamp is the same. + @resolver.hash["test/_foo.erb"][0] = "Bar" + template = @lookup_context.find("foo", %w(test), true) + assert_equal "Foo", template.source + + # Now update the timestamp. + @resolver.hash["test/_foo.erb"][1] = Time.now.utc + template = @lookup_context.find("foo", %w(test), true) + assert_equal "Bar", template.source + end end test "if no template was found in the second lookup, with no cache, raise error" do - template = @lookup_context.find("foo", %w(test), true) - assert_equal "Foo", template.source + ActionView::Resolver.stub(:caching?, false) do + template = @lookup_context.find("foo", %w(test), true) + assert_equal "Foo", template.source - @resolver.hash.clear - assert_raise ActionView::MissingTemplate do - @lookup_context.find("foo", %w(test), true) + @resolver.hash.clear + assert_raise ActionView::MissingTemplate do + @lookup_context.find("foo", %w(test), true) + end end end test "if no template was cached in the first lookup, retrieval should work in the second call" do - @resolver.hash.clear - assert_raise ActionView::MissingTemplate do - @lookup_context.find("foo", %w(test), true) - end + ActionView::Resolver.stub(:caching?, false) do + @resolver.hash.clear + assert_raise ActionView::MissingTemplate do + @lookup_context.find("foo", %w(test), true) + end - @resolver.hash["test/_foo.erb"] = ["Foo", Time.utc(2000)] - template = @lookup_context.find("foo", %w(test), true) - assert_equal "Foo", template.source + @resolver.hash["test/_foo.erb"] = ["Foo", Time.utc(2000)] + template = @lookup_context.find("foo", %w(test), true) + assert_equal "Foo", template.source + end end end diff --git a/actionview/test/template/number_helper_test.rb b/actionview/test/template/number_helper_test.rb index b70b750869..ace3e950b8 100644 --- a/actionview/test/template/number_helper_test.rb +++ b/actionview/test/template/number_helper_test.rb @@ -21,6 +21,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal "<b>1,234,567,890.50</b> $", number_to_currency("1234567890.50", format: "<b>%n</b> %u") assert_equal "<b>1,234,567,890.50</b> $", number_to_currency("-1234567890.50", negative_format: "<b>%n</b> %u") assert_equal "<b>1,234,567,890.50</b> $", number_to_currency("-1234567890.50", 'negative_format' => "<b>%n</b> %u") + assert_equal '₹ 12,30,000.00', number_to_currency(1230000, delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/, unit: '₹', format: "%u %n") end def test_number_to_percentage diff --git a/actionview/test/template/record_tag_helper_test.rb b/actionview/test/template/record_tag_helper_test.rb index 4b7b653916..bfc5d04bed 100644 --- a/actionview/test/template/record_tag_helper_test.rb +++ b/actionview/test/template/record_tag_helper_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' class RecordTagPost extend ActiveModel::Naming - include ActiveModel::Conversion + attr_accessor :id, :body def initialize @@ -14,7 +14,6 @@ class RecordTagPost end class RecordTagHelperTest < ActionView::TestCase - include RenderERBUtils tests ActionView::Helpers::RecordTagHelper diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index 27bbb9b6c1..b63c315a33 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -7,7 +7,14 @@ end module RenderTestCases def setup_view(paths) @assigns = { :secret => 'in the sauce' } - @view = ActionView::Base.new(paths, @assigns) + @view = Class.new(ActionView::Base) do + def view_cache_dependencies; end + + def fragment_cache_key(key) + ActiveSupport::Cache.expand_cache_key(key, :views) + end + end.new(paths, @assigns) + @controller_view = TestController.new.view_context # Reload and register danish language for testing @@ -64,7 +71,7 @@ module RenderTestCases e = assert_raise ActionView::Template::Error do @view.render(:template => "with_format", :formats => [:json]) end - assert_includes(e.message, "Missing partial /_missing with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:raw, :erb, :builder, :ruby]}.") + assert_includes(e.message, "Missing partial /_missing with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby]}.") end def test_render_file_with_locale @@ -244,6 +251,8 @@ module RenderTestCases def test_render_object assert_equal "Hello: david", @view.render(:partial => "test/customer", :object => Customer.new("david")) + assert_equal "FalseClass", @view.render(:partial => "test/klass", :object => false) + assert_equal "NilClass", @view.render(:partial => "test/klass", :object => nil) end def test_render_object_with_array @@ -349,8 +358,8 @@ module RenderTestCases exception = assert_raises ActionView::Template::Error do @controller_view.render("partial_name_local_variable") end - assert_instance_of NameError, exception.original_exception - assert_equal :partial_name_local_variable, exception.original_exception.name + assert_instance_of NameError, exception.cause + assert_equal :partial_name_local_variable, exception.cause.name end # TODO: The reason for this test is unclear, improve documentation @@ -458,6 +467,11 @@ module RenderTestCases @view.render(:file => "test/hello_world", :layout => "layouts/yield_with_render_partial_inside") end + def test_render_partial_with_html_only_extension + assert_equal %(<h1>partial html</h1>\nHello world!\n), + @view.render(:file => "test/hello_world", :layout => "layouts/render_partial_html") + end + def test_render_layout_with_block_and_yield assert_equal %(Content from block!\n), @view.render(:layout => "layouts/yield_only") { "Content from block!" } @@ -587,14 +601,14 @@ class LazyViewRenderTest < ActiveSupport::TestCase def test_render_utf8_template_with_incompatible_external_encoding with_external_encoding Encoding::SHIFT_JIS do e = assert_raises(ActionView::Template::Error) { @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") } - assert_match 'Your template was not saved as valid Shift_JIS', e.original_exception.message + assert_match 'Your template was not saved as valid Shift_JIS', e.cause.message end end def test_render_utf8_template_with_partial_with_incompatible_encoding with_external_encoding Encoding::SHIFT_JIS do e = assert_raises(ActionView::Template::Error) { @view.render(:file => "test/utf8_magic_with_bare_partial", :formats => [:html], :layouts => "layouts/yield") } - assert_match 'Your template was not saved as valid Shift_JIS', e.original_exception.message + assert_match 'Your template was not saved as valid Shift_JIS', e.cause.message end end @@ -616,7 +630,7 @@ class CachedCollectionViewRenderTest < CachedViewRenderTest test "with custom key" do customer = Customer.new("david") - key = ActionController::Base.new.fragment_cache_key([customer, 'key']) + key = cache_key([customer, 'key'], "test/_customer") ActionView::PartialRenderer.collection_cache.write(key, 'Hello') @@ -624,9 +638,19 @@ class CachedCollectionViewRenderTest < CachedViewRenderTest @view.render(partial: "test/customer", collection: [customer], cache: ->(item) { [item, 'key'] }) end + test "with caching with custom key and rendering with different key" do + customer = Customer.new("david") + key = cache_key([customer, 'key'], "test/_customer") + + ActionView::PartialRenderer.collection_cache.write(key, 'Hello') + + assert_equal "Hello: david", + @view.render(partial: "test/customer", collection: [customer], cache: ->(item) { [item, 'another_key'] }) + end + test "automatic caching with inferred cache name" do customer = CachedCustomer.new("david") - key = ActionController::Base.new.fragment_cache_key(customer) + key = cache_key(customer, "test/_cached_customer") ActionView::PartialRenderer.collection_cache.write(key, 'Cached') @@ -636,11 +660,17 @@ class CachedCollectionViewRenderTest < CachedViewRenderTest test "automatic caching with as name" do customer = CachedCustomer.new("david") - key = ActionController::Base.new.fragment_cache_key(customer) + key = cache_key(customer, "test/_cached_customer_as") ActionView::PartialRenderer.collection_cache.write(key, 'Cached') assert_equal "Cached", @view.render(partial: "test/cached_customer_as", collection: [customer], as: :buyer) end + + private + def cache_key(names, virtual_path) + digest = ActionView::Digestor.digest name: virtual_path, finder: @view.lookup_context, dependencies: [] + @view.fragment_cache_key([ *Array(names), digest ]) + end end diff --git a/actionview/test/template/template_error_test.rb b/actionview/test/template/template_error_test.rb index 3971ec809c..54c1d53b60 100644 --- a/actionview/test/template/template_error_test.rb +++ b/actionview/test/template/template_error_test.rb @@ -2,19 +2,34 @@ require "abstract_unit" class TemplateErrorTest < ActiveSupport::TestCase def test_provides_original_message - error = ActionView::Template::Error.new("test", Exception.new("original")) + error = begin + raise Exception.new("original") + rescue Exception + raise ActionView::Template::Error.new("test") rescue $! + end + assert_equal "original", error.message end def test_provides_original_backtrace - original_exception = Exception.new - original_exception.set_backtrace(%W[ foo bar baz ]) - error = ActionView::Template::Error.new("test", original_exception) + error = begin + original_exception = Exception.new + original_exception.set_backtrace(%W[ foo bar baz ]) + raise original_exception + rescue Exception + raise ActionView::Template::Error.new("test") rescue $! + end + assert_equal %W[ foo bar baz ], error.backtrace end def test_provides_useful_inspect - error = ActionView::Template::Error.new("test", Exception.new("original")) + error = begin + raise Exception.new("original") + rescue Exception + raise ActionView::Template::Error.new("test") rescue $! + end + assert_equal "#<ActionView::Template::Error: original>", error.inspect end end diff --git a/actionview/test/template/template_test.rb b/actionview/test/template/template_test.rb index aae6a9aa09..921011b073 100644 --- a/actionview/test/template/template_test.rb +++ b/actionview/test/template/template_test.rb @@ -118,15 +118,17 @@ class TestERBTemplate < ActiveSupport::TestCase def test_refresh_with_templates @template = new_template("Hello", :virtual_path => "test/foo/bar") @template.locals = [:key] - @context.lookup_context.expects(:find_template).with("bar", %w(test/foo), false, [:key]).returns("template") - assert_equal "template", @template.refresh(@context) + assert_called_with(@context.lookup_context, :find_template,["bar", %w(test/foo), false, [:key]], returns: "template") do + assert_equal "template", @template.refresh(@context) + end end def test_refresh_with_partials @template = new_template("Hello", :virtual_path => "test/_foo") @template.locals = [:key] - @context.lookup_context.expects(:find_template).with("foo", %w(test), true, [:key]).returns("partial") - assert_equal "partial", @template.refresh(@context) + assert_called_with(@context.lookup_context, :find_template,[ "foo", %w(test), true, [:key]], returns: "partial") do + assert_equal "partial", @template.refresh(@context) + end end def test_refresh_raises_an_error_without_virtual_path @@ -190,6 +192,38 @@ class TestERBTemplate < ActiveSupport::TestCase assert_match(/\xFC/, e.message) end + def test_not_eligible_for_collection_caching_without_cache_call + [ + "<%= 'Hello' %>", + "<% cache_customer = 42 %>", + "<% cache customer.name do %><% end %>", + "<% my_cache customer do %><% end %>" + ].each do |body| + template = new_template(body, virtual_path: "test/foo/_customer") + assert_not template.eligible_for_collection_caching?, "Template #{body.inspect} should not be eligible for collection caching" + end + end + + def test_eligible_for_collection_caching_with_cache_call_or_explicit + [ + "<% cache customer do %><% end %>", + "<% cache(customer) do %><% end %>", + "<% cache( customer) do %><% end %>", + "<% cache( customer ) do %><% end %>", + "<%cache customer do %><% end %>", + "<% cache customer do %><% end %>", + " <% cache customer do %>\n<% end %>\n", + "<%# comment %><% cache customer do %><% end %>", + "<%# comment %>\n<% cache customer do %><% end %>", + "<%# comment\n line 2\n line 3 %>\n<% cache customer do %><% end %>", + "<%# comment 1 %>\n<%# comment 2 %>\n<% cache customer do %><% end %>", + "<%# comment 1 %>\n<%# Template Collection: customer %>\n<% my_cache customer do %><% end %>" + ].each do |body| + template = new_template(body, virtual_path: "test/foo/_customer") + assert template.eligible_for_collection_caching?, "Template #{body.inspect} should be eligible for collection caching" + end + end + def with_external_encoding(encoding) old = Encoding.default_external Encoding::Converter.new old, encoding if old != encoding diff --git a/actionview/test/template/test_case_test.rb b/actionview/test/template/test_case_test.rb index c6cc47fb4f..d69d5819b6 100644 --- a/actionview/test/template/test_case_test.rb +++ b/actionview/test/template/test_case_test.rb @@ -20,6 +20,7 @@ module ActionView class TestCase helper ASharedTestHelper + DeveloperStruct = Struct.new(:name) module SharedTests def self.included(test_case) @@ -41,6 +42,10 @@ module ActionView assert_same view, view end + test "exposes params" do + assert params.is_a? ActionController::Parameters + end + test "exposes view as _view for backwards compatibility" do assert_same _view, view end @@ -50,7 +55,7 @@ module ActionView end test "works without testing a helper module" do - assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) + assert_equal 'Eloy', render('developers/developer', :developer => DeveloperStruct.new('Eloy')) end test "can render a layout with block" do @@ -69,13 +74,15 @@ module ActionView end test "delegates notice to request.flash[:notice]" do - view.request.flash.expects(:[]).with(:notice) - view.notice + assert_called_with(view.request.flash, :[], [:notice]) do + view.notice + end end test "delegates alert to request.flash[:alert]" do - view.request.flash.expects(:[]).with(:alert) - view.alert + assert_called_with(view.request.flash, :[], [:alert]) do + view.alert + end end test "uses controller lookup context" do @@ -119,7 +126,7 @@ module ActionView test "helper class that is being tested is always included in view instance" do @controller.controller_path = 'test' - @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] + @customers = [DeveloperStruct.new('Eloy'), DeveloperStruct.new('Manfred')] assert_match(/Hello: EloyHello: Manfred/, render(:partial => 'test/from_helper')) end end @@ -209,7 +216,7 @@ module ActionView end test "is able to use routes" do - controller.request.assign_parameters(@routes, 'foo', 'index') + controller.request.assign_parameters(@routes, 'foo', 'index', {}, '/foo', []) assert_equal '/foo', url_for assert_equal '/bar', url_for(:controller => 'bar') end @@ -255,15 +262,15 @@ module ActionView end test "is able to render partials with local variables" do - assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy')) + assert_equal 'Eloy', render('developers/developer', :developer => DeveloperStruct.new('Eloy')) assert_equal 'Eloy', render(:partial => 'developers/developer', - :locals => { :developer => stub(:name => 'Eloy') }) + :locals => { :developer => DeveloperStruct.new('Eloy') }) end test "is able to render partials from templates and also use instance variables" do @controller.controller_path = "test" - @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] + @customers = [DeveloperStruct.new('Eloy'), DeveloperStruct.new('Manfred')] assert_match(/Hello: EloyHello: Manfred/, render(:file => 'test/list')) end @@ -272,7 +279,7 @@ module ActionView view - @customers = [stub(:name => 'Eloy'), stub(:name => 'Manfred')] + @customers = [DeveloperStruct.new('Eloy'), DeveloperStruct.new('Manfred')] assert_match(/Hello: EloyHello: Manfred/, render(:file => 'test/list')) end @@ -306,64 +313,6 @@ module ActionView end end - class RenderTemplateTest < ActionView::TestCase - test "supports specifying templates with a Regexp" do - controller.controller_path = "fun" - render(:template => "fun/games/hello_world") - assert_template %r{\Afun/games/hello_world\Z} - end - - test "supports specifying partials" do - controller.controller_path = "test" - render(:template => "test/calling_partial_with_layout") - assert_template :partial => "_partial_for_use_in_layout" - end - - test "supports specifying locals (passing)" do - controller.controller_path = "test" - render(:template => "test/calling_partial_with_layout") - assert_template :partial => "_partial_for_use_in_layout", :locals => { :name => "David" } - end - - test "supports specifying locals (failing)" do - controller.controller_path = "test" - render(:template => "test/calling_partial_with_layout") - e = assert_raise ActiveSupport::TestCase::Assertion do - assert_template :partial => "_partial_for_use_in_layout", :locals => { :name => "Somebody Else" } - end - assert_match(/Somebody Else.*David/m, e.message) - end - - test 'supports different locals on the same partial' do - controller.controller_path = "test" - render(:template => "test/render_two_partials") - assert_template partial: '_partial', locals: { 'first' => '1' } - assert_template partial: '_partial', locals: { 'second' => '2' } - end - - test 'raises descriptive error message when template was not rendered' do - controller.controller_path = "test" - render(template: "test/hello_world_with_partial") - e = assert_raise ActiveSupport::TestCase::Assertion do - assert_template partial: 'i_was_never_rendered', locals: { 'did_not' => 'happen' } - end - assert_match "i_was_never_rendered to be rendered but it was not.", e.message - assert_match 'Expected ["/test/partial"] to include "i_was_never_rendered"', e.message - end - - test 'specifying locals works when the partial is inside a directory with underline prefix' do - controller.controller_path = "test" - render(template: 'test/render_partial_inside_directory') - assert_template partial: 'test/_directory/_partial_with_locales', locals: { 'name' => 'Jane' } - end - - test 'specifying locals works when the partial is inside a directory without underline prefix' do - controller.controller_path = "test" - render(template: 'test/render_partial_inside_directory') - assert_template partial: 'test/_directory/partial_with_locales', locals: { 'name' => 'Jane' } - end - end - module AHelperWithInitialize def initialize(*) super diff --git a/actionview/test/template/test_test.rb b/actionview/test/template/test_test.rb index 88bac85039..e1ff639979 100644 --- a/actionview/test/template/test_test.rb +++ b/actionview/test/template/test_test.rb @@ -41,12 +41,12 @@ class PeopleHelperTest < ActionView::TestCase extend ActiveModel::Naming def to_model; self; end def persisted?; true; end - def self.name; 'Mocha::Mock'; end + def self.name; 'Minitest::Mock'; end }.new "David" the_model = nil extend Module.new { - define_method(:mocha_mock_path) { |model, *args| + define_method(:minitest_mock_path) { |model, *args| the_model = model "/people/1" } diff --git a/actionview/test/template/text_helper_test.rb b/actionview/test/template/text_helper_test.rb index f1b84c4786..fb98ac6330 100644 --- a/actionview/test/template/text_helper_test.rb +++ b/actionview/test/template/text_helper_test.rb @@ -366,6 +366,10 @@ class TextHelperTest < ActionView::TestCase assert_equal options, passed_options end + def test_word_wrap_with_custom_break_sequence + assert_equal("1234567890\r\n1234567890\r\n1234567890", word_wrap("1234567890 " * 3, line_width: 2, break_sequence: "\r\n")) + end + def test_pluralization assert_equal("1 count", pluralize(1, "count")) assert_equal("2 counts", pluralize(2, "count")) @@ -375,14 +379,38 @@ class TextHelperTest < ActionView::TestCase assert_equal("1.25 counts", pluralize('1.25', "count")) assert_equal("1.0 count", pluralize('1.0', "count")) assert_equal("1.00 count", pluralize('1.00', "count")) - assert_equal("2 counters", pluralize(2, "count", "counters")) - assert_equal("0 counters", pluralize(nil, "count", "counters")) + assert_equal("2 counters", pluralize(2, "count", plural: "counters")) + assert_equal("0 counters", pluralize(nil, "count", plural: "counters")) assert_equal("2 people", pluralize(2, "person")) assert_equal("10 buffaloes", pluralize(10, "buffalo")) assert_equal("1 berry", pluralize(1, "berry")) assert_equal("12 berries", pluralize(12, "berry")) end + def test_localized_pluralization + old_locale = I18n.locale + + begin + I18n.locale = :de + + ActiveSupport::Inflector.inflections(:de) do |inflect| + inflect.irregular 'region', 'regionen' + end + + assert_equal("1 region", pluralize(1, "region")) + assert_equal("2 regionen", pluralize(2, "region")) + assert_equal("2 regions", pluralize(2, "region", locale: :en)) + ensure + I18n.locale = old_locale + end + end + + def test_deprecated_plural_as_positional_argument + assert_deprecated do + pluralize(2, 'count', 'counters') + end + end + def test_cycle_class value = Cycle.new("one", 2, "3") assert_equal("one", value.to_s) diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb index 5dc281adb2..38b9284767 100644 --- a/actionview/test/template/translation_helper_test.rb +++ b/actionview/test/template/translation_helper_test.rb @@ -42,14 +42,26 @@ class TranslationHelperTest < ActiveSupport::TestCase end def test_delegates_setting_to_i18n - I18n.expects(:translate).with(:foo, :locale => 'en', :raise => true).returns("") - translate :foo, :locale => 'en' + assert_called_with(I18n, :translate, [:foo, :locale => 'en', :raise => true], returns: "") do + translate :foo, :locale => 'en' + end end def test_delegates_localize_to_i18n @time = Time.utc(2008, 7, 8, 12, 18, 38) - I18n.expects(:localize).with(@time) - localize @time + assert_called_with(I18n, :localize, [@time]) do + localize @time + end + end + + def test_returns_missing_translation_message_without_span_wrap + old_value = ActionView::Base.debug_missing_translation + ActionView::Base.debug_missing_translation = false + + expected = 'translation missing: en.translations.missing' + assert_equal expected, translate(:"translations.missing") + ensure + ActionView::Base.debug_missing_translation = old_value end def test_returns_missing_translation_message_wrapped_into_span @@ -58,6 +70,20 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal true, translate(:"translations.missing").html_safe? end + def test_returns_missing_translation_message_with_unescaped_interpolation + expected = '<span class="translation_missing" title="translation missing: en.translations.missing, name: Kir, year: 2015, vulnerable: &quot; onclick=&quot;alert()&quot;">Missing</span>' + assert_equal expected, translate(:"translations.missing", name: "Kir", year: "2015", vulnerable: %{" onclick="alert()"}) + assert translate(:"translations.missing").html_safe? + end + + def test_returns_missing_translation_message_does_filters_out_i18n_options + expected = '<span class="translation_missing" title="translation missing: en.translations.missing, year: 2015">Missing</span>' + assert_equal expected, translate(:"translations.missing", year: '2015', default: []) + + expected = '<span class="translation_missing" title="translation missing: en.scoped.translations.missing, year: 2015">Missing</span>' + assert_equal expected, translate(:"translations.missing", year: '2015', scope: %i(scoped)) + end + def test_raises_missing_translation_message_with_raise_config_option ActionView::Base.raise_on_missing_translations = true @@ -125,8 +151,9 @@ class TranslationHelperTest < ActiveSupport::TestCase end def test_translate_escapes_interpolations_in_translations_with_a_html_suffix + word_struct = Struct.new(:to_s) assert_equal '<a>Hello <World></a>', translate(:'translations.interpolated_html', :word => '<World>') - assert_equal '<a>Hello <World></a>', translate(:'translations.interpolated_html', :word => stub(:to_s => "<World>")) + assert_equal '<a>Hello <World></a>', translate(:'translations.interpolated_html', :word => word_struct.new("<World>")) end def test_translate_with_html_count diff --git a/actionview/test/template/url_helper_test.rb b/actionview/test/template/url_helper_test.rb index 0e35c67516..89cabb8f6b 100644 --- a/actionview/test/template/url_helper_test.rb +++ b/actionview/test/template/url_helper_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'minitest/mock' class UrlHelperTest < ActiveSupport::TestCase @@ -39,6 +38,10 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal "/?a=b&c=d", url_for(hash_for(a: :b, c: :d)) end + def test_url_for_does_not_include_empty_hashes + assert_equal "/", url_for(hash_for(a: {})) + end + def test_url_for_with_back referer = 'http://www.example.com/referer' @controller = Struct.new(:request).new(Struct.new(:env).new("HTTP_REFERER" => referer)) @@ -51,6 +54,23 @@ class UrlHelperTest < ActiveSupport::TestCase assert_equal 'javascript:history.back()', url_for(:back) end + def test_url_for_with_back_and_no_controller + @controller = nil + assert_equal 'javascript:history.back()', url_for(:back) + end + + def test_url_for_with_back_and_javascript_referer + referer = 'javascript:alert(document.cookie)' + @controller = Struct.new(:request).new(Struct.new(:env).new("HTTP_REFERER" => referer)) + assert_equal 'javascript:history.back()', url_for(:back) + end + + def test_url_for_with_invalid_referer + referer = 'THIS IS NOT A URL' + @controller = Struct.new(:request).new(Struct.new(:env).new("HTTP_REFERER" => referer)) + assert_equal 'javascript:history.back()', url_for(:back) + end + def test_button_to_with_straight_url assert_dom_equal %{<form method="post" action="http://www.example.com" class="button_to"><input type="submit" value="Hello" /></form>}, button_to("Hello", "http://www.example.com") end @@ -500,6 +520,13 @@ class UrlHelperTest < ActiveSupport::TestCase mail_to("david@loudthinking.com", "David Heinemeier Hansson", class: "admin") end + def test_mail_to_with_special_characters + assert_dom_equal( + %{<a href="mailto:%23%21%24%25%26%27%2A%2B-%2F%3D%3F%5E_%60%7B%7D%7C%7E@example.org">#!$%&'*+-/=?^_`{}|~@example.org</a>}, + mail_to("#!$%&'*+-/=?^_`{}|~@example.org") + ) + end + def test_mail_with_options assert_dom_equal( %{<a href="mailto:me@example.com?cc=ccaddress%40example.com&bcc=bccaddress%40example.com&body=This%20is%20the%20body%20of%20the%20message.&subject=This%20is%20an%20example%20email&reply-to=foo%40bar.com">My email</a>}, @@ -517,6 +544,20 @@ class UrlHelperTest < ActiveSupport::TestCase mail_to('feedback@example.com', '<img src="/feedback.png" />'.html_safe) end + def test_mail_to_with_html_safe_string + assert_dom_equal( + %{<a href="mailto:david@loudthinking.com">david@loudthinking.com</a>}, + mail_to("david@loudthinking.com".html_safe) + ) + end + + def test_mail_to_with_nil + assert_dom_equal( + %{<a href="mailto:"></a>}, + mail_to(nil) + ) + end + def test_mail_to_returns_html_safe_string assert mail_to("david@loudthinking.com").html_safe? end @@ -541,7 +582,7 @@ class UrlHelperTest < ActiveSupport::TestCase self.request_forgery end - def form_authenticity_token + def form_authenticity_token(*args) "secret" end @@ -595,10 +636,6 @@ class UrlHelperControllerTest < ActionController::TestCase render inline: "<%= url_for controller: 'url_helper_controller_test/url_helper', action: 'show_url_for' %>" end - def show_overridden_url_for - render inline: "<%= url_for params.merge(controller: 'url_helper_controller_test/url_helper', action: 'show_url_for') %>" - end - def show_named_route render inline: "<%= show_named_route_#{params[:kind]} %>" end @@ -632,11 +669,6 @@ class UrlHelperControllerTest < ActionController::TestCase assert_equal '/url_helper_controller_test/url_helper/show_url_for', @response.body end - def test_overridden_url_for_shows_only_path - get :show_overridden_url_for - assert_equal '/url_helper_controller_test/url_helper/show_url_for', @response.body - end - def test_named_route_url_shows_host_and_path get :show_named_route, params: { kind: 'url' } assert_equal 'http://test.host/url_helper_controller_test/url_helper/show_named_route', @@ -779,6 +811,13 @@ class SessionsController < ActionController::Base @session = Session.new(params[:id]) render inline: "<%= url_for([@workshop, @session]) %>\n<%= link_to('Session', [@workshop, @session]) %>" end + + def edit + @workshop = Workshop.new(params[:workshop_id]) + @session = Session.new(params[:id]) + @url = [@workshop, @session, format: params[:format]] + render inline: "<%= url_for(@url) %>\n<%= link_to('Session', @url) %>" + end end class PolymorphicControllerTest < ActionController::TestCase @@ -809,4 +848,11 @@ class PolymorphicControllerTest < ActionController::TestCase get :show, params: { workshop_id: 1, id: 1 } assert_equal %{/workshops/1/sessions/1\n<a href="/workshops/1/sessions/1">Session</a>}, @response.body end + + def test_existing_nested_resource_with_params + @controller = SessionsController.new + + get :edit, params: { workshop_id: 1, id: 1, format: "json" } + assert_equal %{/workshops/1/sessions/1.json\n<a href="/workshops/1/sessions/1.json">Session</a>}, @response.body + end end |