diff options
Diffstat (limited to 'actionpack/test')
174 files changed, 5887 insertions, 2285 deletions
diff --git a/actionpack/test/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb index bf068aedcd..62f82a4c7a 100644 --- a/actionpack/test/abstract/abstract_controller_test.rb +++ b/actionpack/test/abstract/abstract_controller_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'set' module AbstractController module Testing @@ -28,7 +29,7 @@ module AbstractController # Test Render mixin # ==== class RenderingController < AbstractController::Base - include ::AbstractController::Rendering + include AbstractController::Rendering def _prefixes [] @@ -152,7 +153,7 @@ module AbstractController # ==== # self._layout is used when defined class WithLayouts < PrefixedViews - include Layouts + include AbstractController::Layouts private def self.layout(formats) @@ -254,7 +255,7 @@ module AbstractController class TestActionMethodsReloading < ActiveSupport::TestCase test "action_methods should be reloaded after defining a new method" do - assert_equal ["index"], Me6.action_methods + assert_equal Set.new(["index"]), Me6.action_methods end end diff --git a/actionpack/test/abstract/collector_test.rb b/actionpack/test/abstract/collector_test.rb index 2ebcebbbb7..c14d24905b 100644 --- a/actionpack/test/abstract/collector_test.rb +++ b/actionpack/test/abstract/collector_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module AbstractController module Testing class MyCollector - include Collector + include AbstractController::Collector attr_accessor :responses def initialize @@ -54,4 +54,4 @@ module AbstractController end end end -end
\ No newline at end of file +end diff --git a/actionpack/test/abstract/helper_test.rb b/actionpack/test/abstract/helper_test.rb index b28a5b5afb..e79008fa9d 100644 --- a/actionpack/test/abstract/helper_test.rb +++ b/actionpack/test/abstract/helper_test.rb @@ -7,7 +7,7 @@ module AbstractController class ControllerWithHelpers < AbstractController::Base include AbstractController::Rendering - include Helpers + include AbstractController::Helpers def with_module render :inline => "Module <%= included_method %>" @@ -44,7 +44,7 @@ module AbstractController class AbstractHelpersBlock < ControllerWithHelpers helper do - include ::AbstractController::Testing::HelperyTest + include AbstractController::Testing::HelperyTest end end @@ -69,7 +69,12 @@ module AbstractController end def test_declare_missing_helper - assert_raise(MissingSourceFile) { AbstractHelpers.helper :missing } + begin + AbstractHelpers.helper :missing + flunk "should have raised an exception" + rescue LoadError => e + assert_equal "helpers/missing_helper.rb", e.path + end end def test_helpers_with_module_through_block diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb index fc25718d9e..558a45b87f 100644 --- a/actionpack/test/abstract/layouts_test.rb +++ b/actionpack/test/abstract/layouts_test.rb @@ -14,7 +14,10 @@ module AbstractControllerTests "layouts/overwrite.erb" => "Overwrite <%= yield %>", "layouts/with_false_layout.erb" => "False Layout <%= yield %>", "abstract_controller_tests/layouts/with_string_implied_child.erb" => - "With Implied <%= yield %>" + "With Implied <%= yield %>", + "abstract_controller_tests/layouts/with_grand_child_of_implied.erb" => + "With Grand Child <%= yield %>" + )] end @@ -64,6 +67,10 @@ module AbstractControllerTests class WithChildOfImplied < WithStringImpliedChild end + class WithGrandChildOfImplied < WithStringImpliedChild + layout nil + end + class WithProc < Base layout proc { |c| "overwrite" } @@ -72,6 +79,27 @@ module AbstractControllerTests end end + class WithZeroArityProc < Base + layout proc { "overwrite" } + + def index + render :template => ActionView::Template::Text.new("Hello zero arity proc!") + end + end + + class WithProcInContextOfInstance < Base + def an_instance_method; end + + layout proc { + break unless respond_to? :an_instance_method + "overwrite" + } + + def index + render :template => ActionView::Template::Text.new("Hello again zero arity proc!") + end + end + class WithSymbol < Base layout :hello @@ -221,6 +249,18 @@ module AbstractControllerTests assert_equal "Overwrite Hello proc!", controller.response_body end + test "when layout is specified as a proc without parameters it works just the same" do + controller = WithZeroArityProc.new + controller.process(:index) + assert_equal "Overwrite Hello zero arity proc!", controller.response_body + end + + test "when layout is specified as a proc without parameters the block is evaluated in the context of an instance" do + controller = WithProcInContextOfInstance.new + controller.process(:index) + assert_equal "Overwrite Hello again zero arity proc!", controller.response_body + end + test "when layout is specified as a symbol, call the requested method and use the layout returned" do controller = WithSymbol.new controller.process(:index) @@ -266,6 +306,13 @@ module AbstractControllerTests assert_equal "With Implied Hello string!", controller.response_body end + test "when a grandchild has nil layout specified, the child has an implied layout, and the " \ + "parent has specified a layout, use the child controller layout" do + controller = WithGrandChildOfImplied.new + controller.process(:index) + assert_equal "With Grand Child Hello string!", controller.response_body + end + test "raises an exception when specifying layout true" do assert_raises ArgumentError do Object.class_eval do @@ -299,6 +346,18 @@ module AbstractControllerTests controller.process(:index) assert_equal "Overwrite Hello index!", controller.response_body end + + test "layout for anonymous controller" do + klass = Class.new(WithString) do + def index + render :text => 'index', :layout => true + end + end + + controller = klass.new + controller.process(:index) + assert_equal "With String index", controller.response_body + end end end end diff --git a/actionpack/test/abstract/translation_test.rb b/actionpack/test/abstract/translation_test.rb index 0194ee943f..99064a8b87 100644 --- a/actionpack/test/abstract/translation_test.rb +++ b/actionpack/test/abstract/translation_test.rb @@ -23,4 +23,17 @@ class TranslationControllerTest < ActiveSupport::TestCase def test_action_controller_base_responds_to_l assert_respond_to @controller, :l end + + def test_lazy_lookup + expected = 'bar' + @controller.stubs(:action_name => :index) + I18n.stubs(:translate).with('action_controller.base.index.foo').returns(expected) + assert_equal expected, @controller.t('.foo') + end + + def test_default_translation + key, expected = 'one.two' 'bar' + I18n.stubs(:translate).with(key).returns(expected) + assert_equal expected, @controller.t(key) + end end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index b1a5356ddd..4f5b2895c9 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -1,11 +1,5 @@ require File.expand_path('../../../load_paths', __FILE__) -lib = File.expand_path("#{File.dirname(__FILE__)}/../lib") -$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib) - -activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__) -$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path) - $:.unshift(File.dirname(__FILE__) + '/lib') $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') $:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers') @@ -91,50 +85,47 @@ module RenderERBUtils end end -module SetupOnce - extend ActiveSupport::Concern - - included do - cattr_accessor :setup_once_block - self.setup_once_block = nil - - setup :run_setup_once - end +SharedTestRoutes = ActionDispatch::Routing::RouteSet.new - module ClassMethods - def setup_once(&block) - self.setup_once_block = block +module ActionDispatch + module SharedRoutes + def before_setup + @routes = SharedTestRoutes + super end end - private - def run_setup_once - if self.setup_once_block - self.setup_once_block.call - self.setup_once_block = nil - end + # Hold off drawing routes until all the possible controller classes + # have been loaded. + module DrawOnce + class << self + attr_accessor :drew end -end + self.drew = false -SharedTestRoutes = ActionDispatch::Routing::RouteSet.new + def before_setup + super + return if DrawOnce.drew -module ActiveSupport - class TestCase - include SetupOnce - # Hold off drawing routes until all the possible controller classes - # have been loaded. - setup_once do SharedTestRoutes.draw do - match ':controller(/:action)' + get ':controller(/:action)' end ActionDispatch::IntegrationTest.app.routes.draw do - match ':controller(/:action)' + get ':controller(/:action)' end + + DrawOnce.drew = true end end end +module ActiveSupport + class TestCase + include ActionDispatch::DrawOnce + end +end + class RoutedRackApp attr_reader :routes @@ -165,9 +156,7 @@ class BasicController end class ActionDispatch::IntegrationTest < ActiveSupport::TestCase - setup do - @routes = SharedTestRoutes - end + include ActionDispatch::SharedRoutes def self.build_app(routes = nil) RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware| @@ -177,7 +166,7 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase middleware.use "ActionDispatch::ParamsParser" middleware.use "ActionDispatch::Cookies" middleware.use "ActionDispatch::Flash" - middleware.use "ActionDispatch::Head" + middleware.use "Rack::Head" yield(middleware) if block_given? end end @@ -283,6 +272,7 @@ module ActionController include ActionController::Testing # This stub emulates the Railtie including the URL helpers from a Rails application include SharedTestRoutes.url_helpers + include SharedTestRoutes.mounted_helpers self.view_paths = FIXTURE_LOAD_PATH @@ -295,10 +285,7 @@ module ActionController class TestCase include ActionDispatch::TestProcess - - setup do - @routes = SharedTestRoutes - end + include ActionDispatch::SharedRoutes end end @@ -309,9 +296,7 @@ module ActionView class TestCase # Must repeat the setup because AV::TestCase is a duplication # of AC::TestCase - setup do - @routes = SharedTestRoutes - end + include ActionDispatch::SharedRoutes end end @@ -361,6 +346,36 @@ end module RoutingTestHelpers def url_for(set, options, recall = nil) - set.send(:url_for, options.merge(:only_path => true, :_path_segments => recall)) + set.send(:url_for, options.merge(:only_path => true, :_recall => recall)) + end +end + +class ResourcesController < ActionController::Base + def index() render :nothing => true end + alias_method :show, :index +end + +class ThreadsController < ResourcesController; end +class MessagesController < ResourcesController; end +class CommentsController < ResourcesController; end +class ReviewsController < ResourcesController; end +class AuthorsController < ResourcesController; end +class LogosController < ResourcesController; end + +class AccountsController < ResourcesController; end +class AdminController < ResourcesController; end +class ProductsController < ResourcesController; end +class ImagesController < ResourcesController; end +class PreferencesController < ResourcesController; end + +module Backoffice + class ProductsController < ResourcesController; end + class TagsController < ResourcesController; end + class ManufacturersController < ResourcesController; end + class ImagesController < ResourcesController; end + + module Admin + class ProductsController < ResourcesController; end + class ImagesController < ResourcesController; end end end diff --git a/actionpack/test/activerecord/active_record_store_test.rb b/actionpack/test/activerecord/active_record_store_test.rb deleted file mode 100644 index 2fe7959f5a..0000000000 --- a/actionpack/test/activerecord/active_record_store_test.rb +++ /dev/null @@ -1,281 +0,0 @@ -require 'active_record_unit' - -class ActiveRecordStoreTest < ActionDispatch::IntegrationTest - class TestController < ActionController::Base - def no_session_access - head :ok - end - - def set_session_value - raise "missing session!" unless session - session[:foo] = params[:foo] || "bar" - head :ok - end - - def get_session_value - render :text => "foo: #{session[:foo].inspect}" - end - - def get_session_id - render :text => "#{request.session_options[:id]}" - end - - def call_reset_session - session[:foo] - reset_session - reset_session if params[:twice] - session[:foo] = "baz" - head :ok - end - - def renew - env["rack.session.options"][:renew] = true - session[:foo] = "baz" - head :ok - end - end - - def setup - ActiveRecord::SessionStore.session_class.create_table! - end - - def teardown - ActiveRecord::SessionStore.session_class.drop_table! - end - - %w{ session sql_bypass }.each do |class_name| - define_method("test_setting_and_getting_session_value_with_#{class_name}_store") do - with_store class_name do - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - - get '/get_session_value' - assert_response :success - assert_equal 'foo: "bar"', response.body - - get '/set_session_value', :foo => "baz" - assert_response :success - assert cookies['_session_id'] - - get '/get_session_value' - assert_response :success - assert_equal 'foo: "baz"', response.body - - get '/call_reset_session' - assert_response :success - assert_not_equal [], headers['Set-Cookie'] - end - end - end - - define_method("test_renewing_with_#{class_name}_store") do - with_store class_name do - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - - get '/renew' - assert_response :success - assert_not_equal [], headers['Set-Cookie'] - end - end - end - end - - def test_getting_nil_session_value - with_test_route_set do - get '/get_session_value' - assert_response :success - assert_equal 'foo: nil', response.body - end - end - - def test_calling_reset_session_twice_does_not_raise_errors - with_test_route_set do - get '/call_reset_session', :twice => "true" - assert_response :success - - get '/get_session_value' - assert_response :success - assert_equal 'foo: "baz"', response.body - end - end - - def test_setting_session_value_after_session_reset - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - session_id = cookies['_session_id'] - - get '/call_reset_session' - assert_response :success - assert_not_equal [], headers['Set-Cookie'] - - get '/get_session_value' - assert_response :success - assert_equal 'foo: "baz"', response.body - - get '/get_session_id' - assert_response :success - assert_not_equal session_id, response.body - end - end - - def test_getting_session_value_after_session_reset - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - session_cookie = cookies.send(:hash_for)['_session_id'] - - get '/call_reset_session' - assert_response :success - assert_not_equal [], headers['Set-Cookie'] - - cookies << session_cookie # replace our new session_id with our old, pre-reset session_id - - get '/get_session_value' - assert_response :success - assert_equal 'foo: nil', response.body, "data for this session should have been obliterated from the database" - end - end - - def test_getting_from_nonexistent_session - with_test_route_set do - get '/get_session_value' - assert_response :success - assert_equal 'foo: nil', response.body - assert_nil cookies['_session_id'], "should only create session on write, not read" - end - end - - def test_getting_session_id - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - session_id = cookies['_session_id'] - - get '/get_session_id' - assert_response :success - assert_equal session_id, response.body, "should be able to read session id without accessing the session hash" - end - end - - def test_doesnt_write_session_cookie_if_session_id_is_already_exists - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - - get '/get_session_value' - assert_response :success - assert_equal nil, headers['Set-Cookie'], "should not resend the cookie again if session_id cookie is already exists" - end - end - - def test_prevents_session_fixation - with_test_route_set do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - - get '/get_session_value' - assert_response :success - assert_equal 'foo: "bar"', response.body - session_id = cookies['_session_id'] - assert session_id - - reset! - - get '/get_session_value', :_session_id => session_id - assert_response :success - assert_equal 'foo: nil', response.body - assert_not_equal session_id, cookies['_session_id'] - end - end - - def test_allows_session_fixation - with_test_route_set(:cookie_only => false) do - get '/set_session_value' - assert_response :success - assert cookies['_session_id'] - - get '/get_session_value' - assert_response :success - assert_equal 'foo: "bar"', response.body - session_id = cookies['_session_id'] - assert session_id - - reset! - - get '/set_session_value', :_session_id => session_id, :foo => "baz" - assert_response :success - assert_equal session_id, cookies['_session_id'] - - get '/get_session_value', :_session_id => session_id - assert_response :success - assert_equal 'foo: "baz"', response.body - assert_equal session_id, cookies['_session_id'] - end - end - - def test_incoming_invalid_session_id_via_cookie_should_be_ignored - with_test_route_set do - open_session do |sess| - sess.cookies['_session_id'] = 'INVALID' - - sess.get '/set_session_value' - new_session_id = sess.cookies['_session_id'] - assert_not_equal 'INVALID', new_session_id - - sess.get '/get_session_value' - new_session_id_2 = sess.cookies['_session_id'] - assert_equal new_session_id, new_session_id_2 - end - end - end - - def test_incoming_invalid_session_id_via_parameter_should_be_ignored - with_test_route_set(:cookie_only => false) do - open_session do |sess| - sess.get '/set_session_value', :_session_id => 'INVALID' - new_session_id = sess.cookies['_session_id'] - assert_not_equal 'INVALID', new_session_id - - sess.get '/get_session_value' - new_session_id_2 = sess.cookies['_session_id'] - assert_equal new_session_id, new_session_id_2 - end - end - end - - private - - def with_test_route_set(options = {}) - with_routing do |set| - set.draw do - match ':action', :to => 'active_record_store_test/test' - end - - @app = self.class.build_app(set) do |middleware| - middleware.use ActiveRecord::SessionStore, options.reverse_merge(:key => '_session_id') - middleware.delete "ActionDispatch::ShowExceptions" - end - - yield - end - end - - def with_store(class_name) - session_class, ActiveRecord::SessionStore.session_class = - ActiveRecord::SessionStore.session_class, "ActiveRecord::SessionStore::#{class_name.camelize}".constantize - yield - ensure - ActiveRecord::SessionStore.session_class = session_class - end -end diff --git a/actionpack/test/activerecord/polymorphic_routes_test.rb b/actionpack/test/activerecord/polymorphic_routes_test.rb index 90e7f4ae59..afb714484b 100644 --- a/actionpack/test/activerecord/polymorphic_routes_test.rb +++ b/actionpack/test/activerecord/polymorphic_routes_test.rb @@ -25,6 +25,24 @@ class Series < ActiveRecord::Base self.table_name = 'projects' end +class ModelDelegator < ActiveRecord::Base + self.table_name = 'projects' + + def to_model + ModelDelegate.new + end +end + +class ModelDelegate + def self.model_name + ActiveModel::Name.new(self) + end + + def to_param + 'overridden' + end +end + module Blog class Post < ActiveRecord::Base self.table_name = 'projects' @@ -50,6 +68,7 @@ class PolymorphicRoutesTest < ActionController::TestCase @bid = Bid.new @tax = Tax.new @fax = Fax.new + @delegator = ModelDelegator.new @series = Series.new @blog_post = Blog::Post.new @blog_blog = Blog::Blog.new @@ -439,6 +458,13 @@ class PolymorphicRoutesTest < ActionController::TestCase end end + def test_routing_a_to_model_delegate + with_test_routes do + @delegator.save + assert_equal "http://example.com/model_delegates/overridden", polymorphic_url(@delegator) + end + end + def with_namespaced_routes(name) with_routing do |set| set.draw do @@ -469,6 +495,7 @@ class PolymorphicRoutesTest < ActionController::TestCase resource :bid end resources :series + resources :model_delegates end self.class.send(:include, @routes.url_helpers) @@ -516,5 +543,4 @@ class PolymorphicRoutesTest < ActionController::TestCase yield end end - end diff --git a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb index 97be5a5bb0..409370104d 100644 --- a/actionpack/test/activerecord/render_partial_with_record_identification_test.rb +++ b/actionpack/test/activerecord/render_partial_with_record_identification_test.rb @@ -16,7 +16,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base end def render_with_has_many_through_association - @developer = Developer.find(:first) + @developer = Developer.first render :partial => @developer.topics end @@ -31,7 +31,7 @@ class RenderPartialWithRecordIdentificationController < ActionController::Base end def render_with_record - @developer = Developer.find(:first) + @developer = Developer.first render :partial => @developer end @@ -130,14 +130,40 @@ class RenderPartialWithRecordIdentificationAndNestedControllersTest < ActiveReco def test_render_with_record_in_nested_controller get :render_with_record_in_nested_controller - assert_template 'fun/games/_game' - assert_equal 'Pong', @response.body + assert_template %r{\Afun/games/_game\Z} + assert_equal "Fun Pong\n", @response.body end def test_render_with_record_collection_in_nested_controller get :render_with_record_collection_in_nested_controller - assert_template 'fun/games/_game' - assert_equal 'PongTank', @response.body + assert_template %r{\Afun/games/_game\Z} + assert_equal "Fun Pong\nFun Tank\n", @response.body + end +end + +class RenderPartialWithRecordIdentificationAndNestedControllersWithoutPrefixTest < ActiveRecordTestCase + tests Fun::NestedController + + def test_render_with_record_in_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_in_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Pong\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config + end + + def test_render_with_record_collection_in_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_collection_in_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Pong\nJust Tank\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config end end @@ -146,13 +172,39 @@ class RenderPartialWithRecordIdentificationAndNestedDeeperControllersTest < Acti def test_render_with_record_in_deeper_nested_controller get :render_with_record_in_deeper_nested_controller - assert_template 'fun/serious/games/_game' - assert_equal 'Chess', @response.body + assert_template %r{\Afun/serious/games/_game\Z} + assert_equal "Serious Chess\n", @response.body end def test_render_with_record_collection_in_deeper_nested_controller get :render_with_record_collection_in_deeper_nested_controller - assert_template 'fun/serious/games/_game' - assert_equal 'ChessSudokuSolitaire', @response.body + assert_template %r{\Afun/serious/games/_game\Z} + assert_equal "Serious Chess\nSerious Sudoku\nSerious Solitaire\n", @response.body + end +end + +class RenderPartialWithRecordIdentificationAndNestedDeeperControllersWithoutPrefixTest < ActiveRecordTestCase + tests Fun::Serious::NestedDeeperController + + def test_render_with_record_in_deeper_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_in_deeper_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Chess\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config + end + + def test_render_with_record_collection_in_deeper_nested_controller + old_config = ActionView::Base.prefix_partial_path_with_controller_namespace + ActionView::Base.prefix_partial_path_with_controller_namespace = false + + get :render_with_record_collection_in_deeper_nested_controller + assert_template %r{\Agames/_game\Z} + assert_equal "Just Chess\nJust Sudoku\nJust Solitaire\n", @response.body + ensure + ActionView::Base.prefix_partial_path_with_controller_namespace = old_config end end diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb index 01cafe1aca..4ab5d92a2b 100644 --- a/actionpack/test/controller/action_pack_assertions_test.rb +++ b/actionpack/test/controller/action_pack_assertions_test.rb @@ -1,5 +1,5 @@ require 'abstract_unit' -require 'action_controller/vendor/html-scanner' +require 'action_view/vendor/html-scanner' require 'controller/fake_controllers' class ActionPackAssertionsController < ActionController::Base @@ -76,6 +76,11 @@ class ActionPackAssertionsController < ActionController::Base render "test/hello_world", :layout => "layouts/standard" end + def render_with_layout_and_partial + @variable_for_layout = nil + render "test/hello_world_with_partial", :layout => "layouts/standard" + end + def session_stuffing session['xmas'] = 'turkey' render :text => "ho ho ho" @@ -162,7 +167,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_string_constraint with_routing do |set| set.draw do - match "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"} + get "photos", :to => 'action_pack_assertions#nothing', :constraints => {:subdomain => "admin"} end end end @@ -170,15 +175,18 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase def test_assert_redirect_to_named_route_failure with_routing do |set| set.draw do - match 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one - match 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two - match ':controller/:action' + get 'route_one', :to => 'action_pack_assertions#nothing', :as => :route_one + get 'route_two', :to => 'action_pack_assertions#nothing', :id => 'two', :as => :route_two + get ':controller/:action' end process :redirect_to_named_route assert_raise(ActiveSupport::TestCase::Assertion) do assert_redirected_to 'http://test.host/route_two' end assert_raise(ActiveSupport::TestCase::Assertion) do + assert_redirected_to %r(^http://test.host/route_two) + end + assert_raise(ActiveSupport::TestCase::Assertion) do assert_redirected_to :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two' end assert_raise(ActiveSupport::TestCase::Assertion) do @@ -192,8 +200,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do - match 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module - match ':controller/:action' + get 'admin/inner_module', :to => 'admin/inner_module#index', :as => :admin_inner_module + get ':controller/:action' end process :redirect_to_index # redirection is <{"action"=>"index", "controller"=>"admin/admin/inner_module"}> @@ -206,12 +214,13 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do - match '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level - match ':controller/:action' + get '/action_pack_assertions/:id', :to => 'action_pack_assertions#index', :as => :top_level + get ':controller/:action' end process :redirect_to_top_level_named_route # assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return assert_redirected_to "/action_pack_assertions/foo" + assert_redirected_to %r(/action_pack_assertions/foo) end end @@ -221,8 +230,8 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase with_routing do |set| set.draw do # this controller exists in the admin namespace as well which is the only difference from previous test - match '/user/:id', :to => 'user#index', :as => :top_level - match ':controller/:action' + get '/user/:id', :to => 'user#index', :as => :top_level + get ':controller/:action' end process :redirect_to_top_level_named_route # assert_redirected_to top_level_url('foo') would pass because of exact match early return @@ -469,11 +478,43 @@ class AssertTemplateTest < ActionController::TestCase end end + def test_fails_expecting_no_layout + get :render_with_layout + assert_raise(ActiveSupport::TestCase::Assertion) do + assert_template :layout => nil + end + end + def test_passes_with_correct_layout get :render_with_layout assert_template :layout => "layouts/standard" end + def test_passes_with_layout_and_partial + get :render_with_layout_and_partial + assert_template :layout => "layouts/standard" + end + + def test_passed_with_no_layout + get :hello_world + assert_template :layout => nil + end + + def test_passed_with_no_layout_false + get :hello_world + assert_template :layout => false + end + + def test_passes_with_correct_layout_without_layouts_prefix + get :render_with_layout + assert_template :layout => "standard" + end + + def test_passes_with_correct_layout_symbol + get :render_with_layout + assert_template :layout => :standard + end + def test_assert_template_reset_between_requests get :hello_world assert_template 'test/hello_world' diff --git a/actionpack/test/controller/assert_select_test.rb b/actionpack/test/controller/assert_select_test.rb index d3359e79a6..38598a520c 100644 --- a/actionpack/test/controller/assert_select_test.rb +++ b/actionpack/test/controller/assert_select_test.rb @@ -10,6 +10,16 @@ require 'controller/fake_controllers' require 'action_mailer' ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH +class SynchronousQueue < Queue + def push(job) + job.run + end + alias << push + alias enq push +end + +ActionMailer::Base.queue = SynchronousQueue.new + class AssertSelectTest < ActionController::TestCase Assertion = ActiveSupport::TestCase::Assertion @@ -131,6 +141,13 @@ class AssertSelectTest < ActionController::TestCase assert_raise(Assertion) { assert_select "pre", :html=>text } end + def test_strip_textarea + render_html %Q{<textarea>\n\nfoo\n</textarea>} + assert_select "textarea", "\nfoo\n" + render_html %Q{<textarea>\nfoo</textarea>} + assert_select "textarea", "foo" + end + def test_counts render_html %Q{<div id="1">foo</div><div id="2">foo</div>} assert_nothing_raised { assert_select "div", 2 } diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb index 791edb9069..9b42e7631f 100644 --- a/actionpack/test/controller/base_test.rb +++ b/actionpack/test/controller/base_test.rb @@ -1,5 +1,6 @@ require 'abstract_unit' require 'active_support/logger' +require 'controller/fake_models' require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late # Provide some controller to run the tests on. @@ -45,7 +46,7 @@ class DefaultUrlOptionsController < ActionController::Base render :inline => "<%= #{params[:route]} %>" end - def default_url_options(options = nil) + def default_url_options { :host => 'www.override.com', :action => 'new', :locale => 'en' } end end @@ -56,13 +57,17 @@ class UrlOptionsController < ActionController::Base end def url_options - super.merge(:host => 'www.override.com', :action => 'new', :locale => 'en') + super.merge(:host => 'www.override.com') end end class RecordIdentifierController < ActionController::Base end +class RecordIdentifierWithoutDeprecationController < ActionController::Base + include ActionView::RecordIdentifier +end + class ControllerClassTests < ActiveSupport::TestCase def test_controller_path @@ -81,6 +86,42 @@ class ControllerClassTests < ActiveSupport::TestCase assert_respond_to RecordIdentifierController.new, :dom_id assert_respond_to RecordIdentifierController.new, :dom_class end + + def test_record_identifier_is_deprecated + record = Comment.new + record.save + + dom_id = nil + assert_deprecated 'dom_id method will no longer' do + dom_id = RecordIdentifierController.new.dom_id(record) + end + + assert_equal 'comment_1', dom_id + + dom_class = nil + assert_deprecated 'dom_class method will no longer' do + dom_class = RecordIdentifierController.new.dom_class(record) + end + assert_equal 'comment', dom_class + end + + def test_no_deprecation_when_action_view_record_identifier_is_included + record = Comment.new + record.save + + dom_id = nil + assert_not_deprecated do + dom_id = RecordIdentifierWithoutDeprecationController.new.dom_id(record) + end + + assert_equal 'comment_1', dom_id + + dom_class = nil + assert_not_deprecated do + dom_class = RecordIdentifierWithoutDeprecationController.new.dom_class(record) + end + assert_equal 'comment', dom_class + end end class ControllerInstanceTests < ActiveSupport::TestCase @@ -130,8 +171,6 @@ class PerformActionTest < ActionController::TestCase @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @request.host = "www.nextangle.com" - - rescue_action_in_public! end def test_process_should_be_precise @@ -155,13 +194,12 @@ class UrlOptionsTest < ActionController::TestCase def setup super @request.host = 'www.example.com' - rescue_action_in_public! end def test_url_for_query_params_included rs = ActionDispatch::Routing::RouteSet.new rs.draw do - match 'home' => 'pages#home' + get 'home' => 'pages#home' end options = { @@ -177,25 +215,24 @@ class UrlOptionsTest < ActionController::TestCase def test_url_options_override with_routing do |set| set.draw do - match 'from_view', :to => 'url_options#from_view', :as => :from_view - match ':controller/:action' + get 'from_view', :to => 'url_options#from_view', :as => :from_view + get ':controller/:action' end get :from_view, :route => "from_view_url" - assert_equal 'http://www.override.com/from_view?locale=en', @response.body - assert_equal 'http://www.override.com/from_view?locale=en', @controller.send(:from_view_url) - assert_equal 'http://www.override.com/default_url_options/new?locale=en', @controller.url_for(:controller => 'default_url_options') + assert_equal 'http://www.override.com/from_view', @response.body + assert_equal 'http://www.override.com/from_view', @controller.send(:from_view_url) + assert_equal 'http://www.override.com/default_url_options/index', @controller.url_for(:controller => 'default_url_options') end end def test_url_helpers_does_not_become_actions with_routing do |set| set.draw do - match "account/overview" + get "account/overview" end - @controller.class.send(:include, set.url_helpers) assert !@controller.class.action_methods.include?("account_overview_path") end end @@ -207,14 +244,13 @@ class DefaultUrlOptionsTest < ActionController::TestCase def setup super @request.host = 'www.example.com' - rescue_action_in_public! end def test_default_url_options_override with_routing do |set| set.draw do - match 'from_view', :to => 'default_url_options#from_view', :as => :from_view - match ':controller/:action' + get 'from_view', :to => 'default_url_options#from_view', :as => :from_view + get ':controller/:action' end get :from_view, :route => "from_view_url" @@ -231,7 +267,7 @@ class DefaultUrlOptionsTest < ActionController::TestCase scope("/:locale") do resources :descriptions end - match ':controller/:action' + get ':controller/:action' end get :from_view, :route => "description_path(1)" @@ -258,7 +294,6 @@ class EmptyUrlOptionsTest < ActionController::TestCase def setup super @request.host = 'www.example.com' - rescue_action_in_public! end def test_ensure_url_for_works_as_expected_when_called_with_no_options_if_default_url_options_is_not_set diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index a42c68a628..2c3511f6a0 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -102,8 +102,8 @@ class PageCachingTest < ActionController::TestCase def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route with_routing do |set| set.draw do - match 'posts.:format', :to => 'posts#index', :as => :formatted_posts - match '/', :to => 'posts#index', :as => :main + get 'posts.:format', :to => 'posts#index', :as => :formatted_posts + get '/', :to => 'posts#index', :as => :main end @params[:format] = 'rss' assert_equal '/posts.rss', @routes.url_for(@params) @@ -223,6 +223,7 @@ end class ActionCachingTestController < CachingController rescue_from(Exception) { head 500 } + rescue_from(ActionController::UnknownFormat) { head :not_acceptable } if defined? ActiveRecord rescue_from(ActiveRecord::RecordNotFound) { head :not_found } end @@ -230,14 +231,16 @@ class ActionCachingTestController < CachingController # Eliminate uninitialized ivar warning before_filter { @title = nil } - caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour + caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| c.request.format && !c.request.format.json? }, :expires_in => 1.hour caches_action :show, :cache_path => 'http://test.host/custom/show' caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" } caches_action :with_layout caches_action :with_format_and_http_param, :cache_path => Proc.new { |c| { :key => 'value' } } caches_action :layout_false, :layout => false + caches_action :with_layout_proc_param, :layout => Proc.new { |c| c.params[:layout] } caches_action :record_not_found, :four_oh_four, :simple_runtime_error caches_action :streaming + caches_action :invalid layout 'talk_from_action' @@ -282,6 +285,7 @@ class ActionCachingTestController < CachingController alias_method :edit, :index alias_method :destroy, :index alias_method :layout_false, :with_layout + alias_method :with_layout_proc_param, :with_layout def expire expire_action :controller => 'action_caching_test', :action => 'index' @@ -301,6 +305,14 @@ class ActionCachingTestController < CachingController def streaming render :text => "streaming", :stream => true end + + def invalid + @cache_this = MockTime.now.to_f.to_s + + respond_to do |format| + format.json{ render :json => @cache_this } + end + end end class MockTime < Time @@ -337,15 +349,18 @@ class ActionCachingMockController end class ActionCacheTest < ActionController::TestCase + tests ActionCachingTestController + def setup super - reset! + @request.host = 'hostname.com' FileUtils.mkdir_p(FILE_STORE_PATH) @path_class = ActionController::Caching::Actions::ActionCachePath @mock_controller = ActionCachingMockController.new end def teardown + super FileUtils.rm_rf(File.dirname(FILE_STORE_PATH)) end @@ -355,7 +370,6 @@ class ActionCacheTest < ActionController::TestCase cached_time = content_to_cache assert_equal cached_time, @response.body assert fragment_exist?('hostname.com/action_caching_test') - reset! get :index assert_response :success @@ -368,7 +382,6 @@ class ActionCacheTest < ActionController::TestCase cached_time = content_to_cache assert_equal cached_time, @response.body assert !fragment_exist?('hostname.com/action_caching_test/destroy') - reset! get :destroy assert_response :success @@ -383,7 +396,6 @@ class ActionCacheTest < ActionController::TestCase cached_time = content_to_cache assert_not_equal cached_time, @response.body assert fragment_exist?('hostname.com/action_caching_test/with_layout') - reset! get :with_layout assert_response :success @@ -398,16 +410,42 @@ class ActionCacheTest < ActionController::TestCase cached_time = content_to_cache assert_not_equal cached_time, @response.body assert fragment_exist?('hostname.com/action_caching_test/layout_false') - reset! get :layout_false assert_response :success assert_not_equal cached_time, @response.body - body = body_to_string(read_fragment('hostname.com/action_caching_test/layout_false')) assert_equal cached_time, body end + def test_action_cache_with_layout_and_layout_cache_false_via_proc + get :with_layout_proc_param, :layout => false + assert_response :success + cached_time = content_to_cache + assert_not_equal cached_time, @response.body + assert fragment_exist?('hostname.com/action_caching_test/with_layout_proc_param') + + get :with_layout_proc_param, :layout => false + assert_response :success + assert_not_equal cached_time, @response.body + body = body_to_string(read_fragment('hostname.com/action_caching_test/with_layout_proc_param')) + assert_equal cached_time, body + end + + def test_action_cache_with_layout_and_layout_cache_true_via_proc + get :with_layout_proc_param, :layout => true + assert_response :success + cached_time = content_to_cache + assert_not_equal cached_time, @response.body + assert fragment_exist?('hostname.com/action_caching_test/with_layout_proc_param') + + get :with_layout_proc_param, :layout => true + assert_response :success + assert_not_equal cached_time, @response.body + body = body_to_string(read_fragment('hostname.com/action_caching_test/with_layout_proc_param')) + assert_equal @response.body, body + end + def test_action_cache_conditional_options @request.env['HTTP_ACCEPT'] = 'application/json' get :index @@ -436,7 +474,6 @@ class ActionCacheTest < ActionController::TestCase cached_time = content_to_cache assert_equal cached_time, @response.body assert fragment_exist?('test.host/custom/show') - reset! get :show assert_response :success @@ -447,7 +484,6 @@ class ActionCacheTest < ActionController::TestCase get :edit assert_response :success assert fragment_exist?('test.host/edit') - reset! get :edit, :id => 1 assert_response :success @@ -458,22 +494,18 @@ class ActionCacheTest < ActionController::TestCase get :index assert_response :success cached_time = content_to_cache - reset! get :index assert_response :success assert_equal cached_time, @response.body - reset! get :expire assert_response :success - reset! get :index assert_response :success new_cached_time = content_to_cache assert_not_equal cached_time, @response.body - reset! get :index assert_response :success @@ -483,12 +515,10 @@ class ActionCacheTest < ActionController::TestCase def test_cache_expiration_isnt_affected_by_request_format get :index cached_time = content_to_cache - reset! @request.request_uri = "/action_caching_test/expire.xml" get :expire, :format => :xml assert_response :success - reset! get :index assert_response :success @@ -498,12 +528,10 @@ class ActionCacheTest < ActionController::TestCase def test_cache_expiration_with_url_string get :index cached_time = content_to_cache - reset! @request.request_uri = "/action_caching_test/expire_with_url_string" get :expire_with_url_string assert_response :success - reset! get :index assert_response :success @@ -516,23 +544,17 @@ class ActionCacheTest < ActionController::TestCase assert_response :success jamis_cache = content_to_cache - reset! - @request.host = 'david.hostname.com' get :index assert_response :success david_cache = content_to_cache assert_not_equal jamis_cache, @response.body - reset! - @request.host = 'jamis.hostname.com' get :index assert_response :success assert_equal jamis_cache, @response.body - reset! - @request.host = 'david.hostname.com' get :index assert_response :success @@ -542,8 +564,6 @@ class ActionCacheTest < ActionController::TestCase def test_redirect_is_not_cached get :redirected assert_response :redirect - reset! - get :redirected assert_response :redirect end @@ -551,8 +571,6 @@ class ActionCacheTest < ActionController::TestCase def test_forbidden_is_not_cached get :forbidden assert_response :forbidden - reset! - get :forbidden assert_response :forbidden end @@ -560,7 +578,7 @@ class ActionCacheTest < ActionController::TestCase def test_xml_version_of_resource_is_treated_as_different_cache with_routing do |set| set.draw do - match ':controller(/:action(.:format))' + get ':controller(/:action(.:format))' end get :index, :format => 'xml' @@ -568,17 +586,14 @@ class ActionCacheTest < ActionController::TestCase cached_time = content_to_cache assert_equal cached_time, @response.body assert fragment_exist?('hostname.com/action_caching_test/index.xml') - reset! get :index, :format => 'xml' assert_response :success assert_equal cached_time, @response.body assert_equal 'application/xml', @response.content_type - reset! get :expire_xml assert_response :success - reset! get :index, :format => 'xml' assert_response :success @@ -659,19 +674,30 @@ class ActionCacheTest < ActionController::TestCase assert fragment_exist?('hostname.com/action_caching_test/streaming') end + def test_invalid_format_returns_not_acceptable + get :invalid, :format => "json" + assert_response :success + cached_time = content_to_cache + assert_equal cached_time, @response.body + + assert fragment_exist?("hostname.com/action_caching_test/invalid.json") + + get :invalid, :format => "json" + assert_response :success + assert_equal cached_time, @response.body + + get :invalid, :format => "xml" + assert_response :not_acceptable + + get :invalid, :format => "\xC3\x83" + assert_response :not_acceptable + end + private def content_to_cache assigns(:cache_this) end - def reset! - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - @controller = ActionCachingTestController.new - @controller.singleton_class.send(:include, @routes.url_helpers) - @request.host = 'hostname.com' - end - def fragment_exist?(path) @controller.fragment_exist?(path) end @@ -828,14 +854,17 @@ Ciao CACHED assert_equal expected_body, @response.body - assert_equal "This bit's fragment cached", @store.read('views/test.host/functional_caching/fragment_cached') + assert_equal "This bit's fragment cached", + @store.read("views/test.host/functional_caching/fragment_cached/#{template_digest("functional_caching/fragment_cached", "html")}") end def test_fragment_caching_in_partials get :html_fragment_cached_with_partial assert_response :success assert_match(/Old fragment caching in a partial/, @response.body) - assert_match("Old fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial')) + + assert_match("Old fragment caching in a partial", + @store.read("views/test.host/functional_caching/html_fragment_cached_with_partial/#{template_digest("functional_caching/_partial", "html")}")) end def test_render_inline_before_fragment_caching @@ -843,7 +872,8 @@ CACHED assert_response :success assert_match(/Some inline content/, @response.body) assert_match(/Some cached content/, @response.body) - assert_match("Some cached content", @store.read('views/test.host/functional_caching/inline_fragment_cached')) + assert_match("Some cached content", + @store.read("views/test.host/functional_caching/inline_fragment_cached/#{template_digest("functional_caching/inline_fragment_cached", "html")}")) end def test_html_formatted_fragment_caching @@ -853,7 +883,8 @@ CACHED assert_equal expected_body, @response.body - assert_equal "<p>ERB</p>", @store.read('views/test.host/functional_caching/formatted_fragment_cached') + assert_equal "<p>ERB</p>", + @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached", "html")}") end def test_xml_formatted_fragment_caching @@ -863,8 +894,14 @@ CACHED assert_equal expected_body, @response.body - assert_equal " <p>Builder</p>\n", @store.read('views/test.host/functional_caching/formatted_fragment_cached') + assert_equal " <p>Builder</p>\n", + @store.read("views/test.host/functional_caching/formatted_fragment_cached/#{template_digest("functional_caching/formatted_fragment_cached", "xml")}") end + + private + def template_digest(name, format) + ActionView::Digestor.digest(name, format, @controller.lookup_context) + end end class CacheHelperOutputBufferTest < ActionController::TestCase diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index 046396b37c..d203601771 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -193,7 +193,7 @@ class FilterTest < ActionController::TestCase end class ConditionalClassFilter - def self.filter(controller) controller.instance_variable_set(:"@ran_class_filter", true) end + def self.before(controller) controller.instance_variable_set(:"@ran_class_filter", true) end end class OnlyConditionClassController < ConditionalFilterController @@ -309,7 +309,7 @@ class FilterTest < ActionController::TestCase end class AuditFilter - def self.filter(controller) + def self.before(controller) controller.instance_variable_set(:"@was_audited", true) end end @@ -326,6 +326,12 @@ class FilterTest < ActionController::TestCase controller.instance_variable_set(:"@after_ran", true) controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log end + + def around(controller) + before(controller) + yield + after(controller) + end end class AppendedAroundFilter @@ -336,6 +342,12 @@ class FilterTest < ActionController::TestCase def after(controller) controller.class.execution_log << " after appended aroundfilter " end + + def around(controller) + before(controller) + yield + after(controller) + end end class AuditController < ActionController::Base @@ -437,7 +449,7 @@ class FilterTest < ActionController::TestCase class ErrorToRescue < Exception; end class RescuingAroundFilterWithBlock - def filter(controller) + def around(controller) begin yield rescue ErrorToRescue => ex @@ -493,6 +505,10 @@ class FilterTest < ActionController::TestCase def show render :text => 'hello world' end + + def error + raise StandardError.new + end end class ImplicitActionsController < ActionController::Base @@ -510,11 +526,25 @@ class FilterTest < ActionController::TestCase end end + def test_sweeper_should_not_ignore_no_method_error + sweeper = ActionController::Caching::Sweeper.send(:new) + assert_raise NoMethodError do + sweeper.send_not_defined + end + end + def test_sweeper_should_not_block_rendering response = test_process(SweeperTestController) assert_equal 'hello world', response.body end + def test_sweeper_should_clean_up_if_exception_is_raised + assert_raise StandardError do + test_process(SweeperTestController, 'error') + end + assert_nil AppSweeper.instance.controller + end + def test_before_method_of_sweeper_should_always_return_true sweeper = ActionController::Caching::Sweeper.send(:new) assert sweeper.before(TestController.new) @@ -864,7 +894,7 @@ end class ControllerWithFilterClass < PostsController class YieldingFilter < DefaultFilter - def self.filter(controller) + def self.around(controller) yield raise After end @@ -875,7 +905,7 @@ end class ControllerWithFilterInstance < PostsController class YieldingFilter < DefaultFilter - def filter(controller) + def around(controller) yield raise After end @@ -886,13 +916,13 @@ end class ControllerWithFilterMethod < PostsController class YieldingFilter < DefaultFilter - def filter(controller) + def around(controller) yield raise After end end - around_filter YieldingFilter.new.method(:filter), :only => :raises_after + around_filter YieldingFilter.new.method(:around), :only => :raises_after end class ControllerWithProcFilter < PostsController @@ -937,9 +967,7 @@ class ControllerWithAllTypesOfFilters < PostsController end class ControllerWithTwoLessFilters < ControllerWithAllTypesOfFilters - $vbf = true skip_filter :around_again - $vbf = false skip_filter :after end diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index 37ccc7a4a5..8340aab4d2 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -90,6 +90,10 @@ class FlashTest < ActionController::TestCase def redirect_with_other_flashes redirect_to '/wonderland', :flash => { :joyride => "Horses!" } end + + def redirect_with_foo_flash + redirect_to "/wonderland", :foo => 'for great justice' + end end tests TestController @@ -203,6 +207,12 @@ class FlashTest < ActionController::TestCase get :redirect_with_other_flashes assert_equal "Horses!", @controller.send(:flash)[:joyride] end + + def test_redirect_to_with_adding_flash_types + @controller.class.add_flash_types :foo + get :redirect_with_foo_flash + assert_equal "for great justice", @controller.send(:flash)[:foo] + end end class FlashIntegrationTest < ActionDispatch::IntegrationTest @@ -210,9 +220,7 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33' class TestController < ActionController::Base - def dont_set_flash - head :ok - end + add_flash_types :bar def set_flash flash["that"] = "hello" @@ -227,6 +235,11 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest def use_flash render :inline => "flash: #{flash["that"]}" end + + def set_bar + flash[:bar] = "for great justice" + head :ok + end end def test_flash @@ -266,6 +279,14 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest end end + def test_added_flash_types_method + with_test_route_set do + get '/set_bar' + assert_response :success + assert_equal 'for great justice', @controller.bar + end + end + private # Overwrite get to send SessionSecret in env hash @@ -277,7 +298,7 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match ':action', :to => FlashIntegrationTest::TestController + get ':action', :to => FlashIntegrationTest::TestController end @app = self.class.build_app(set) do |middleware| diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb index b681a19fe0..6758668b7a 100644 --- a/actionpack/test/controller/force_ssl_test.rb +++ b/actionpack/test/controller/force_ssl_test.rb @@ -26,6 +26,14 @@ class ForceSSLExceptAction < ForceSSLController force_ssl :except => :banana end +class ForceSSLIfCondition < ForceSSLController + force_ssl :if => :use_force_ssl? + + def use_force_ssl? + action_name == 'cheeseburger' + end +end + class ForceSSLFlash < ForceSSLController force_ssl :except => [:banana, :set_flash, :use_flash] @@ -41,6 +49,15 @@ class ForceSSLFlash < ForceSSLController end end +class RedirectToSSL < ForceSSLController + def banana + force_ssl_redirect || render(:text => 'monkey') + end + def cheeseburger + force_ssl_redirect('secure.cheeseburger.host') || render(:text => 'ihaz') + end +end + class ForceSSLControllerLevelTest < ActionController::TestCase tests ForceSSLControllerLevel @@ -109,18 +126,19 @@ class ForceSSLExceptActionTest < ActionController::TestCase end end -class ForceSSLExcludeDevelopmentTest < ActionController::TestCase - tests ForceSSLControllerLevel - - def setup - Rails.env.stubs(:development?).returns(false) - end +class ForceSSLIfConditionTest < ActionController::TestCase + tests ForceSSLIfCondition - def test_development_environment_not_redirects_to_https - Rails.env.stubs(:development?).returns(true) + def test_banana_not_redirects_to_https get :banana assert_response 200 end + + def test_cheeseburger_redirects_to_https + get :cheeseburger + assert_response 301 + assert_equal "https://test.host/force_ssl_if_condition/cheeseburger", redirect_to_url + end end class ForceSSLFlashTest < ActionController::TestCase @@ -140,3 +158,25 @@ class ForceSSLFlashTest < ActionController::TestCase assert_equal "hello", assigns["flashy"] end end + +class RedirectToSSLTest < ActionController::TestCase + tests RedirectToSSL + def test_banana_redirects_to_https_if_not_https + get :banana + assert_response 301 + assert_equal "https://test.host/redirect_to_ssl/banana", redirect_to_url + end + + def test_cheeseburgers_redirects_to_https_with_new_host_if_not_https + get :cheeseburger + assert_response 301 + assert_equal "https://secure.cheeseburger.host/redirect_to_ssl/cheeseburger", redirect_to_url + end + + def test_banana_does_not_redirect_if_already_https + request.env['HTTPS'] = 'on' + get :cheeseburger + assert_response 200 + assert_equal 'ihaz', response.body + end +end
\ No newline at end of file diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 757661d8d0..248c81193e 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -46,12 +46,42 @@ end class MeTooController < JustMeController end +class HelpersPathsController < ActionController::Base + paths = ["helpers2_pack", "helpers1_pack"].map do |path| + File.join(File.expand_path('../../fixtures', __FILE__), path) + end + $:.unshift(*paths) + + self.helpers_path = paths + helper :all + + def index + render :inline => "<%= conflicting_helper %>" + end +end + module LocalAbcHelper def a() end def b() end def c() end end +class HelperPathsTest < ActiveSupport::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_helpers_paths_priority + request = ActionController::TestRequest.new + responses = HelpersPathsController.action(:index).call(request.env) + + # helpers1_pack was given as a second path, so pack1_helper should be + # included as the second one + assert_equal "pack1", responses.last.body + end +end + class HelperTest < ActiveSupport::TestCase class TestController < ActionController::Base attr_accessor :delegate_attr @@ -79,13 +109,13 @@ class HelperTest < ActiveSupport::TestCase def test_helper_method assert_nothing_raised { @controller_class.helper_method :delegate_method } - assert master_helper_methods.include?('delegate_method') + assert master_helper_methods.include?(:delegate_method) end def test_helper_attr assert_nothing_raised { @controller_class.helper_attr :delegate_attr } - assert master_helper_methods.include?('delegate_attr') - assert master_helper_methods.include?('delegate_attr=') + assert master_helper_methods.include?(:delegate_attr) + assert master_helper_methods.include?(:delegate_attr=) end def call_controller(klass, action) @@ -130,16 +160,16 @@ class HelperTest < ActiveSupport::TestCase end def test_all_helpers - methods = AllHelpersController._helpers.instance_methods.map {|m| m.to_s} + methods = AllHelpersController._helpers.instance_methods # abc_helper.rb - assert methods.include?('bare_a') + assert methods.include?(:bare_a) # fun/games_helper.rb - assert methods.include?('stratego') + assert methods.include?(:stratego) # fun/pdf_helper.rb - assert methods.include?('foobar') + assert methods.include?(:foobar) end def test_all_helpers_with_alternate_helper_dir @@ -150,35 +180,35 @@ class HelperTest < ActiveSupport::TestCase @controller_class.helper :all # helpers/abc_helper.rb should not be included - assert !master_helper_methods.include?('bare_a') + assert !master_helper_methods.include?(:bare_a) # alternate_helpers/foo_helper.rb - assert master_helper_methods.include?('baz') + assert master_helper_methods.include?(:baz) end def test_helper_proxy - methods = AllHelpersController.helpers.methods.map(&:to_s) + methods = AllHelpersController.helpers.methods # Action View - assert methods.include?('pluralize') + assert methods.include?(:pluralize) # abc_helper.rb - assert methods.include?('bare_a') + assert methods.include?(:bare_a) # fun/games_helper.rb - assert methods.include?('stratego') + assert methods.include?(:stratego) # fun/pdf_helper.rb - assert methods.include?('foobar') + assert methods.include?(:foobar) end private def expected_helper_methods - TestHelper.instance_methods.map {|m| m.to_s } + TestHelper.instance_methods end def master_helper_methods - @controller_class._helpers.instance_methods.map {|m| m.to_s } + @controller_class._helpers.instance_methods end def missing_methods diff --git a/actionpack/test/controller/http_digest_authentication_test.rb b/actionpack/test/controller/http_digest_authentication_test.rb index a91e3cafa5..b11ad633bd 100644 --- a/actionpack/test/controller/http_digest_authentication_test.rb +++ b/actionpack/test/controller/http_digest_authentication_test.rb @@ -139,11 +139,12 @@ class HttpDigestAuthenticationTest < ActionController::TestCase test "authentication request with request-uri that doesn't match credentials digest-uri" do @request.env['HTTP_AUTHORIZATION'] = encode_credentials(:username => 'pretty', :password => 'please') - @request.env['ORIGINAL_FULLPATH'] = "/http_digest_authentication_test/dummy_digest/altered/uri" + @request.env['PATH_INFO'] = "/proxied/uri" get :display - assert_response :unauthorized - assert_equal "Authentication Failed", @response.body + assert_response :success + assert assigns(:logged_in) + assert_equal 'Definitely Maybe', @response.body end test "authentication request with absolute request uri (as in webrick)" do @@ -274,6 +275,6 @@ class HttpDigestAuthenticationTest < ActionController::TestCase end def decode_credentials(header) - ActionController::HttpAuthentication::Digest.decode_credentials(@response.headers['WWW-Authenticate']) + ActionController::HttpAuthentication::Digest.decode_credentials(header) end end diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb index 3054c1684c..ad4e743be8 100644 --- a/actionpack/test/controller/http_token_authentication_test.rb +++ b/actionpack/test/controller/http_token_authentication_test.rb @@ -79,6 +79,14 @@ class HttpTokenAuthenticationTest < ActionController::TestCase end end + test "authentication request with badly formatted header" do + @request.env['HTTP_AUTHORIZATION'] = "Token foobar" + get :index + + assert_response :unauthorized + assert_equal "HTTP Token: Access denied.\n", @response.body, "Authentication header was not properly parsed" + end + test "authentication request without credential" do get :display diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 44f033119d..cf561d913a 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -1,6 +1,6 @@ require 'abstract_unit' require 'controller/fake_controllers' -require 'action_controller/vendor/html-scanner' +require 'action_view/vendor/html-scanner' class SessionTest < ActiveSupport::TestCase StubApp = lambda { |env| @@ -405,6 +405,15 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end end + def test_request_with_bad_format + with_test_route_set do + xhr :get, '/get.php' + assert_equal 406, status + assert_response 406 + assert_response :not_acceptable + end + end + def test_get_with_query_string with_test_route_set do get '/get_with_params?foo=bar' @@ -466,7 +475,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end set.draw do - match ':action', :to => controller + match ':action', :to => controller, :via => [:get, :post] get 'get/:action', :to => controller end @@ -529,11 +538,26 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest @routes ||= ActionDispatch::Routing::RouteSet.new end + class MountedApp + def self.routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + routes.draw do + get 'baz', :to => 'application_integration_test/test#index', :as => :baz + end + + def self.call(*) + end + end + routes.draw do - match '', :to => 'application_integration_test/test#index', :as => :empty_string + get '', :to => 'application_integration_test/test#index', :as => :empty_string + + get 'foo', :to => 'application_integration_test/test#index', :as => :foo + get 'bar', :to => 'application_integration_test/test#index', :as => :bar - match 'foo', :to => 'application_integration_test/test#index', :as => :foo - match 'bar', :to => 'application_integration_test/test#index', :as => :bar + mount MountedApp => '/mounted', :as => "mounted" end def app @@ -546,6 +570,10 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest assert_equal '/bar', bar_path end + test "includes mounted helpers" do + assert_equal '/mounted/baz', mounted.baz_path + end + test "route helpers after controller access" do get '/' assert_equal '/', empty_string_path @@ -606,3 +634,83 @@ class EnvironmentFilterIntegrationTest < ActionDispatch::IntegrationTest assert_equal '[FILTERED]', request.filtered_env['rack.request.form_vars'] end end + +class UrlOptionsIntegrationTest < ActionDispatch::IntegrationTest + class FooController < ActionController::Base + def index + render :text => "foo#index" + end + + def show + render :text => "foo#show" + end + + def edit + render :text => "foo#show" + end + end + + class BarController < ActionController::Base + def default_url_options + { :host => "bar.com" } + end + + def index + render :text => "foo#index" + end + end + + def self.routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + def self.call(env) + routes.call(env) + end + + def app + self.class + end + + routes.draw do + default_url_options :host => "foo.com" + + scope :module => "url_options_integration_test" do + get "/foo" => "foo#index", :as => :foos + get "/foo/:id" => "foo#show", :as => :foo + get "/foo/:id/edit" => "foo#edit", :as => :edit_foo + get "/bar" => "bar#index", :as => :bars + end + end + + test "session uses default url options from routes" do + assert_equal "http://foo.com/foo", foos_url + end + + test "current host overrides default url options from routes" do + get "/foo" + assert_response :success + assert_equal "http://www.example.com/foo", foos_url + end + + test "controller can override default url options from request" do + get "/bar" + assert_response :success + assert_equal "http://bar.com/foo", foos_url + end + + test "test can override default url options" do + default_url_options[:host] = "foobar.com" + assert_equal "http://foobar.com/foo", foos_url + + get "/bar" + assert_response :success + assert_equal "http://foobar.com/foo", foos_url + end + + test "current request path parameters are recalled" do + get "/foo/1" + assert_response :success + assert_equal "/foo/1/edit", url_for(:action => 'edit', :only_path => true) + end +end diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb index bc171e201b..94a8d2f180 100644 --- a/actionpack/test/controller/layout_test.rb +++ b/actionpack/test/controller/layout_test.rb @@ -78,6 +78,13 @@ end class DefaultLayoutController < LayoutTest end +class StreamingLayoutController < LayoutTest + def render(*args) + options = args.extract_options! || {} + super(*args, options.merge(:stream => true)) + end +end + class AbsolutePathLayoutController < LayoutTest layout File.expand_path(File.expand_path(__FILE__) + '/../../fixtures/layout_tests/layouts/layout_test') end @@ -122,6 +129,12 @@ class LayoutSetInResponseTest < ActionController::TestCase assert_template :layout => "layouts/layout_test" end + def test_layout_set_when_using_streaming_layout + @controller = StreamingLayoutController.new + get :hello + assert_template :hello + end + def test_layout_set_when_set_in_controller @controller = HasOwnLayoutController.new get :hello @@ -187,7 +200,7 @@ class SetsNonExistentLayoutFile < LayoutTest layout "nofile" end -class LayoutExceptionRaised < ActionController::TestCase +class LayoutExceptionRaisedTest < ActionController::TestCase def test_exception_raised_when_layout_file_not_found @controller = SetsNonExistentLayoutFile.new assert_raise(ActionView::MissingTemplate) { get :hello } diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb new file mode 100644 index 0000000000..20e433d1ec --- /dev/null +++ b/actionpack/test/controller/live_stream_test.rb @@ -0,0 +1,121 @@ +require 'abstract_unit' +require 'active_support/concurrency/latch' + +module ActionController + class LiveStreamTest < ActionController::TestCase + class TestController < ActionController::Base + include ActionController::Live + + attr_accessor :latch, :tc + + def self.controller_path + 'test' + end + + def render_text + render :text => 'zomg' + end + + def default_header + response.stream.write "<html><body>hi</body></html>" + response.stream.close + end + + def basic_stream + response.headers['Content-Type'] = 'text/event-stream' + %w{ hello world }.each do |word| + response.stream.write word + end + response.stream.close + end + + def blocking_stream + response.headers['Content-Type'] = 'text/event-stream' + %w{ hello world }.each do |word| + response.stream.write word + latch.await + end + response.stream.close + end + + def thread_locals + tc.assert_equal 'aaron', Thread.current[:setting] + tc.refute_equal Thread.current.object_id, Thread.current[:originating_thread] + + response.headers['Content-Type'] = 'text/event-stream' + %w{ hello world }.each do |word| + response.stream.write word + end + response.stream.close + end + end + + tests TestController + + class TestResponse < Live::Response + def recycle! + initialize + end + end + + def build_response + TestResponse.new + end + + def test_set_response! + @controller.set_response!(@request) + assert_kind_of(Live::Response, @controller.response) + assert_equal @request, @controller.response.request + end + + def test_write_to_stream + @controller = TestController.new + get :basic_stream + assert_equal "helloworld", @response.body + assert_equal 'text/event-stream', @response.headers['Content-Type'] + end + + def test_async_stream + @controller.latch = ActiveSupport::Concurrency::Latch.new + parts = ['hello', 'world'] + + @controller.request = @request + @controller.response = @response + + t = Thread.new(@response) { |resp| + resp.stream.each do |part| + assert_equal parts.shift, part + ol = @controller.latch + @controller.latch = ActiveSupport::Concurrency::Latch.new + ol.release + end + } + + @controller.process :blocking_stream + + assert t.join + end + + def test_thread_locals_get_copied + @controller.tc = self + Thread.current[:originating_thread] = Thread.current.object_id + Thread.current[:setting] = 'aaron' + + get :thread_locals + end + + def test_live_stream_default_header + @controller.request = @request + @controller.response = @response + @controller.process :default_header + _, headers, _ = @response.prepare! + assert headers['Content-Type'] + end + + def test_render_text + get :render_text + assert_equal 'zomg', response.body + assert response.stream.closed?, 'stream should be closed' + end + end +end diff --git a/actionpack/test/controller/log_subscriber_test.rb b/actionpack/test/controller/log_subscriber_test.rb index 700fd788fa..a72b6dde1a 100644 --- a/actionpack/test/controller/log_subscriber_test.rb +++ b/actionpack/test/controller/log_subscriber_test.rb @@ -54,6 +54,10 @@ module Another def with_rescued_exception raise SpecialException end + + def with_action_not_found + raise AbstractController::ActionNotFound + end end end @@ -225,6 +229,17 @@ class ACLogSubscriberTest < ActionController::TestCase assert_match(/Completed 406/, logs.last) end + def test_process_action_with_with_action_not_found_logs_404 + begin + get :with_action_not_found + wait + rescue AbstractController::ActionNotFound + end + + assert_equal 2, logs.size + assert_match(/Completed 404/, logs.last) + end + def logs @logs ||= @logger.logged(:info) end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index ae368842b5..b21d35c846 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -1,7 +1,6 @@ require 'abstract_unit' require 'controller/fake_models' require 'active_support/core_ext/hash/conversions' -require 'active_support/core_ext/object/inclusion' class StarStarMimeController < ActionController::Base layout nil @@ -132,7 +131,6 @@ class RespondToController < ActionController::Base end end - def iphone_with_html_response_type request.format = :iphone if request.env["HTTP_ACCEPT"] == "text/iphone" @@ -153,10 +151,11 @@ class RespondToController < ActionController::Base protected def set_layout - if action_name.in?(["all_types_with_layout", "iphone_with_html_response_type"]) - "respond_to/layouts/standard" - elsif action_name == "iphone_with_html_response_type_without_layout" - "respond_to/layouts/missing" + case action_name + when "all_types_with_layout", "iphone_with_html_response_type" + "respond_to/layouts/standard" + when "iphone_with_html_response_type_without_layout" + "respond_to/layouts/missing" end end end @@ -208,8 +207,9 @@ class RespondToControllerTest < ActionController::TestCase get :html_or_xml assert_equal 'HTML', @response.body - get :just_xml - assert_response 406 + assert_raises(ActionController::UnknownFormat) do + get :just_xml + end end def test_all @@ -240,8 +240,10 @@ class RespondToControllerTest < ActionController::TestCase assert_equal 'HTML', @response.body @request.accept = "text/javascript, text/html" - xhr :get, :just_xml - assert_response 406 + + assert_raises(ActionController::UnknownFormat) do + xhr :get, :just_xml + end end def test_json_or_yaml_with_leading_star_star @@ -496,14 +498,14 @@ class RespondToControllerTest < ActionController::TestCase end def test_invalid_format - get :using_defaults, :format => "invalidformat" - assert_equal " ", @response.body - assert_equal "text/html", @response.content_type + assert_raises(ActionController::UnknownFormat) do + get :using_defaults, :format => "invalidformat" + end end end class RespondWithController < ActionController::Base - respond_to :html, :json + respond_to :html, :json, :touch respond_to :xml, :except => :using_resource_with_block respond_to :js, :only => [ :using_resource_with_block, :using_resource, 'using_hash_resource' ] @@ -621,12 +623,14 @@ class RespondWithControllerTest < ActionController::TestCase super @request.host = "www.example.com" Mime::Type.register_alias('text/html', :iphone) + Mime::Type.register_alias('text/html', :touch) Mime::Type.register('text/x-mobile', :mobile) end def teardown super Mime::Type.unregister(:iphone) + Mime::Type.unregister(:touch) Mime::Type.unregister(:mobile) end @@ -702,12 +706,14 @@ class RespondWithControllerTest < ActionController::TestCase def test_not_acceptable @request.accept = "application/xml" - get :using_resource_with_block - assert_equal 406, @response.status + assert_raises(ActionController::UnknownFormat) do + get :using_resource_with_block + end @request.accept = "text/javascript" - get :using_resource_with_overwrite_block - assert_equal 406, @response.status + assert_raises(ActionController::UnknownFormat) do + get :using_resource_with_overwrite_block + end end def test_using_resource_for_post_with_html_redirects_on_success @@ -845,7 +851,7 @@ class RespondWithControllerTest < ActionController::TestCase put :using_resource assert_equal "application/xml", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_put_with_json_yields_no_content_on_success @@ -854,7 +860,7 @@ class RespondWithControllerTest < ActionController::TestCase put :using_resource assert_equal "application/json", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure @@ -896,7 +902,7 @@ class RespondWithControllerTest < ActionController::TestCase delete :using_resource assert_equal "application/xml", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_delete_with_json_yields_no_content_on_success @@ -906,7 +912,7 @@ class RespondWithControllerTest < ActionController::TestCase delete :using_resource assert_equal "application/json", @response.content_type assert_equal 204, @response.status - assert_equal " ", @response.body + assert_equal "", @response.body end def test_using_resource_for_delete_with_html_redirects_on_failure @@ -985,8 +991,9 @@ class RespondWithControllerTest < ActionController::TestCase def test_clear_respond_to @controller = InheritedRespondWithController.new @request.accept = "text/html" - get :index - assert_equal 406, @response.status + assert_raises(ActionController::UnknownFormat) do + get :index + end end def test_first_in_respond_to_has_higher_priority @@ -1119,7 +1126,7 @@ class RespondWithControllerTest < ActionController::TestCase resources :quiz_stores do resources :customers end - match ":controller/:action" + get ":controller/:action" end yield end @@ -1135,7 +1142,7 @@ class PostController < AbstractPostController around_filter :with_iphone def index - respond_to(:html, :iphone) + respond_to(:html, :iphone, :js) end protected @@ -1182,4 +1189,45 @@ class MimeControllerLayoutsTest < ActionController::TestCase get :index assert_equal '<html><div id="super_iphone">Super iPhone</div></html>', @response.body end + + def test_non_navigational_format_with_no_template_fallbacks_to_html_template_with_no_layout + get :index, :format => :js + assert_equal "Hello Firefox", @response.body + end +end + +class FlashResponder < ActionController::Responder + def initialize(controller, resources, options={}) + super + end + + def to_html + controller.flash[:notice] = 'Success' + super + end +end + +class FlashResponderController < ActionController::Base + self.responder = FlashResponder + respond_to :html + + def index + respond_with Object.new do |format| + format.html { render :text => 'HTML' } + end + end +end + +class FlashResponderControllerTest < ActionController::TestCase + tests FlashResponderController + + def test_respond_with_block_executed + get :index + assert_equal 'HTML', @response.body + end + + def test_flash_responder_executed + get :index + assert_equal 'Success', flash[:notice] + end end diff --git a/actionpack/test/controller/new_base/bare_metal_test.rb b/actionpack/test/controller/new_base/bare_metal_test.rb index c424dcbd8d..7396c850ad 100644 --- a/actionpack/test/controller/new_base/bare_metal_test.rb +++ b/actionpack/test/controller/new_base/bare_metal_test.rb @@ -37,6 +37,36 @@ module BareMetalTest def index head :not_found end + + def continue + self.content_type = "text/html" + head 100 + end + + def switching_protocols + self.content_type = "text/html" + head 101 + end + + def processing + self.content_type = "text/html" + head 102 + end + + def no_content + self.content_type = "text/html" + head 204 + end + + def reset_content + self.content_type = "text/html" + head 205 + end + + def not_modified + self.content_type = "text/html" + head 304 + end end class HeadTest < ActiveSupport::TestCase @@ -44,6 +74,72 @@ module BareMetalTest status = HeadController.action(:index).call(Rack::MockRequest.env_for("/")).first assert_equal 404, status end + + test "head :continue (100) does not return a content-type header" do + headers = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :continue (101) does not return a content-type header" do + headers = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :processing (102) does not return a content-type header" do + headers = HeadController.action(:processing).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :no_content (204) does not return a content-type header" do + headers = HeadController.action(:no_content).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :reset_content (205) does not return a content-type header" do + headers = HeadController.action(:reset_content).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :not_modified (304) does not return a content-type header" do + headers = HeadController.action(:not_modified).call(Rack::MockRequest.env_for("/")).second + assert_nil headers['Content-Type'] + assert_nil headers['Content-Length'] + end + + test "head :no_content (204) does not return any content" do + content = HeadController.action(:no_content).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :reset_content (205) does not return any content" do + content = HeadController.action(:reset_content).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :not_modified (304) does not return any content" do + content = HeadController.action(:not_modified).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :continue (100) does not return any content" do + content = HeadController.action(:continue).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :switching_protocols (101) does not return any content" do + content = HeadController.action(:switching_protocols).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end + + test "head :processing (102) does not return any content" do + content = HeadController.action(:processing).call(Rack::MockRequest.env_for("/")).third.first + assert_empty content + end end class BareControllerTest < ActionController::TestCase diff --git a/actionpack/test/controller/new_base/content_type_test.rb b/actionpack/test/controller/new_base/content_type_test.rb index 4b70031c90..9b57641e75 100644 --- a/actionpack/test/controller/new_base/content_type_test.rb +++ b/actionpack/test/controller/new_base/content_type_test.rb @@ -43,7 +43,7 @@ module ContentType test "default response is HTML and UTF8" do with_routing do |set| set.draw do - match ':controller', :action => 'index' + get ':controller', :action => 'index' end get "/content_type/base" diff --git a/actionpack/test/controller/new_base/render_action_test.rb b/actionpack/test/controller/new_base/render_action_test.rb index aa44e0b282..475bf9d3c9 100644 --- a/actionpack/test/controller/new_base/render_action_test.rb +++ b/actionpack/test/controller/new_base/render_action_test.rb @@ -86,8 +86,6 @@ module RenderAction def setup end - describe "Both <controller_path>.html.erb and application.html.erb are missing" - test "rendering with layout => true" do assert_raise(ArgumentError) do get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false @@ -154,8 +152,6 @@ module RenderActionWithApplicationLayout end class LayoutTest < Rack::TestCase - describe "Only application.html.erb is present and <controller_path>.html.erb is missing" - test "rendering implicit application.html.erb as layout" do get "/render_action_with_application_layout/basic/hello_world" @@ -232,8 +228,6 @@ module RenderActionWithControllerLayout end class ControllerLayoutTest < Rack::TestCase - describe "Only <controller_path>.html.erb is present and application.html.erb is missing" - test "render hello_world and implicitly use <controller_path>.html.erb as a layout." do get "/render_action_with_controller_layout/basic/hello_world" @@ -290,8 +284,6 @@ module RenderActionWithBothLayouts end class ControllerLayoutTest < Rack::TestCase - describe "Both <controller_path>.html.erb and application.html.erb are present" - test "rendering implicitly use <controller_path>.html.erb over application.html.erb as a layout" do get "/render_action_with_both_layouts/basic/hello_world" diff --git a/actionpack/test/controller/new_base/render_streaming_test.rb b/actionpack/test/controller/new_base/render_streaming_test.rb index 61ea68e3f7..f4bdd3e1d4 100644 --- a/actionpack/test/controller/new_base/render_streaming_test.rb +++ b/actionpack/test/controller/new_base/render_streaming_test.rb @@ -73,19 +73,19 @@ module RenderStreaming test "rendering with layout exception" do get "/render_streaming/basic/layout_exception" - assert_body "d\r\n<body class=\"\r\n4e\r\n\"><script type=\"text/javascript\">window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" + assert_body "d\r\n<body class=\"\r\n37\r\n\"><script>window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" assert_streaming! end test "rendering with template exception" do get "/render_streaming/basic/template_exception" - assert_body "4e\r\n\"><script type=\"text/javascript\">window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" + assert_body "37\r\n\"><script>window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" assert_streaming! end test "rendering with template exception logs the exception" do io = StringIO.new - _old, ActionController::Base.logger = ActionController::Base.logger, ActiveSupport::Logger.new(io) + _old, ActionView::Base.logger = ActionView::Base.logger, ActiveSupport::Logger.new(io) begin get "/render_streaming/basic/template_exception" diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index ade204c387..d0be4f66d1 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -126,7 +126,7 @@ module RenderTemplate test "rendering a template with error properly excerts the code" do get :with_error assert_status 500 - assert_match "undefined local variable or method `idontexist'", response.body + assert_match "undefined local variable or method `idontexist", response.body end end @@ -160,11 +160,9 @@ module RenderTemplate end class TestWithLayout < Rack::TestCase - describe "Rendering with :template using implicit or explicit layout" - test "rendering with implicit layout" do with_routing do |set| - set.draw { match ':controller', :action => :index } + set.draw { get ':controller', :action => :index } get "/render_template/with_layout" diff --git a/actionpack/test/controller/new_base/render_test.rb b/actionpack/test/controller/new_base/render_test.rb index 60468bf5c7..cc7f12ac6d 100644 --- a/actionpack/test/controller/new_base/render_test.rb +++ b/actionpack/test/controller/new_base/render_test.rb @@ -57,7 +57,7 @@ module Render test "render with blank" do with_routing do |set| set.draw do - match ":controller", :action => 'index' + get ":controller", :action => 'index' end get "/render/blank_render" @@ -70,7 +70,7 @@ module Render test "rendering more than once raises an exception" do with_routing do |set| set.draw do - match ":controller", :action => 'index' + get ":controller", :action => 'index' end assert_raises(AbstractController::DoubleRenderError) do diff --git a/actionpack/test/controller/new_base/render_text_test.rb b/actionpack/test/controller/new_base/render_text_test.rb index 06d500cca7..d6c3926a4d 100644 --- a/actionpack/test/controller/new_base/render_text_test.rb +++ b/actionpack/test/controller/new_base/render_text_test.rb @@ -63,11 +63,9 @@ module RenderText end class RenderTextTest < Rack::TestCase - describe "Rendering text using render :text" - - test "rendering text from a action with default options renders the text with the layout" do + test "rendering text from an action with default options renders the text with the layout" do with_routing do |set| - set.draw { match ':controller', :action => 'index' } + set.draw { get ':controller', :action => 'index' } get "/render_text/simple" assert_body "hello david" @@ -75,9 +73,9 @@ module RenderText end end - test "rendering text from a action with default options renders the text without the layout" do + test "rendering text from an action with default options renders the text without the layout" do with_routing do |set| - set.draw { match ':controller', :action => 'index' } + set.draw { get ':controller', :action => 'index' } get "/render_text/with_layout" diff --git a/actionpack/test/controller/parameters/nested_parameters_test.rb b/actionpack/test/controller/parameters/nested_parameters_test.rb new file mode 100644 index 0000000000..41f5b6e127 --- /dev/null +++ b/actionpack/test/controller/parameters/nested_parameters_test.rb @@ -0,0 +1,113 @@ +require 'abstract_unit' +require 'action_controller/metal/strong_parameters' + +class NestedParametersTest < ActiveSupport::TestCase + test "permitted nested parameters" do + params = ActionController::Parameters.new({ + book: { + title: "Romeo and Juliet", + authors: [{ + name: "William Shakespeare", + born: "1564-04-26" + }, { + name: "Christopher Marlowe" + }], + details: { + pages: 200, + genre: "Tragedy" + } + }, + magazine: "Mjallo!" + }) + + permitted = params.permit book: [ :title, { authors: [ :name ] }, { details: :pages } ] + + assert permitted.permitted? + assert_equal "Romeo and Juliet", permitted[:book][:title] + assert_equal "William Shakespeare", permitted[:book][:authors][0][:name] + assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name] + assert_equal 200, permitted[:book][:details][:pages] + assert_nil permitted[:book][:details][:genre] + assert_nil permitted[:book][:authors][0][:born] + assert_nil permitted[:magazine] + end + + test "nested arrays with strings" do + params = ActionController::Parameters.new({ + :book => { + :genres => ["Tragedy"] + } + }) + + permitted = params.permit :book => :genres + assert_equal ["Tragedy"], permitted[:book][:genres] + end + + test "permit may specify symbols or strings" do + params = ActionController::Parameters.new({ + :book => { + :title => "Romeo and Juliet", + :author => "William Shakespeare" + }, + :magazine => "Shakespeare Today" + }) + + permitted = params.permit({:book => ["title", :author]}, "magazine") + assert_equal "Romeo and Juliet", permitted[:book][:title] + assert_equal "William Shakespeare", permitted[:book][:author] + assert_equal "Shakespeare Today", permitted[:magazine] + end + + test "nested array with strings that should be hashes" do + params = ActionController::Parameters.new({ + book: { + genres: ["Tragedy"] + } + }) + + permitted = params.permit book: { genres: :type } + assert_empty permitted[:book][:genres] + end + + test "nested array with strings that should be hashes and additional values" do + params = ActionController::Parameters.new({ + book: { + title: "Romeo and Juliet", + genres: ["Tragedy"] + } + }) + + permitted = params.permit book: [ :title, { genres: :type } ] + assert_equal "Romeo and Juliet", permitted[:book][:title] + assert_empty permitted[:book][:genres] + end + + test "nested string that should be a hash" do + params = ActionController::Parameters.new({ + book: { + genre: "Tragedy" + } + }) + + permitted = params.permit book: { genre: :type } + assert_nil permitted[:book][:genre] + end + + test "fields_for-style nested params" do + params = ActionController::Parameters.new({ + book: { + authors_attributes: { + :'0' => { name: 'William Shakespeare', age_of_death: '52' }, + :'-1' => { name: 'Unattributed Assistant' } + } + } + }) + permitted = params.permit book: { authors_attributes: [ :name ] } + + assert_not_nil permitted[:book][:authors_attributes]['0'] + assert_not_nil permitted[:book][:authors_attributes]['-1'] + assert_nil permitted[:book][:authors_attributes]['0'][:age_of_death] + assert_equal 'William Shakespeare', permitted[:book][:authors_attributes]['0'][:name] + assert_equal 'Unattributed Assistant', permitted[:book][:authors_attributes]['-1'][:name] + end +end diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb new file mode 100644 index 0000000000..7fe8e6051b --- /dev/null +++ b/actionpack/test/controller/parameters/parameters_permit_test.rb @@ -0,0 +1,73 @@ +require 'abstract_unit' +require 'action_controller/metal/strong_parameters' + +class ParametersPermitTest < ActiveSupport::TestCase + setup do + @params = ActionController::Parameters.new({ person: { + age: "32", name: { first: "David", last: "Heinemeier Hansson" } + }}) + end + + test "fetch raises ParameterMissing exception" do + e = assert_raises(ActionController::ParameterMissing) do + @params.fetch :foo + end + assert_equal :foo, e.param + end + + test "fetch doesnt raise ParameterMissing exception if there is a default" do + assert_equal "monkey", @params.fetch(:foo, "monkey") + assert_equal "monkey", @params.fetch(:foo) { "monkey" } + end + + test "permitted is sticky on accessors" do + assert !@params.slice(:person).permitted? + assert !@params[:person][:name].permitted? + + @params.each { |key, value| assert(value.permitted?) if key == :person } + + assert !@params.fetch(:person).permitted? + + assert !@params.values_at(:person).first.permitted? + end + + test "permitted is sticky on mutators" do + assert !@params.delete_if { |k| k == :person }.permitted? + assert !@params.keep_if { |k,v| k == :person }.permitted? + end + + test "permitted is sticky beyond merges" do + assert !@params.merge(a: "b").permitted? + end + + test "modifying the parameters" do + @params[:person][:hometown] = "Chicago" + @params[:person][:family] = { brother: "Jonas" } + + assert_equal "Chicago", @params[:person][:hometown] + assert_equal "Jonas", @params[:person][:family][:brother] + end + + test "permitting parameters that are not there should not include the keys" do + assert !@params.permit(:person, :funky).has_key?(:funky) + end + + test "permit state is kept on a dup" do + @params.permit! + assert_equal @params.permitted?, @params.dup.permitted? + end + + test "permitted takes a default value when Parameters.permit_all_parameters is set" do + begin + ActionController::Parameters.permit_all_parameters = true + params = ActionController::Parameters.new({ person: { + age: "32", name: { first: "David", last: "Heinemeier Hansson" } + }}) + + assert params.slice(:person).permitted? + assert params[:person][:name].permitted? + ensure + ActionController::Parameters.permit_all_parameters = false + end + end +end diff --git a/actionpack/test/controller/parameters/parameters_require_test.rb b/actionpack/test/controller/parameters/parameters_require_test.rb new file mode 100644 index 0000000000..bdaba8d2d8 --- /dev/null +++ b/actionpack/test/controller/parameters/parameters_require_test.rb @@ -0,0 +1,10 @@ +require 'abstract_unit' +require 'action_controller/metal/strong_parameters' + +class ParametersRequireTest < ActiveSupport::TestCase + test "required parameters must be present not merely not nil" do + assert_raises(ActionController::ParameterMissing) do + ActionController::Parameters.new(person: {}).require(:person) + end + end +end diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index c4d2614200..209f021cf7 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -37,6 +37,14 @@ class ParamsWrapperTest < ActionController::TestCase UsersController.last_parameters = nil end + def test_filtered_parameters + with_default_wrapper_options do + @request.env['CONTENT_TYPE'] = 'application/json' + post :parse, { 'username' => 'sikachu' } + assert_equal @request.filtered_parameters, { 'controller' => 'params_wrapper_test/users', 'action' => 'parse', 'username' => 'sikachu', 'user' => { 'username' => 'sikachu' } } + end + end + def test_derived_name_from_controller with_default_wrapper_options do @request.env['CONTENT_TYPE'] = 'application/json' @@ -147,7 +155,6 @@ class ParamsWrapperTest < ActionController::TestCase end def test_derived_wrapped_keys_from_matching_model - User.expects(:respond_to?).with(:accessible_attributes).returns(false) User.expects(:respond_to?).with(:attribute_names).returns(true) User.expects(:attribute_names).twice.returns(["username"]) @@ -160,7 +167,6 @@ class ParamsWrapperTest < ActionController::TestCase def test_derived_wrapped_keys_from_specified_model with_default_wrapper_options do - Person.expects(:respond_to?).with(:accessible_attributes).returns(false) Person.expects(:respond_to?).with(:attribute_names).returns(true) Person.expects(:attribute_names).twice.returns(["username"]) @@ -171,33 +177,8 @@ class ParamsWrapperTest < ActionController::TestCase assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) end end - - def test_accessible_wrapped_keys_from_matching_model - User.expects(:respond_to?).with(:accessible_attributes).returns(true) - User.expects(:accessible_attributes).twice.returns(["username"]) - - with_default_wrapper_options do - @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } - assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu' }}) - end - end - - def test_accessible_wrapped_keys_from_specified_model - with_default_wrapper_options do - Person.expects(:respond_to?).with(:accessible_attributes).returns(true) - Person.expects(:accessible_attributes).twice.returns(["username"]) - - UsersController.wrap_parameters Person - - @request.env['CONTENT_TYPE'] = 'application/json' - post :parse, { 'username' => 'sikachu', 'title' => 'Developer' } - assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'person' => { 'username' => 'sikachu' }}) - end - end def test_not_wrapping_abstract_model - User.expects(:respond_to?).with(:accessible_attributes).returns(false) User.expects(:respond_to?).with(:attribute_names).returns(true) User.expects(:attribute_names).returns([]) diff --git a/actionpack/test/controller/permitted_params_test.rb b/actionpack/test/controller/permitted_params_test.rb new file mode 100644 index 0000000000..f46249d712 --- /dev/null +++ b/actionpack/test/controller/permitted_params_test.rb @@ -0,0 +1,25 @@ +require 'abstract_unit' + +class PeopleController < ActionController::Base + def create + render text: params[:person].permitted? ? "permitted" : "forbidden" + end + + def create_with_permit + render text: params[:person].permit(:name).permitted? ? "permitted" : "forbidden" + end +end + +class ActionControllerPermittedParamsTest < ActionController::TestCase + tests PeopleController + + test "parameters are forbidden" do + post :create, { person: { name: "Mjallo!" } } + assert_equal "forbidden", response.body + end + + test "parameters can be permitted and are then not forbidden" do + post :create_with_permit, { person: { name: "Mjallo!" } } + assert_equal "permitted", response.body + end +end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index b1d76150f8..4331333b98 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -103,6 +103,14 @@ class RedirectController < ActionController::Base redirect_to proc { {:action => "hello_world"} } end + def redirect_with_header_break + redirect_to "/lol\r\nwat" + end + + def redirect_with_null_bytes + redirect_to "\000/lol\r\nwat" + end + def rescue_errors(e) raise e end protected @@ -120,6 +128,18 @@ class RedirectTest < ActionController::TestCase assert_equal "http://test.host/redirect/hello_world", redirect_to_url end + def test_redirect_with_header_break + get :redirect_with_header_break + assert_response :redirect + assert_equal "http://test.host/lolwat", redirect_to_url + end + + def test_redirect_with_null_bytes + get :redirect_with_null_bytes + assert_response :redirect + assert_equal "http://test.host/lolwat", redirect_to_url + end + def test_redirect_with_no_status get :simple_redirect assert_response 302 @@ -242,7 +262,7 @@ class RedirectTest < ActionController::TestCase with_routing do |set| set.draw do resources :workshops - match ':controller/:action' + get ':controller/:action' end get :redirect_to_existing_record @@ -276,7 +296,7 @@ class RedirectTest < ActionController::TestCase def test_redirect_to_with_block_and_accepted_options with_routing do |set| set.draw do - match ':controller/:action' + get ':controller/:action' end get :redirect_to_with_block_and_options diff --git a/actionpack/test/controller/render_json_test.rb b/actionpack/test/controller/render_json_test.rb index 75fed8e933..7c0a6bd67e 100644 --- a/actionpack/test/controller/render_json_test.rb +++ b/actionpack/test/controller/render_json_test.rb @@ -102,7 +102,7 @@ class RenderJsonTest < ActionController::TestCase def test_render_json_with_callback get :render_json_hello_world_with_callback assert_equal 'alert({"hello":"world"})', @response.body - assert_equal 'application/json', @response.content_type + assert_equal 'text/javascript', @response.content_type end def test_render_json_with_custom_content_type diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index e040878b26..fd8f87e377 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -22,6 +22,18 @@ module Quiz end end +class TestControllerWithExtraEtags < ActionController::Base + etag { nil } + etag { 'ab' } + etag { :cde } + etag { [:f] } + etag { nil } + + def fresh + render text: "stale" if stale?(etag: '123') + end +end + class TestController < ActionController::Base protect_from_forgery @@ -102,12 +114,12 @@ class TestController < ActionController::Base end def conditional_hello_with_expires_in_with_public_with_more_keys - expires_in 1.minute, :public => true, 'max-stale' => 5.hours + expires_in 1.minute, :public => true, 's-maxage' => 5.hours render :action => 'hello_world' end def conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax - expires_in 1.minute, :public => true, :private => nil, 'max-stale' => 5.hours + expires_in 1.minute, :public => true, :private => nil, 's-maxage' => 5.hours render :action => 'hello_world' end @@ -116,6 +128,12 @@ class TestController < ActionController::Base render :action => 'hello_world' end + def conditional_hello_with_cache_control_headers + response.headers['Cache-Control'] = 'no-transform' + expires_now + render :action => 'hello_world' + end + def conditional_hello_with_bangs render :action => 'hello_world' end @@ -180,7 +198,7 @@ class TestController < ActionController::Base # :ported: def render_text_hello_world_with_layout - @variable_for_layout = ", I'm here!" + @variable_for_layout = ", I am here!" render :text => "hello world", :layout => true end @@ -505,6 +523,14 @@ class TestController < ActionController::Base render :text => "hello world!" end + def head_created + head :created + end + + def head_created_with_application_json_content_type + head :created, :content_type => "application/json" + end + def head_with_location_header head :location => "/foo" end @@ -553,12 +579,33 @@ class TestController < ActionController::Base render :partial => 'partial' end + def partial_html_erb + render :partial => 'partial_html_erb' + end + def render_to_string_with_partial @partial_only = render_to_string :partial => "partial_only" @partial_with_locals = render_to_string :partial => "customer", :locals => { :customer => Customer.new("david") } render :template => "test/hello_world" end + def render_to_string_with_template_and_html_partial + @text = render_to_string :template => "test/with_partial", :formats => [:text] + @html = render_to_string :template => "test/with_partial", :formats => [:html] + render :template => "test/with_html_partial" + end + + def render_to_string_and_render_with_different_formats + @html = render_to_string :template => "test/with_partial", :formats => [:html] + render :template => "test/with_partial", :formats => [:text] + end + + def render_template_within_a_template_with_other_format + render :template => "test/with_xml_template", + :formats => [:html], + :layout => "with_html_partial" + end + def partial_with_counter render :partial => "counter", :locals => { :counter_counter => 5 } end @@ -695,6 +742,14 @@ class TestController < ActionController::Base end end +class MetalTestController < ActionController::Metal + include ActionController::Rendering + + def accessing_logger_in_template + render :inline => "<%= logger.class %>" + end +end + class RenderTest < ActionController::TestCase tests TestController @@ -801,7 +856,7 @@ class RenderTest < ActionController::TestCase # :ported: def test_do_with_render_text_and_layout get :render_text_hello_world_with_layout - assert_equal "<html>hello world, I'm here!</html>", @response.body + assert_equal "<html>hello world, I am here!</html>", @response.body end # :ported: @@ -1001,6 +1056,7 @@ class RenderTest < ActionController::TestCase def test_accessing_local_assigns_in_inline_template get :accessing_local_assigns_in_inline_template, :local_name => "Local David" assert_equal "Goodbye, Local David", @response.body + assert_equal "text/html", @response.content_type end def test_should_implicitly_render_html_template_from_xhr_request @@ -1155,6 +1211,19 @@ class RenderTest < ActionController::TestCase assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body end + def test_head_created + post :head_created + assert_blank @response.body + assert_response :created + end + + def test_head_created_with_application_json_content_type + post :head_created_with_application_json_content_type + assert_blank @response.body + assert_equal "application/json", @response.content_type + assert_response :created + end + def test_head_with_location_header get :head_with_location_header assert_blank @response.body @@ -1166,7 +1235,7 @@ class RenderTest < ActionController::TestCase with_routing do |set| set.draw do resources :customers - match ':controller/:action' + get ':controller/:action' end get :head_with_location_object @@ -1246,22 +1315,57 @@ class RenderTest < ActionController::TestCase def test_partial_only get :partial_only assert_equal "only partial", @response.body + assert_equal "text/html", @response.content_type end def test_should_render_html_formatted_partial get :partial - assert_equal 'partial html', @response.body + assert_equal "partial html", @response.body + assert_equal "text/html", @response.content_type + end + + def test_render_html_formatted_partial_even_with_other_mime_time_in_accept + @request.accept = "text/javascript, text/html" + + get :partial_html_erb + + assert_equal "partial.html.erb", @response.body.strip + assert_equal "text/html", @response.content_type end def test_should_render_html_partial_with_formats get :partial_formats_html - assert_equal 'partial html', @response.body + assert_equal "partial html", @response.body + assert_equal "text/html", @response.content_type end def test_render_to_string_partial get :render_to_string_with_partial assert_equal "only partial", assigns(:partial_only) assert_equal "Hello: david", assigns(:partial_with_locals) + assert_equal "text/html", @response.content_type + end + + def test_render_to_string_with_template_and_html_partial + get :render_to_string_with_template_and_html_partial + assert_equal "**only partial**\n", assigns(:text) + assert_equal "<strong>only partial</strong>\n", assigns(:html) + assert_equal "<strong>only html partial</strong>\n", @response.body + assert_equal "text/html", @response.content_type + end + + def test_render_to_string_and_render_with_different_formats + get :render_to_string_and_render_with_different_formats + assert_equal "<strong>only partial</strong>\n", assigns(:html) + assert_equal "**only partial**\n", @response.body + assert_equal "text/plain", @response.content_type + end + + def test_render_template_within_a_template_with_other_format + get :render_template_within_a_template_with_other_format + expected = "only html partial<p>This is grand!</p>" + assert_equal expected, @response.body.strip + assert_equal "text/html", @response.content_type end def test_partial_with_counter @@ -1421,12 +1525,12 @@ class ExpiresInRenderTest < ActionController::TestCase def test_expires_in_header_with_additional_headers get :conditional_hello_with_expires_in_with_public_with_more_keys - assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] + assert_equal "max-age=60, public, s-maxage=18000", @response.headers["Cache-Control"] end def test_expires_in_old_syntax get :conditional_hello_with_expires_in_with_public_with_more_keys_old_syntax - assert_equal "max-age=60, public, max-stale=18000", @response.headers["Cache-Control"] + assert_equal "max-age=60, public, s-maxage=18000", @response.headers["Cache-Control"] end def test_expires_now @@ -1434,6 +1538,12 @@ class ExpiresInRenderTest < ActionController::TestCase assert_equal "no-cache", @response.headers["Cache-Control"] end + def test_expires_now_with_cache_control_headers + get :conditional_hello_with_cache_control_headers + assert_match(/no-cache/, @response.headers["Cache-Control"]) + assert_match(/no-transform/, @response.headers["Cache-Control"]) + end + def test_date_header_when_expires_in time = Time.mktime(2011,10,30) Time.stubs(:now).returns(time) @@ -1527,3 +1637,32 @@ class LastModifiedRenderTest < ActionController::TestCase assert_response :success end end + +class EtagRenderTest < ActionController::TestCase + tests TestControllerWithExtraEtags + + def setup + super + @request.host = "www.nextangle.com" + end + + def test_multiple_etags + @request.if_none_match = %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key([ "123", 'ab', :cde, [:f] ]))}") + get :fresh + assert_response :not_modified + + @request.if_none_match = %("nomatch") + get :fresh + assert_response :success + end +end + + +class MetalRenderTest < ActionController::TestCase + tests MetalTestController + + def test_access_to_logger_in_view + get :accessing_logger_in_template + assert_equal "NilClass", @response.body + end +end diff --git a/actionpack/test/controller/render_xml_test.rb b/actionpack/test/controller/render_xml_test.rb index 8b4f2f5349..4f280c4bec 100644 --- a/actionpack/test/controller/render_xml_test.rb +++ b/actionpack/test/controller/render_xml_test.rb @@ -72,7 +72,7 @@ class RenderXmlTest < ActionController::TestCase with_routing do |set| set.draw do resources :customers - match ':controller/:action' + get ':controller/:action' end get :render_with_object_location diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb index 64ed7f667f..1f637eb791 100644 --- a/actionpack/test/controller/request_forgery_protection_test.rb +++ b/actionpack/test/controller/request_forgery_protection_test.rb @@ -9,7 +9,7 @@ module RequestForgeryProtectionActions end def show_button - render :inline => "<%= button_to('New', '/') {} %>" + render :inline => "<%= button_to('New', '/') %>" end def external_form @@ -35,25 +35,39 @@ module RequestForgeryProtectionActions def form_for_without_protection render :inline => "<%= form_for(:some_resource, :authenticity_token => false ) {} %>" end + + def form_for_remote + render :inline => "<%= form_for(:some_resource, :remote => true ) {} %>" + end + + def form_for_remote_with_token + render :inline => "<%= form_for(:some_resource, :remote => true, :authenticity_token => true ) {} %>" + end + + def form_for_with_token + render :inline => "<%= form_for(:some_resource, :authenticity_token => true ) {} %>" + end + + def form_for_remote_with_external_token + render :inline => "<%= form_for(:some_resource, :remote => true, :authenticity_token => 'external_token') {} %>" + end + + def rescue_action(e) raise e end end # sample controllers -class RequestForgeryProtectionController < ActionController::Base +class RequestForgeryProtectionControllerUsingResetSession < ActionController::Base include RequestForgeryProtectionActions - protect_from_forgery :only => %w(index meta) + protect_from_forgery :only => %w(index meta), :with => :reset_session end -class RequestForgeryProtectionControllerUsingOldBehaviour < ActionController::Base +class RequestForgeryProtectionControllerUsingException < ActionController::Base include RequestForgeryProtectionActions - protect_from_forgery :only => %w(index meta) - - def handle_unverified_request - raise(ActionController::InvalidAuthenticityToken) - end + protect_from_forgery :only => %w(index meta), :with => :exception end -class FreeCookieController < RequestForgeryProtectionController +class FreeCookieController < RequestForgeryProtectionControllerUsingResetSession self.allow_forgery_protection = false def index @@ -61,11 +75,11 @@ class FreeCookieController < RequestForgeryProtectionController end def show_button - render :inline => "<%= button_to('New', '/') {} %>" + render :inline => "<%= button_to('New', '/') %>" end end -class CustomAuthenticityParamController < RequestForgeryProtectionController +class CustomAuthenticityParamController < RequestForgeryProtectionControllerUsingResetSession def form_authenticity_param 'foobar' end @@ -98,6 +112,60 @@ module RequestForgeryProtectionTests assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', @token end + def test_should_render_form_without_token_tag_if_remote + assert_not_blocked do + get :form_for_remote + end + assert_no_match(/authenticity_token/, response.body) + end + + def test_should_render_form_with_token_tag_if_remote_and_embedding_token_is_on + original = ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms + begin + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = true + assert_not_blocked do + get :form_for_remote + end + assert_match(/authenticity_token/, response.body) + ensure + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = original + end + end + + def test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested_and_embedding_is_on + original = ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms + begin + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = true + assert_not_blocked do + get :form_for_remote_with_external_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', 'external_token' + ensure + ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms = original + end + end + + def test_should_render_form_with_token_tag_if_remote_and_external_authenticity_token_requested + assert_not_blocked do + get :form_for_remote_with_external_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', 'external_token' + end + + def test_should_render_form_with_token_tag_if_remote_and_authenticity_token_requested + assert_not_blocked do + get :form_for_remote_with_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', @token + end + + def test_should_render_form_with_token_tag_with_authenticity_token_requested + assert_not_blocked do + get :form_for_with_token + end + assert_select 'form>div>input[name=?][value=?]', 'custom_authenticity_token', @token + end + def test_should_allow_get assert_not_blocked { get :index } end @@ -196,7 +264,7 @@ end # OK let's get our test on -class RequestForgeryProtectionControllerTest < ActionController::TestCase +class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController::TestCase include RequestForgeryProtectionTests setup do @@ -215,7 +283,7 @@ class RequestForgeryProtectionControllerTest < ActionController::TestCase end end -class RequestForgeryProtectionControllerUsingOldBehaviourTest < ActionController::TestCase +class RequestForgeryProtectionControllerUsingExceptionTest < ActionController::TestCase include RequestForgeryProtectionTests def assert_blocked assert_raises(ActionController::InvalidAuthenticityToken) do diff --git a/actionpack/test/controller/required_params_test.rb b/actionpack/test/controller/required_params_test.rb new file mode 100644 index 0000000000..661bcb3945 --- /dev/null +++ b/actionpack/test/controller/required_params_test.rb @@ -0,0 +1,30 @@ +require 'abstract_unit' + +class BooksController < ActionController::Base + def create + params.require(:book).require(:name) + head :ok + end +end + +class ActionControllerRequiredParamsTest < ActionController::TestCase + tests BooksController + + test "missing required parameters will raise exception" do + post :create, { magazine: { name: "Mjallo!" } } + assert_response :bad_request + + post :create, { book: { title: "Mjallo!" } } + assert_response :bad_request + end + + test "required parameters that are present will not raise" do + post :create, { book: { name: "Mjallo!" } } + assert_response :ok + end + + test "missing parameters will be mentioned in the return" do + post :create, { magazine: { name: "Mjallo!" } } + assert_equal "Required parameter missing: book", response.body + end +end diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb index 9c51db135b..48e2d6491e 100644 --- a/actionpack/test/controller/rescue_test.rb +++ b/actionpack/test/controller/rescue_test.rb @@ -60,11 +60,6 @@ class RescueController < ActionController::Base render :text => exception.message end - # This is a Dispatcher exception and should be in ApplicationController. - rescue_from ActionController::RoutingError do - render :text => 'no way' - end - rescue_from ActionView::TemplateError do render :text => 'action_view templater error' end @@ -343,9 +338,9 @@ class RescueTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match 'foo', :to => ::RescueTest::TestController.action(:foo) - match 'invalid', :to => ::RescueTest::TestController.action(:invalid) - match 'b00m', :to => ::RescueTest::TestController.action(:b00m) + get 'foo', :to => ::RescueTest::TestController.action(:foo) + get 'invalid', :to => ::RescueTest::TestController.action(:invalid) + get 'b00m', :to => ::RescueTest::TestController.action(:b00m) end yield end diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 3c0a5d36ca..305659b219 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -1,36 +1,6 @@ require 'abstract_unit' require 'active_support/core_ext/object/try' require 'active_support/core_ext/object/with_options' -require 'active_support/core_ext/object/inclusion' - -class ResourcesController < ActionController::Base - def index() render :nothing => true end - alias_method :show, :index -end - -class ThreadsController < ResourcesController; end -class MessagesController < ResourcesController; end -class CommentsController < ResourcesController; end -class AuthorsController < ResourcesController; end -class LogosController < ResourcesController; end - -class AccountsController < ResourcesController; end -class AdminController < ResourcesController; end -class ProductsController < ResourcesController; end -class ImagesController < ResourcesController; end -class PreferencesController < ResourcesController; end - -module Backoffice - class ProductsController < ResourcesController; end - class TagsController < ResourcesController; end - class ManufacturersController < ResourcesController; end - class ImagesController < ResourcesController; end - - module Admin - class ProductsController < ResourcesController; end - class ImagesController < ResourcesController; end - end -end class ResourcesTest < ActionController::TestCase def test_default_restful_routes @@ -109,7 +79,7 @@ class ResourcesTest < ActionController::TestCase expected_options = {:controller => 'messages', :action => 'show', :id => '1.1.1'} with_restful_routing :messages do - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes(expected_options, :path => 'messages/1.1.1', :method => :get) end end @@ -660,15 +630,15 @@ class ResourcesTest < ActionController::TestCase options = { :controller => controller_name.to_s } collection_path = "/#{controller_name}" - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :patch) end - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes(options.merge(:action => 'update'), :path => collection_path, :method => :put) end - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes(options.merge(:action => 'destroy'), :path => collection_path, :method => :delete) end end @@ -680,7 +650,7 @@ class ResourcesTest < ActionController::TestCase scope '/threads/:thread_id' do resources :messages, :as => 'thread_messages' do get :search, :on => :collection - match :preview, :on => :new + get :preview, :on => :new end end end @@ -698,7 +668,7 @@ class ResourcesTest < ActionController::TestCase scope '/admin' do resource :account, :as => :admin_account do get :login, :on => :member - match :preview, :on => :new + get :preview, :on => :new end end end @@ -1308,7 +1278,7 @@ class ResourcesTest < ActionController::TestCase def assert_resource_methods(expected, resource, action_method, method) assert_equal expected.length, resource.send("#{action_method}_methods")[method].size, "#{resource.send("#{action_method}_methods")[method].inspect}" expected.each do |action| - assert action.in?(resource.send("#{action_method}_methods")[method]) + assert resource.send("#{action_method}_methods")[method].include?(action) "#{method} not in #{action_method} methods: #{resource.send("#{action_method}_methods")[method].inspect}" end end @@ -1345,15 +1315,15 @@ class ResourcesTest < ActionController::TestCase options = options.merge(:action => action.to_s) path_options = { :path => path, :method => method } - if action.in?(Array(allowed)) + if Array(allowed).include?(action) assert_recognizes options, path_options - elsif action.in?(Array(not_allowed)) + elsif Array(not_allowed).include?(action) assert_not_recognizes options, path_options end end def assert_not_recognizes(expected_options, path) - assert_raise ActionController::RoutingError, Assertion do + assert_raise Assertion do assert_recognizes(expected_options, path) end end diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb index 807905c7b5..f0430e516f 100644 --- a/actionpack/test/controller/routing_test.rb +++ b/actionpack/test/controller/routing_test.rb @@ -17,7 +17,7 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase def setup @set = ActionDispatch::Routing::RouteSet.new @set.draw do - match ':controller/:action/:variable/*additional' + get ':controller/:action/:variable/*additional' end safe, unsafe = %w(: @ & = + $ , ;), %w(^ ? # [ ]) @@ -59,11 +59,11 @@ end class MockController def self.build(helpers) Class.new do - def url_for(options) + def url_options + options = super options[:protocol] ||= "http" options[:host] ||= "test.host" - - super(options) + options end include helpers @@ -85,7 +85,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_symbols_with_dashes rs.draw do - match '/:artist/:song-omg', :to => lambda { |env| + get '/:artist/:song-omg', :to => lambda { |env| resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] [200, {}, [resp]] } @@ -97,7 +97,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_id_with_dash rs.draw do - match '/journey/:id', :to => lambda { |env| + get '/journey/:id', :to => lambda { |env| resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] [200, {}, [resp]] } @@ -109,7 +109,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_dash_with_custom_regexp rs.draw do - match '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env| + get '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env| resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] [200, {}, [resp]] } @@ -122,7 +122,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_pre_dash rs.draw do - match '/:artist/omg-:song', :to => lambda { |env| + get '/:artist/omg-:song', :to => lambda { |env| resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] [200, {}, [resp]] } @@ -134,7 +134,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_pre_dash_with_custom_regexp rs.draw do - match '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env| + get '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env| resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY] [200, {}, [resp]] } @@ -147,7 +147,32 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_star_paths_are_greedy rs.draw do - match "/(*filters)", :to => lambda { |env| + get "/*path", :to => lambda { |env| + x = env["action_dispatch.request.path_parameters"][:path] + [200, {}, [x]] + }, :format => false + end + + u = URI('http://example.org/foo/bar.html') + assert_equal u.path.sub(/^\//, ''), get(u) + end + + def test_star_paths_are_greedy_but_not_too_much + rs.draw do + get "/*path", :to => lambda { |env| + x = JSON.dump env["action_dispatch.request.path_parameters"] + [200, {}, [x]] + } + end + + expected = { "path" => "foo/bar", "format" => "html" } + u = URI('http://example.org/foo/bar.html') + assert_equal expected, JSON.parse(get(u)) + end + + def test_optional_star_paths_are_greedy + rs.draw do + get "/(*filters)", :to => lambda { |env| x = env["action_dispatch.request.path_parameters"][:filters] [200, {}, [x]] }, :format => false @@ -157,9 +182,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal u.path.sub(/^\//, ''), get(u) end - def test_star_paths_are_greedy_but_not_too_much + def test_optional_star_paths_are_greedy_but_not_too_much rs.draw do - match "/(*filters).:format", :to => lambda { |env| + get "/(*filters)", :to => lambda { |env| x = JSON.dump env["action_dispatch.request.path_parameters"] [200, {}, [x]] } @@ -172,12 +197,12 @@ class LegacyRouteSetTests < ActiveSupport::TestCase end def test_regexp_precidence - @rs.draw do - match '/whois/:domain', :constraints => { + rs.draw do + get '/whois/:domain', :constraints => { :domain => /\w+\.[\w\.]+/ }, :to => lambda { |env| [200, {}, %w{regexp}] } - match '/whois/:id', :to => lambda { |env| [200, {}, %w{id}] } + get '/whois/:id', :to => lambda { |env| [200, {}, %w{id}] } end assert_equal 'regexp', get(URI('http://example.org/whois/example.org')) @@ -191,10 +216,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase end } - @rs.draw do - match '/', :constraints => subdomain.new, + rs.draw do + get '/', :constraints => subdomain.new, :to => lambda { |env| [200, {}, %w{default}] } - match '/', :constraints => { :subdomain => 'clients' }, + get '/', :constraints => { :subdomain => 'clients' }, :to => lambda { |env| [200, {}, %w{clients}] } end @@ -203,12 +228,12 @@ class LegacyRouteSetTests < ActiveSupport::TestCase end def test_lambda_constraints - @rs.draw do - match '/', :constraints => lambda { |req| + rs.draw do + get '/', :constraints => lambda { |req| req.subdomain.present? and req.subdomain != "clients" }, :to => lambda { |env| [200, {}, %w{default}] } - match '/', :constraints => lambda { |req| + get '/', :constraints => lambda { |req| req.subdomain.present? && req.subdomain == "clients" }, :to => lambda { |env| [200, {}, %w{clients}] } end @@ -241,12 +266,22 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_draw_with_block_arity_one_raises assert_raise(RuntimeError) do - @rs.draw { |map| map.match '/:controller(/:action(/:id))' } + rs.draw { |map| map.match '/:controller(/:action(/:id))' } + end + end + + def test_specific_controller_action_failure + rs.draw do + mount lambda {} => "/foo" + end + + assert_raises(ActionController::UrlGenerationError) do + url_for(rs, :controller => "omg", :action => "lol") end end def test_default_setup - @rs.draw { match '/:controller(/:action(/:id))' } + rs.draw { get '/:controller(/:action(/:id))' } assert_equal({:controller => "content", :action => 'index'}, rs.recognize_path("/content")) assert_equal({:controller => "content", :action => 'list'}, rs.recognize_path("/content/list")) assert_equal({:controller => "content", :action => 'show', :id => '10'}, rs.recognize_path("/content/show/10")) @@ -263,22 +298,22 @@ class LegacyRouteSetTests < ActiveSupport::TestCase end def test_ignores_leading_slash - @rs.clear! - @rs.draw { match '/:controller(/:action(/:id))'} + rs.clear! + rs.draw { get '/:controller(/:action(/:id))'} test_default_setup end def test_route_with_colon_first rs.draw do - match '/:controller/:action/:id', :action => 'index', :id => nil - match ':url', :controller => 'tiny_url', :action => 'translate' + get '/:controller/:action/:id', :action => 'index', :id => nil + get ':url', :controller => 'tiny_url', :action => 'translate' end end def test_route_with_regexp_for_controller rs.draw do - match ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/ - match '/:controller(/:action(/:id))' + get ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/ + get '/:controller(/:action(/:id))' end assert_equal({:controller => "admin/user", :admintoken => "foo", :action => "index"}, @@ -292,7 +327,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_route_with_regexp_and_captures_for_controller rs.draw do - match '/:controller(/:action(/:id))', :controller => /admin\/(accounts|users)/ + get '/:controller(/:action(/:id))', :controller => /admin\/(accounts|users)/ end assert_equal({:controller => "admin/accounts", :action => "index"}, rs.recognize_path("/admin/accounts")) assert_equal({:controller => "admin/users", :action => "index"}, rs.recognize_path("/admin/users")) @@ -301,7 +336,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_route_with_regexp_and_dot rs.draw do - match ':controller/:action/:file', + get ':controller/:action/:file', :controller => /admin|user/, :action => /upload|download/, :defaults => {:file => nil}, @@ -331,7 +366,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_with_option rs.draw do - match 'page/:title' => 'content#show_page', :as => 'page' + get 'page/:title' => 'content#show_page', :as => 'page' end assert_equal("http://test.host/page/new%20stuff", @@ -340,7 +375,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_with_default rs.draw do - match 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page' + get 'page/:title' => 'content#show_page', :title => 'AboutPage', :as => 'page' end assert_equal("http://test.host/page/AboutRails", @@ -350,7 +385,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_with_path_prefix rs.draw do scope "my" do - match 'page' => 'content#show_page', :as => 'page' + get 'page' => 'content#show_page', :as => 'page' end end @@ -361,7 +396,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_with_blank_path_prefix rs.draw do scope "" do - match 'page' => 'content#show_page', :as => 'page' + get 'page' => 'content#show_page', :as => 'page' end end @@ -371,7 +406,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_with_nested_controller rs.draw do - match 'admin/user' => 'admin/user#index', :as => "users" + get 'admin/user' => 'admin/user#index', :as => "users" end assert_equal("http://test.host/admin/user", @@ -380,7 +415,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_optimised_named_route_with_host rs.draw do - match 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com' + get 'page' => 'content#show_page', :as => 'pages', :host => 'foo.com' end routes = setup_for_named_route routes.expects(:url_for).with({ @@ -399,7 +434,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_without_hash rs.draw do - match ':controller/:action/:id', :as => 'normal' + get ':controller/:action/:id', :as => 'normal' end end @@ -412,11 +447,20 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal("/", routes.send(:root_path)) end + def test_named_route_root_without_hash + rs.draw do + root "hello#index" + end + routes = setup_for_named_route + assert_equal("http://test.host/", routes.send(:root_url)) + assert_equal("/", routes.send(:root_path)) + end + def test_named_route_with_regexps rs.draw do - match 'page/:year/:month/:day/:title' => 'page#show', :as => 'article', + get 'page/:year/:month/:day/:title' => 'page#show', :as => 'article', :year => /\d+/, :month => /\d+/, :day => /\d+/ - match ':controller/:action/:id' + get ':controller/:action/:id' end routes = setup_for_named_route @@ -426,7 +470,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase end def test_changing_controller - @rs.draw { match ':controller/:action/:id' } + rs.draw { get ':controller/:action/:id' } assert_equal '/admin/stuff/show/10', url_for(rs, {:controller => 'stuff', :action => 'show', :id => 10}, @@ -435,8 +479,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_paths_escaped rs.draw do - match 'file/*path' => 'content#show_file', :as => 'path' - match ':controller/:action/:id' + get 'file/*path' => 'content#show_file', :as => 'path' + get ':controller/:action/:id' end # No + to space in URI escaping, only for query params. @@ -452,7 +496,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_paths_slashes_unescaped_with_ordered_parameters rs.draw do - match '/file/*path' => 'content#index', :as => 'path' + get '/file/*path' => 'content#index', :as => 'path' end # No / to %2F in URI, only for query params. @@ -461,23 +505,23 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_non_controllers_cannot_be_matched rs.draw do - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_raise(ActionController::RoutingError) { rs.recognize_path("/not_a/show/10") } end def test_should_list_options_diff_when_routing_constraints_dont_match rs.draw do - match 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post' + get 'post/:id' => 'post#show', :constraints => { :id => /\d+/ }, :as => 'post' end - assert_raise(ActionController::RoutingError) do + assert_raise(ActionController::UrlGenerationError) do url_for(rs, { :controller => 'post', :action => 'show', :bad_param => "foo", :use_route => "post" }) end end def test_dynamic_path_allowed rs.draw do - match '*path' => 'content#show_file' + get '*path' => 'content#show_file' end assert_equal '/pages/boo', @@ -486,7 +530,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_dynamic_recall_paths_allowed rs.draw do - match '*path' => 'content#show_file' + get '*path' => 'content#show_file' end assert_equal '/pages/boo', @@ -495,8 +539,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_backwards rs.draw do - match 'page/:id(/:action)' => 'pages#show' - match ':controller(/:action(/:id))' + get 'page/:id(/:action)' => 'pages#show' + get ':controller(/:action(/:id))' end assert_equal '/page/20', url_for(rs, { :id => 20 }, { :controller => 'pages', :action => 'show' }) @@ -506,8 +550,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_route_with_fixnum_default rs.draw do - match 'page(/:id)' => 'content#show_page', :id => 1 - match ':controller/:action/:id' + get 'page(/:id)' => 'content#show_page', :id => 1 + get ':controller/:action/:id' end assert_equal '/page', url_for(rs, { :controller => 'content', :action => 'show_page' }) @@ -523,8 +567,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase # For newer revision def test_route_with_text_default rs.draw do - match 'page/:id' => 'content#show_page', :id => 1 - match ':controller/:action/:id' + get 'page/:id' => 'content#show_page', :id => 1 + get ':controller/:action/:id' end assert_equal '/page/foo', url_for(rs, { :controller => 'content', :action => 'show_page', :id => 'foo' }) @@ -539,29 +583,29 @@ class LegacyRouteSetTests < ActiveSupport::TestCase end def test_action_expiry - @rs.draw { match ':controller(/:action(/:id))' } + rs.draw { get ':controller(/:action(/:id))' } assert_equal '/content', url_for(rs, { :controller => 'content' }, { :controller => 'content', :action => 'show' }) end def test_requirement_should_prevent_optional_id rs.draw do - match 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post' + get 'post/:id' => 'post#show', :constraints => {:id => /\d+/}, :as => 'post' end assert_equal '/post/10', url_for(rs, { :controller => 'post', :action => 'show', :id => 10 }) - assert_raise ActionController::RoutingError do + assert_raise(ActionController::UrlGenerationError) do url_for(rs, { :controller => 'post', :action => 'show' }) end end def test_both_requirement_and_optional rs.draw do - match('test(/:year)' => 'post#show', :as => 'blog', + get('test(/:year)' => 'post#show', :as => 'blog', :defaults => { :year => nil }, :constraints => { :year => /\d{4}/ } ) - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_equal '/test', url_for(rs, { :controller => 'post', :action => 'show' }) @@ -572,8 +616,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_set_to_nil_forgets rs.draw do - match 'pages(/:year(/:month(/:day)))' => 'content#list_pages', :month => nil, :day => nil - match ':controller/:action/:id' + get 'pages(/:year(/:month(/:day)))' => 'content#list_pages', :month => nil, :day => nil + get ':controller/:action/:id' end assert_equal '/pages/2005', @@ -615,8 +659,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_named_route_method rs.draw do - match 'categories' => 'content#categories', :as => 'categories' - match ':controller(/:action(/:id))' + get 'categories' => 'content#categories', :as => 'categories' + get ':controller(/:action(/:id))' end assert_equal '/categories', url_for(rs, { :controller => 'content', :action => 'categories' }) @@ -630,9 +674,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_nil_defaults rs.draw do - match 'journal' => 'content#list_journal', + get 'journal' => 'content#list_journal', :date => nil, :user_id => nil - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_equal '/journal', url_for(rs, { @@ -664,7 +708,7 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_recognize_array_of_methods rs.draw do match '/match' => 'books#get_or_post', :via => [:get, :post] - match '/match' => 'books#not_get_or_post' + put '/match' => 'books#not_get_or_post' end params = rs.recognize_path("/match", :method => :post) @@ -676,10 +720,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_subpath_recognized rs.draw do - match '/books/:id/edit' => 'subpath_books#edit' - match '/items/:id/:action' => 'subpath_books' - match '/posts/new/:action' => 'subpath_books' - match '/posts/:id' => 'subpath_books#show' + get '/books/:id/edit' => 'subpath_books#edit' + get '/items/:id/:action' => 'subpath_books' + get '/posts/new/:action' => 'subpath_books' + get '/posts/:id' => 'subpath_books#show' end hash = rs.recognize_path "/books/17/edit" @@ -701,9 +745,9 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_subpath_generated rs.draw do - match '/books/:id/edit' => 'subpath_books#edit' - match '/items/:id/:action' => 'subpath_books' - match '/posts/new/:action' => 'subpath_books' + get '/books/:id/edit' => 'subpath_books#edit' + get '/items/:id/:action' => 'subpath_books' + get '/posts/new/:action' => 'subpath_books' end assert_equal "/books/7/edit", url_for(rs, { :controller => "subpath_books", :id => 7, :action => "edit" }) @@ -713,10 +757,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_failed_constraints_raises_exception_with_violated_constraints rs.draw do - match 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ } + get 'foos/:id' => 'foos#show', :as => 'foo_with_requirement', :constraints => { :id => /\d+/ } end - assert_raise(ActionController::RoutingError) do + assert_raise(ActionController::UrlGenerationError) do setup_for_named_route.send(:foo_with_requirement_url, "I am Against the constraints") end end @@ -724,11 +768,11 @@ class LegacyRouteSetTests < ActiveSupport::TestCase def test_routes_changed_correctly_after_clear rs = ::ActionDispatch::Routing::RouteSet.new rs.draw do - match 'ca' => 'ca#aa' - match 'cb' => 'cb#ab' - match 'cc' => 'cc#ac' - match ':controller/:action/:id' - match ':controller/:action/:id.:format' + get 'ca' => 'ca#aa' + get 'cb' => 'cb#ab' + get 'cc' => 'cc#ac' + get ':controller/:action/:id' + get ':controller/:action/:id.:format' end hash = rs.recognize_path "/cc" @@ -737,10 +781,10 @@ class LegacyRouteSetTests < ActiveSupport::TestCase assert_equal %w(cc ac), [hash[:controller], hash[:action]] rs.draw do - match 'cb' => 'cb#ab' - match 'cc' => 'cc#ac' - match ':controller/:action/:id' - match ':controller/:action/:id.:format' + get 'cb' => 'cb#ab' + get 'cc' => 'cc#ac' + get ':controller/:action/:id' + get ':controller/:action/:id.:format' end hash = rs.recognize_path "/cc" @@ -765,29 +809,29 @@ class RouteSetTest < ActiveSupport::TestCase @default_route_set ||= begin set = ROUTING::RouteSet.new set.draw do - match '/:controller(/:action(/:id))' + get '/:controller(/:action(/:id))' end set end end def test_generate_extras - set.draw { match ':controller/(:action(/:id))' } + set.draw { get ':controller/(:action(/:id))' } path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal "/foo/bar/15", path assert_equal %w(that this), extras.map { |e| e.to_s }.sort end def test_extra_keys - set.draw { match ':controller/:action/:id' } + set.draw { get ':controller/:action/:id' } extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal %w(that this), extras.map { |e| e.to_s }.sort end def test_generate_extras_not_first set.draw do - match ':controller/:action/:id.:format' - match ':controller/:action/:id' + get ':controller/:action/:id.:format' + get ':controller/:action/:id' end path, extras = set.generate_extras(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal "/foo/bar/15", path @@ -796,8 +840,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_not_first set.draw do - match ':controller/:action/:id.:format' - match ':controller/:action/:id' + get ':controller/:action/:id.:format' + get ':controller/:action/:id' end assert_equal "/foo/bar/15?this=hello", url_for(set, { :controller => "foo", :action => "bar", :id => 15, :this => "hello" }) @@ -805,8 +849,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_extra_keys_not_first set.draw do - match ':controller/:action/:id.:format' - match ':controller/:action/:id' + get ':controller/:action/:id.:format' + get ':controller/:action/:id' end extras = set.extra_keys(:controller => "foo", :action => "bar", :id => 15, :this => "hello", :that => "world") assert_equal %w(that this), extras.map { |e| e.to_s }.sort @@ -815,7 +859,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_draw assert_equal 0, set.routes.size set.draw do - match '/hello/world' => 'a#b' + get '/hello/world' => 'a#b' end assert_equal 1, set.routes.size end @@ -823,7 +867,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_draw_symbol_controller_name assert_equal 0, set.routes.size set.draw do - match '/users/index' => 'users#index' + get '/users/index' => 'users#index' end set.recognize_path('/users/index', :method => :get) assert_equal 1, set.routes.size @@ -832,7 +876,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_named_draw assert_equal 0, set.routes.size set.draw do - match '/hello/world' => 'a#b', :as => 'hello' + get '/hello/world' => 'a#b', :as => 'hello' end assert_equal 1, set.routes.size assert_equal set.routes.first, set.named_routes[:hello] @@ -840,40 +884,23 @@ class RouteSetTest < ActiveSupport::TestCase def test_earlier_named_routes_take_precedence set.draw do - match '/hello/world' => 'a#b', :as => 'hello' - match '/hello' => 'a#b', :as => 'hello' + get '/hello/world' => 'a#b', :as => 'hello' + get '/hello' => 'a#b', :as => 'hello' end assert_equal set.routes.first, set.named_routes[:hello] end def setup_named_route_test set.draw do - match '/people(/:id)' => 'people#show', :as => 'show' - match '/people' => 'people#index', :as => 'index' - match '/people/go/:foo/:bar/joe(/:id)' => 'people#multi', :as => 'multi' - match '/admin/users' => 'admin/users#index', :as => "users" + get '/people(/:id)' => 'people#show', :as => 'show' + get '/people' => 'people#index', :as => 'index' + get '/people/go/:foo/:bar/joe(/:id)' => 'people#multi', :as => 'multi' + get '/admin/users' => 'admin/users#index', :as => "users" end MockController.build(set.url_helpers).new end - def test_named_route_hash_access_method - controller = setup_named_route_test - - assert_equal( - { :controller => 'people', :action => 'show', :id => 5, :use_route => "show", :only_path => false }, - controller.send(:hash_for_show_url, :id => 5)) - - assert_equal( - { :controller => 'people', :action => 'index', :use_route => "index", :only_path => false }, - controller.send(:hash_for_index_url)) - - assert_equal( - { :controller => 'people', :action => 'show', :id => 5, :use_route => "show", :only_path => true }, - controller.send(:hash_for_show_path, :id => 5) - ) - end - def test_named_route_url_method controller = setup_named_route_test @@ -885,7 +912,6 @@ class RouteSetTest < ActiveSupport::TestCase assert_equal "http://test.host/admin/users", controller.send(:users_url) assert_equal '/admin/users', controller.send(:users_path) - assert_equal '/admin/users', url_for(set, controller.send(:hash_for_users_url), { :controller => 'users', :action => 'index' }) end def test_named_route_url_method_with_anchor @@ -951,7 +977,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_draw_default_route set.draw do - match '/:controller/:action/:id' + get '/:controller/:action/:id' end assert_equal 1, set.routes.size @@ -965,8 +991,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_with_parameter_shell set.draw do - match 'page/:id' => 'pages#show', :id => /\d+/ - match '/:controller(/:action(/:id))' + get 'page/:id' => 'pages#show', :id => /\d+/ + get '/:controller(/:action(/:id))' end assert_equal({:controller => 'pages', :action => 'index'}, set.recognize_path('/pages')) @@ -980,7 +1006,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_on_request_object_with_anchors_are_valid assert_nothing_raised do set.draw do - match 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ } + get 'page/:id' => 'pages#show', :constraints => { :host => /^foo$/ } end end end @@ -988,27 +1014,27 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_with_anchor_chars_are_invalid assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /^\d+/ + get 'page/:id' => 'pages#show', :id => /^\d+/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\A\d+/ + get 'page/:id' => 'pages#show', :id => /\A\d+/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\d+$/ + get 'page/:id' => 'pages#show', :id => /\d+$/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\d+\Z/ + get 'page/:id' => 'pages#show', :id => /\d+\Z/ end end assert_raise ArgumentError do set.draw do - match 'page/:id' => 'pages#show', :id => /\d+\z/ + get 'page/:id' => 'pages#show', :id => /\d+\z/ end end end @@ -1021,9 +1047,19 @@ class RouteSetTest < ActiveSupport::TestCase end end + def test_route_error_with_missing_controller + set.draw do + get "/people" => "missing#index" + end + + assert_raise(ActionController::RoutingError) { + set.recognize_path("/people", :method => :get) + } + end + def test_recognize_with_encoded_id_and_regex set.draw do - match 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/ + get 'page/:id' => 'pages#show', :id => /[a-zA-Z0-9\+]+/ end assert_equal({:controller => 'pages', :action => 'show', :id => '10'}, set.recognize_path('/page/10')) @@ -1094,7 +1130,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_typo_recognition set.draw do - match 'articles/:year/:month/:day/:title' => 'articles#permalink', + get 'articles/:year/:month/:day/:title' => 'articles#permalink', :year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/ end @@ -1109,7 +1145,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_routing_traversal_does_not_load_extra_classes assert !Object.const_defined?("Profiler__"), "Profiler should not be loaded" set.draw do - match '/profile' => 'profile#index' + get '/profile' => 'profile#index' end set.recognize_path("/profile") rescue nil @@ -1143,8 +1179,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_default_action set.draw do - match "/people", :controller => "people", :action => "index" - match "/people/list", :controller => "people", :action => "list" + get "/people", :controller => "people", :action => "index" + get "/people/list", :controller => "people", :action => "list" end url = url_for(set, { :controller => "people", :action => "list" }) @@ -1163,7 +1199,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do namespace 'api' do - match 'inventory' => 'products#inventory' + get 'inventory' => 'products#inventory' end end @@ -1188,7 +1224,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_namespace_with_path_prefix set.draw do scope :module => "api", :path => "prefix" do - match 'inventory' => 'products#inventory' + get 'inventory' => 'products#inventory' end end @@ -1200,7 +1236,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_namespace_with_blank_path_prefix set.draw do scope :module => "api", :path => "" do - match 'inventory' => 'products#inventory' + get 'inventory' => 'products#inventory' end end @@ -1210,7 +1246,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_generate_changes_controller_module - set.draw { match ':controller/:action/:id' } + set.draw { get ':controller/:action/:id' } current = { :controller => "bling/bloop", :action => "bap", :id => 9 } assert_equal "/foo/bar/baz/7", @@ -1219,7 +1255,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_id_is_sticky_when_it_ought_to_be set.draw do - match ':controller/:id/:action' + get ':controller/:id/:action' end url = url_for(set, { :action => "destroy" }, { :controller => "people", :action => "show", :id => "7" }) @@ -1228,8 +1264,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_use_static_path_when_possible set.draw do - match 'about' => "welcome#about" - match ':controller/:action/:id' + get 'about' => "welcome#about" + get ':controller/:action/:id' end url = url_for(set, { :controller => "welcome", :action => "about" }, @@ -1239,7 +1275,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_generate - set.draw { match ':controller/:action/:id' } + set.draw { get ':controller/:action/:id' } args = { :controller => "foo", :action => "bar", :id => "7", :x => "y" } assert_equal "/foo/bar/7?x=y", url_for(set, args) @@ -1250,7 +1286,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_path_prefix set.draw do scope "my" do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end @@ -1261,7 +1297,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_blank_path_prefix set.draw do scope "" do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end @@ -1271,9 +1307,9 @@ class RouteSetTest < ActiveSupport::TestCase def test_named_routes_are_never_relative_to_modules set.draw do - match "/connection/manage(/:action)" => 'connection/manage#index' - match "/connection/connection" => "connection/connection#index" - match '/connection' => 'connection#index', :as => 'family_connection' + get "/connection/manage(/:action)" => 'connection/manage#index' + get "/connection/connection" => "connection/connection#index" + get '/connection' => 'connection#index', :as => 'family_connection' end url = url_for(set, { :controller => "connection" }, { :controller => 'connection/manage' }) @@ -1285,7 +1321,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_action_left_off_when_id_is_recalled set.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end assert_equal '/books', url_for(set, {:controller => 'books', :action => 'index'}, @@ -1295,8 +1331,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_query_params_will_be_shown_when_recalled set.draw do - match 'show_weblog/:parameter' => 'weblog#show' - match ':controller(/:action(/:id))' + get 'show_weblog/:parameter' => 'weblog#show' + get ':controller(/:action(/:id))' end assert_equal '/weblog/edit?parameter=1', url_for(set, {:action => 'edit', :parameter => 1}, @@ -1306,7 +1342,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_format_is_not_inherit set.draw do - match '/posts(.:format)' => 'posts#index' + get '/posts(.:format)' => 'posts#index' end assert_equal '/posts', url_for(set, @@ -1321,7 +1357,7 @@ class RouteSetTest < ActiveSupport::TestCase end def test_expiry_determination_should_consider_values_with_to_param - set.draw { match 'projects/:project_id/:controller/:action' } + set.draw { get 'projects/:project_id/:controller/:action' } assert_equal '/projects/1/weblog/show', url_for(set, { :action => 'show', :project_id => 1 }, { :controller => 'weblog', :action => 'show', :project_id => '1' }) @@ -1331,7 +1367,7 @@ class RouteSetTest < ActiveSupport::TestCase set.draw do resources :projects do member do - match 'milestones' => 'milestones#index', :as => 'milestones' + get 'milestones' => 'milestones#index', :as => 'milestones' end end end @@ -1364,7 +1400,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_with_unsupported_regexp_options_must_error assert_raise ArgumentError do set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => { :name => /(david|jamis)/m } end end @@ -1373,13 +1409,13 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_constraints_with_supported_options_must_not_error assert_nothing_raised do set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => { :name => /(david|jamis)/i } end end assert_nothing_raised do set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => { :name => / # Desperately overcommented regexp ( #Either david #The Creator @@ -1389,11 +1425,11 @@ class RouteSetTest < ActiveSupport::TestCase end end end - + def test_route_with_subdomain_and_constraints_must_receive_params name_param = nil set.draw do - match 'page/:name' => 'pages#show', :constraints => lambda {|request| + get 'page/:name' => 'pages#show', :constraints => lambda {|request| name_param = request.params[:name] return true } @@ -1402,10 +1438,10 @@ class RouteSetTest < ActiveSupport::TestCase set.recognize_path('http://subdomain.example.org/page/mypage')) assert_equal(name_param, 'mypage') end - + def test_route_requirement_recognize_with_ignore_case set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => /(david|jamis)/i} end assert_equal({:controller => 'pages', :action => 'show', :name => 'jamis'}, set.recognize_path('/page/jamis')) @@ -1417,13 +1453,13 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_requirement_generate_with_ignore_case set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => /(david|jamis)/i} end url = url_for(set, { :controller => 'pages', :action => 'show', :name => 'david' }) assert_equal "/page/david", url - assert_raise ActionController::RoutingError do + assert_raise(ActionController::UrlGenerationError) do url_for(set, { :controller => 'pages', :action => 'show', :name => 'davidjamis' }) end url = url_for(set, { :controller => 'pages', :action => 'show', :name => 'JAMIS' }) @@ -1432,7 +1468,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_requirement_recognize_with_extended_syntax set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => / # Desperately overcommented regexp ( #Either david #The Creator @@ -1452,7 +1488,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_route_requirement_with_xi_modifiers set.draw do - match 'page/:name' => 'pages#show', + get 'page/:name' => 'pages#show', :constraints => {:name => / # Desperately overcommented regexp ( #Either david #The Creator @@ -1470,8 +1506,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_routes_with_symbols set.draw do - match 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol - match 'named' , :controller => :pages, :action => :show, :name => :as_symbol, :as => :named + get 'unnamed', :controller => :pages, :action => :show, :name => :as_symbol + get 'named' , :controller => :pages, :action => :show, :name => :as_symbol, :as => :named end assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/unnamed')) assert_equal({:controller => 'pages', :action => 'show', :name => :as_symbol}, set.recognize_path('/named')) @@ -1479,8 +1515,8 @@ class RouteSetTest < ActiveSupport::TestCase def test_regexp_chunk_should_add_question_mark_for_optionals set.draw do - match '/' => 'foo#index' - match '/hello' => 'bar#index' + get '/' => 'foo#index' + get '/hello' => 'bar#index' end assert_equal '/', url_for(set, { :controller => 'foo' }) @@ -1492,7 +1528,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_assign_route_options_with_anchor_chars set.draw do - match '/cars/:action/:person/:car/', :controller => 'cars' + get '/cars/:action/:person/:car/', :controller => 'cars' end assert_equal '/cars/buy/1/2', url_for(set, { :controller => 'cars', :action => 'buy', :person => '1', :car => '2' }) @@ -1502,7 +1538,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_segmentation_of_dot_path set.draw do - match '/books/:action.rss', :controller => 'books' + get '/books/:action.rss', :controller => 'books' end assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list' }) @@ -1512,7 +1548,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_segmentation_of_dynamic_dot_path set.draw do - match '/books(/:action(.:format))', :controller => 'books' + get '/books(/:action(.:format))', :controller => 'books' end assert_equal '/books/list.rss', url_for(set, { :controller => 'books', :action => 'list', :format => 'rss' }) @@ -1528,7 +1564,7 @@ class RouteSetTest < ActiveSupport::TestCase def test_slashes_are_implied @set = nil - set.draw { match("/:controller(/:action(/:id))") } + set.draw { get("/:controller(/:action(/:id))") } assert_equal '/content', url_for(set, { :controller => 'content', :action => 'index' }) assert_equal '/content/list', url_for(set, { :controller => 'content', :action => 'list' }) @@ -1613,13 +1649,13 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_default_params set.draw do - match 'dummy/page/:page' => 'dummy#show' - match 'dummy/dots/page.:page' => 'dummy#dots' - match 'ibocorp(/:page)' => 'ibocorp#show', + get 'dummy/page/:page' => 'dummy#show' + get 'dummy/dots/page.:page' => 'dummy#dots' + get 'ibocorp(/:page)' => 'ibocorp#show', :constraints => { :page => /\d+/ }, :defaults => { :page => 1 } - match ':controller/:action/:id' + get ':controller/:action/:id' end assert_equal '/ibocorp', url_for(set, { :controller => 'ibocorp', :action => "show", :page => 1 }) @@ -1627,17 +1663,17 @@ class RouteSetTest < ActiveSupport::TestCase def test_generate_with_optional_params_recalls_last_request set.draw do - match "blog/", :controller => "blog", :action => "index" + get "blog/", :controller => "blog", :action => "index" - match "blog(/:year(/:month(/:day)))", + get "blog(/:year(/:month(/:day)))", :controller => "blog", :action => "show_date", :constraints => { :year => /(19|20)\d\d/, :month => /[01]?\d/, :day => /[0-3]?\d/ }, :day => nil, :month => nil - match "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/ - match "blog/:controller/:action(/:id)" - match "*anything", :controller => "blog", :action => "unknown_request" + get "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/ + get "blog/:controller/:action(/:id)" + get "*anything", :controller => "blog", :action => "unknown_request" end assert_equal({:controller => "blog", :action => "index"}, set.recognize_path("/blog")) @@ -1685,7 +1721,7 @@ class RackMountIntegrationTests < ActiveSupport::TestCase root :to => 'users#index' end - match '/blog(/:year(/:month(/:day)))' => 'posts#show_date', + get '/blog(/:year(/:month(/:day)))' => 'posts#show_date', :constraints => { :year => /(19|20)\d\d/, :month => /[01]?\d/, @@ -1694,37 +1730,38 @@ class RackMountIntegrationTests < ActiveSupport::TestCase :day => nil, :month => nil - match 'archive/:year', :controller => 'archive', :action => 'index', + get 'archive/:year', :controller => 'archive', :action => 'index', :defaults => { :year => nil }, :constraints => { :year => /\d{4}/ }, :as => "blog" resources :people - match 'legacy/people' => "people#index", :legacy => "true" + get 'legacy/people' => "people#index", :legacy => "true" - match 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol - match 'id_default(/:id)' => "foo#id_default", :id => 1 + get 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol + get 'id_default(/:id)' => "foo#id_default", :id => 1 match 'get_or_post' => "foo#get_or_post", :via => [:get, :post] - match 'optional/:optional' => "posts#index" - match 'projects/:project_id' => "project#index", :as => "project" - match 'clients' => "projects#index" + get 'optional/:optional' => "posts#index" + get 'projects/:project_id' => "project#index", :as => "project" + get 'clients' => "projects#index" - match 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i - match 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { + get 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i + get 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { :postalcode => /# Postcode format \d{5} #Prefix (-\d{4})? #Suffix /x }, :as => "geocode" - match 'news(.:format)' => "news#index" + get 'news(.:format)' => "news#index" - match 'comment/:id(/:action)' => "comments#show" - match 'ws/:controller(/:action(/:id))', :ws => true - match 'account(/:action)' => "account#subscription" - match 'pages/:page_id/:controller(/:action(/:id))' - match ':controller/ping', :action => 'ping' - match ':controller(/:action(/:id))(.:format)' + get 'comment/:id(/:action)' => "comments#show" + get 'ws/:controller(/:action(/:id))', :ws => true + get 'account(/:action)' => "account#subscription" + get 'pages/:page_id/:controller(/:action(/:id))' + get ':controller/ping', :action => 'ping' + get 'ăăă«ăĄăŻ/äžç', :controller => 'news', :action => 'index' + match ':controller(/:action(/:id))(.:format)', :via => :all root :to => "news#index" } @@ -1840,6 +1877,10 @@ class RackMountIntegrationTests < ActiveSupport::TestCase assert_equal({:controller => 'people', :action => 'create', :person => { :name => 'Josh'}}, params) end + def test_unicode_path + assert_equal({:controller => 'news', :action => 'index'}, @routes.recognize_path(URI.parser.escape('ăăă«ăĄăŻ/äžç'), :method => :get)) + end + private def sort_extras!(extras) if extras.length == 2 diff --git a/actionpack/test/controller/selector_test.rb b/actionpack/test/controller/selector_test.rb index 5e302da212..1e80c8601c 100644 --- a/actionpack/test/controller/selector_test.rb +++ b/actionpack/test/controller/selector_test.rb @@ -5,7 +5,7 @@ require 'abstract_unit' require 'controller/fake_controllers' -require 'action_controller/vendor/html-scanner' +require 'action_view/vendor/html-scanner' class SelectorTest < ActiveSupport::TestCase # diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb index 36884846be..97ede35317 100644 --- a/actionpack/test/controller/send_file_test.rb +++ b/actionpack/test/controller/send_file_test.rb @@ -23,10 +23,6 @@ class SendFileController < ActionController::Base def data send_data(file_data, options) end - - def multibyte_text_data - send_data("ĐĐžŃОлОŃĐ°\nç„æšć„œé.", options) - end end class SendFileTest < ActionController::TestCase @@ -55,14 +51,14 @@ class SendFileTest < ActionController::TestCase response = nil assert_nothing_raised { response = process('file') } assert_not_nil response - assert_respond_to response.body_parts, :each - assert_respond_to response.body_parts, :to_path + assert_respond_to response.stream, :each + assert_respond_to response.stream, :to_path require 'stringio' output = StringIO.new output.binmode output.string.force_encoding(file_data.encoding) - assert_nothing_raised { response.body_parts.each { |part| output << part.to_s } } + response.body_parts.each { |part| output << part.to_s } assert_equal file_data, output.string end @@ -158,6 +154,17 @@ class SendFileTest < ActionController::TestCase end end + def test_send_file_with_default_content_disposition_header + process('data') + assert_equal 'attachment', @controller.headers['Content-Disposition'] + end + + def test_send_file_without_content_disposition_header + @controller.options = {:disposition => nil} + process('data') + assert_nil @controller.headers['Content-Disposition'] + end + %w(file data).each do |method| define_method "test_send_#{method}_status" do @controller.options = { :stream => false, :status => 500 } diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index 13ab19ed8f..351b9c4cfa 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -68,4 +68,29 @@ module ShowExceptions assert_match(/boom/, body) end end + + class ShowExceptionsFormatsTest < ActionDispatch::IntegrationTest + def test_render_json_exception + @app = ShowExceptionsOverridenController.action(:boom) + get "/", {}, 'HTTP_ACCEPT' => 'application/json' + assert_response :internal_server_error + assert_equal 'application/json', response.content_type.to_s + assert_equal({ :status => '500', :error => 'boom!' }.to_json, response.body) + end + + def test_render_xml_exception + @app = ShowExceptionsOverridenController.action(:boom) + get "/", {}, 'HTTP_ACCEPT' => 'application/xml' + assert_response :internal_server_error + assert_equal 'application/xml', response.content_type.to_s + assert_equal({ :status => '500', :error => 'boom!' }.to_xml, response.body) + end + + def test_render_fallback_exception + @app = ShowExceptionsOverridenController.action(:boom) + get "/", {}, 'HTTP_ACCEPT' => 'text/csv' + assert_response :internal_server_error + assert_equal 'text/html', response.content_type.to_s + end + end end diff --git a/actionpack/test/controller/streaming_test.rb b/actionpack/test/controller/streaming_test.rb new file mode 100644 index 0000000000..6ee6444065 --- /dev/null +++ b/actionpack/test/controller/streaming_test.rb @@ -0,0 +1,26 @@ +require 'abstract_unit' + +module ActionController + class StreamingResponseTest < ActionController::TestCase + class TestController < ActionController::Base + def self.controller_path + 'test' + end + + def basic_stream + %w{ hello world }.each do |word| + response.stream.write word + response.stream.write "\n" + end + response.stream.close + end + end + + tests TestController + + def test_write_to_stream + get :basic_stream + assert_equal "hello\nworld\n", @response.body + end + end +end diff --git a/actionpack/test/controller/sweeper_test.rb b/actionpack/test/controller/sweeper_test.rb new file mode 100644 index 0000000000..0561efc62f --- /dev/null +++ b/actionpack/test/controller/sweeper_test.rb @@ -0,0 +1,16 @@ +require 'abstract_unit' + + +class SweeperTest < ActionController::TestCase + + class ::AppSweeper < ActionController::Caching::Sweeper; end + + def test_sweeper_should_not_ignore_unknown_method_calls + sweeper = ActionController::Caching::Sweeper.send(:new) + assert_raise NameError do + sweeper.instance_eval do + some_method_that_doesnt_exist + end + end + end +end diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb index ecba9fed22..8990fc34d6 100644 --- a/actionpack/test/controller/test_case_test.rb +++ b/actionpack/test/controller/test_case_test.rb @@ -45,6 +45,10 @@ class TestCaseTest < ActionController::TestCase render :text => request.fullpath end + def test_format + render :text => request.format + end + def test_query_string render :text => request.query_string end @@ -138,7 +142,7 @@ XML @request.env['PATH_INFO'] = nil @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| r.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end end @@ -193,6 +197,11 @@ XML assert_raise(NoMethodError) { head :test_params, "document body", :id => 10 } end + def test_options + options :test_params + assert_equal 200, @response.status + end + def test_process_without_flash process :set_flash assert_equal '><', flash['test'] @@ -224,6 +233,26 @@ XML assert_equal 'value2', session[:symbol] end + def test_process_merges_session_arg + session[:foo] = 'bar' + get :no_op, nil, { :bar => 'baz' } + assert_equal 'bar', session[:foo] + assert_equal 'baz', session[:bar] + end + + def test_merged_session_arg_is_retained_across_requests + get :no_op, nil, { :foo => 'bar' } + assert_equal 'bar', session[:foo] + get :no_op + assert_equal 'bar', session[:foo] + end + + def test_process_overwrites_existing_session_arg + session[:foo] = 'bar' + get :no_op, nil, { :foo => 'baz' } + assert_equal 'baz', session[:foo] + end + def test_session_is_cleared_from_controller_after_reset_session process :set_session process :reset_the_session @@ -524,7 +553,7 @@ XML with_routing do |set| set.draw do namespace :admin do - match 'user' => 'user#index' + get 'user' => 'user#index' end end @@ -534,7 +563,7 @@ XML def test_assert_routing_with_glob with_routing do |set| - set.draw { match('*path' => "pages#show") } + set.draw { get('*path' => "pages#show") } assert_routing('/company/about', { :controller => 'pages', :action => 'show', :path => 'company/about' }) end end @@ -559,14 +588,34 @@ XML ) end + def test_params_passing_with_fixnums_when_not_html_request + get :test_params, :format => 'json', :count => 999 + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'format' => 'json', 'count' => 999 }, + parsed_params + ) + end + + def test_params_passing_path_parameter_is_string_when_not_html_request + get :test_params, :format => 'json', :id => 1 + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_case_test/test', 'action' => 'test_params', + 'format' => 'json', 'id' => '1' }, + parsed_params + ) + end + def test_params_passing_with_frozen_values assert_nothing_raised do - get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze + get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze, :deepfreeze => { :frozen => 'icy'.freeze }.freeze end parsed_params = eval(@response.body) assert_equal( {'controller' => 'test_case_test/test', 'action' => 'test_params', - 'frozen' => 'icy', 'frozens' => ['icy']}, + 'frozen' => 'icy', 'frozens' => ['icy'], 'deepfreeze' => { 'frozen' => 'icy' }}, parsed_params ) end @@ -585,13 +634,13 @@ XML def test_array_path_parameter_handled_properly with_routing do |set| set.draw do - match 'file/*path', :to => 'test_case_test/test#test_params' - match ':controller/:action' + get 'file/*path', :to => 'test_case_test/test#test_params' + get ':controller/:action' end get :test_params, :path => ['hello', 'world'] assert_equal ['hello', 'world'], @request.path_parameters['path'] - assert_equal 'hello/world', @request.path_parameters['path'].to_s + assert_equal 'hello/world', @request.path_parameters['path'].to_param end end @@ -667,6 +716,20 @@ XML assert_equal "http://", @response.body end + def test_request_format + get :test_format, :format => 'html' + assert_equal 'text/html', @response.body + + get :test_format, :format => 'json' + assert_equal 'application/json', @response.body + + get :test_format, :format => 'xml' + assert_equal 'application/xml', @response.body + + get :test_format + assert_equal 'text/html', @response.body + end + def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set cookies['foo'] = 'bar' get :no_op @@ -755,6 +818,13 @@ XML assert_equal '159528', @response.body end + def test_action_dispatch_uploaded_file_upload + filename = 'mona_lisa.jpg' + path = "#{FILES_DIR}/#{filename}" + post :test_file_upload, :file => ActionDispatch::Http::UploadedFile.new(:filename => path, :type => "image/jpg", :tempfile => File.open(path)) + assert_equal '159528', @response.body + end + def test_test_uploaded_file_exception_when_file_doesnt_exist assert_raise(RuntimeError) { Rack::Test::UploadedFile.new('non_existent_file') } end @@ -828,3 +898,24 @@ class NamedRoutesControllerTest < ActionController::TestCase end end end + +class AnonymousControllerTest < ActionController::TestCase + def setup + @controller = Class.new(ActionController::Base) do + def index + render :text => params[:controller] + end + end.new + + @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| + r.draw do + get ':controller(/:action(/:id))' + end + end + end + + def test_controller_name + get :index + assert_equal 'anonymous', @response.body + end +end diff --git a/actionpack/test/controller/url_for_integration_test.rb b/actionpack/test/controller/url_for_integration_test.rb index 451ea6027d..6c2311e7a5 100644 --- a/actionpack/test/controller/url_for_integration_test.rb +++ b/actionpack/test/controller/url_for_integration_test.rb @@ -18,7 +18,7 @@ module ActionPack root :to => 'users#index' end - match '/blog(/:year(/:month(/:day)))' => 'posts#show_date', + get '/blog(/:year(/:month(/:day)))' => 'posts#show_date', :constraints => { :year => /(19|20)\d\d/, :month => /[01]?\d/, @@ -27,7 +27,7 @@ module ActionPack :day => nil, :month => nil - match 'archive/:year', :controller => 'archive', :action => 'index', + get 'archive/:year', :controller => 'archive', :action => 'index', :defaults => { :year => nil }, :constraints => { :year => /\d{4}/ }, :as => "blog" @@ -35,29 +35,29 @@ module ActionPack resources :people #match 'legacy/people' => "people#index", :legacy => "true" - match 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol - match 'id_default(/:id)' => "foo#id_default", :id => 1 + get 'symbols', :controller => :symbols, :action => :show, :name => :as_symbol + get 'id_default(/:id)' => "foo#id_default", :id => 1 match 'get_or_post' => "foo#get_or_post", :via => [:get, :post] - match 'optional/:optional' => "posts#index" - match 'projects/:project_id' => "project#index", :as => "project" - match 'clients' => "projects#index" + get 'optional/:optional' => "posts#index" + get 'projects/:project_id' => "project#index", :as => "project" + get 'clients' => "projects#index" - match 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i - match 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { + get 'ignorecase/geocode/:postalcode' => 'geocode#show', :postalcode => /hx\d\d-\d[a-z]{2}/i + get 'extended/geocode/:postalcode' => 'geocode#show',:constraints => { :postalcode => /# Postcode format \d{5} #Prefix (-\d{4})? #Suffix /x }, :as => "geocode" - match 'news(.:format)' => "news#index" + get 'news(.:format)' => "news#index" - match 'comment/:id(/:action)' => "comments#show" - match 'ws/:controller(/:action(/:id))', :ws => true - match 'account(/:action)' => "account#subscription" - match 'pages/:page_id/:controller(/:action(/:id))' - match ':controller/ping', :action => 'ping' - match ':controller(/:action(/:id))(.:format)' + get 'comment/:id(/:action)' => "comments#show" + get 'ws/:controller(/:action(/:id))', :ws => true + get 'account(/:action)' => "account#subscription" + get 'pages/:page_id/:controller(/:action(/:id))' + get ':controller/ping', :action => 'ping' + get ':controller(/:action(/:id))(.:format)' root :to => "news#index" } diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index 288efbf7c3..d3fc7128e9 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -3,9 +3,9 @@ require 'abstract_unit' module AbstractController module Testing - class UrlForTests < ActionController::TestCase + class UrlForTest < ActionController::TestCase class W - include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { match ':controller(/:action(/:id(.:format)))' } }.url_helpers + include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { get ':controller(/:action(/:id(.:format)))' } }.url_helpers end def teardown @@ -16,6 +16,10 @@ module AbstractController W.default_url_options[:host] = 'www.basecamphq.com' end + def add_port! + W.default_url_options[:port] = 3000 + end + def add_numeric_host! W.default_url_options[:host] = '127.0.0.1' end @@ -121,6 +125,14 @@ module AbstractController ) end + def test_default_port + add_host! + add_port! + assert_equal('http://www.basecamphq.com:3000/c/a/i', + W.new.url_for(:controller => 'c', :action => 'a', :id => 'i') + ) + end + def test_protocol add_host! assert_equal('https://www.basecamphq.com/c/a/i', @@ -198,8 +210,8 @@ module AbstractController def test_named_routes with_routing do |set| set.draw do - match 'this/is/verbose', :to => 'home#index', :as => :no_args - match 'home/sweet/home/:user', :to => 'home#index', :as => :home + get 'this/is/verbose', :to => 'home#index', :as => :no_args + get 'home/sweet/home/:user', :to => 'home#index', :as => :home end # We need to create a new class in order to install the new named route. @@ -219,7 +231,7 @@ module AbstractController def test_relative_url_root_is_respected_for_named_routes with_routing do |set| set.draw do - match '/home/sweet/home/:user', :to => 'home#index', :as => :home + get '/home/sweet/home/:user', :to => 'home#index', :as => :home end kls = Class.new { include set.url_helpers } @@ -233,8 +245,8 @@ module AbstractController def test_only_path with_routing do |set| set.draw do - match 'home/sweet/home/:user', :to => 'home#index', :as => :home - match ':controller/:action/:id' + get 'home/sweet/home/:user', :to => 'home#index', :as => :home + get ':controller/:action/:id' end # We need to create a new class in order to install the new named route. @@ -301,8 +313,8 @@ module AbstractController def test_named_routes_with_nil_keys with_routing do |set| set.draw do - match 'posts.:format', :to => 'posts#index', :as => :posts - match '/', :to => 'posts#index', :as => :main + get 'posts.:format', :to => 'posts#index', :as => :posts + get '/', :to => 'posts#index', :as => :main end # We need to create a new class in order to install the new named route. diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb index f88903b10e..d9a1ae7d4f 100644 --- a/actionpack/test/controller/url_rewriter_test.rb +++ b/actionpack/test/controller/url_rewriter_test.rb @@ -1,7 +1,7 @@ require 'abstract_unit' require 'controller/fake_controllers' -class UrlRewriterTests < ActionController::TestCase +class UrlRewriterTests < ActiveSupport::TestCase class Rewriter def initialize(request) @options = { @@ -21,7 +21,7 @@ class UrlRewriterTests < ActionController::TestCase @rewriter = Rewriter.new(@request) #.new(@request, @params) @routes = ActionDispatch::Routing::RouteSet.new.tap do |r| r.draw do - match ':controller(/:action(/:id))' + get ':controller(/:action(/:id))' end end end diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb index 351e61eeae..c0b9833603 100644 --- a/actionpack/test/controller/webservice_test.rb +++ b/actionpack/test/controller/webservice_test.rb @@ -254,7 +254,7 @@ class WebServiceTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match '/', :to => 'web_service_test/test#assign_parameters' + match '/', :to => 'web_service_test/test#assign_parameters', :via => :all end yield end diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb index 3e48d97e67..347b3b3b5a 100644 --- a/actionpack/test/dispatch/cookies_test.rb +++ b/actionpack/test/dispatch/cookies_test.rb @@ -38,6 +38,8 @@ class CookiesTest < ActionController::TestCase head :ok end + alias delete_cookie logout + def delete_cookie_with_path cookies.delete("user_name", :path => '/beaten') head :ok @@ -179,6 +181,18 @@ class CookiesTest < ActionController::TestCase assert_equal({"user_name" => "david"}, @response.cookies) end + def test_setting_the_same_value_to_cookie + request.cookies[:user_name] = 'david' + get :authenticate + assert response.cookies.empty? + end + + def test_setting_the_same_value_to_permanent_cookie + request.cookies[:user_name] = 'Jamie' + get :set_permanent_cookie + assert_equal response.cookies, 'user_name' => 'Jamie' + end + def test_setting_with_escapable_characters get :set_with_with_escapable_characters assert_cookie_header "that+%26+guy=foo+%26+bar+%3D%3E+baz; path=/" @@ -235,23 +249,33 @@ class CookiesTest < ActionController::TestCase end def test_expiring_cookie + request.cookies[:user_name] = 'Joe' get :logout assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" assert_equal({"user_name" => nil}, @response.cookies) end def test_delete_cookie_with_path + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_path assert_cookie_header "user_name=; path=/beaten; expires=Thu, 01-Jan-1970 00:00:00 GMT" end + def test_delete_unexisting_cookie + request.cookies.clear + get :delete_cookie + assert @response.cookies.empty? + end + def test_deleted_cookie_predicate + cookies[:user_name] = 'Joe' cookies.delete("user_name") assert cookies.deleted?("user_name") assert_equal false, cookies.deleted?("another") end def test_deleted_cookie_predicate_with_mismatching_options + cookies[:user_name] = 'Joe' cookies.delete("user_name", :path => "/path") assert_equal false, cookies.deleted?("user_name", :path => "/different") end @@ -284,6 +308,7 @@ class CookiesTest < ActionController::TestCase end def test_delete_and_set_cookie + request.cookies[:user_name] = 'Joe' get :delete_and_set_cookie assert_cookie_header "user_name=david; path=/; expires=Mon, 10-Oct-2005 05:00:00 GMT" assert_equal({"user_name" => "david"}, @response.cookies) @@ -387,6 +412,7 @@ class CookiesTest < ActionController::TestCase end def test_deleting_cookie_with_all_domain_option + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domain assert_response :success assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" @@ -413,6 +439,7 @@ class CookiesTest < ActionController::TestCase end def test_deleting_cookie_with_all_domain_option_and_tld_length + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domain_and_tld assert_response :success assert_cookie_header "user_name=; domain=.nextangle.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" @@ -441,6 +468,7 @@ class CookiesTest < ActionController::TestCase def test_deletings_cookie_with_several_preset_domains_using_one_of_these_domains @request.host = "example2.com" + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domains assert_response :success assert_cookie_header "user_name=; domain=example2.com; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" @@ -448,19 +476,19 @@ class CookiesTest < ActionController::TestCase def test_deletings_cookie_with_several_preset_domains_using_other_domain @request.host = "other-domain.com" + request.cookies[:user_name] = 'Joe' get :delete_cookie_with_domains assert_response :success assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT" end - def test_cookies_hash_is_indifferent_access - get :symbol_key - assert_equal "david", cookies[:user_name] - assert_equal "david", cookies['user_name'] - get :string_key - assert_equal "dhh", cookies[:user_name] - assert_equal "dhh", cookies['user_name'] + get :symbol_key + assert_equal "david", cookies[:user_name] + assert_equal "david", cookies['user_name'] + get :string_key + assert_equal "dhh", cookies[:user_name] + assert_equal "dhh", cookies['user_name'] end @@ -575,4 +603,4 @@ class CookiesTest < ActionController::TestCase assert_not_equal expected.split("\n"), header end end -end
\ No newline at end of file +end diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index 11c292d61a..d236b14e02 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -35,6 +35,10 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest raise ActionController::InvalidAuthenticityToken when "/not_found_original_exception" raise ActionView::Template::Error.new('template', AbstractController::ActionNotFound.new) + when "/bad_request" + raise ActionController::BadRequest + when "/missing_keys" + raise ActionController::UrlGenerationError, "No route matches" else raise "puke!" end @@ -88,6 +92,10 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest get "/method_not_allowed", {}, {'action_dispatch.show_exceptions' => true} assert_response 405 assert_match(/ActionController::MethodNotAllowed/, body) + + get "/bad_request", {}, {'action_dispatch.show_exceptions' => true} + assert_response 400 + assert_match(/ActionController::BadRequest/, body) end test "does not show filtered parameters" do @@ -107,6 +115,15 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest assert_match(/AbstractController::ActionNotFound/, body) end + test "named urls missing keys raise 500 level error" do + @app = DevelopmentApp + + get "/missing_keys", {}, {'action_dispatch.show_exceptions' => true} + assert_response 500 + + assert_match(/ActionController::UrlGenerationError/, body) + end + test "show the controller name in the diagnostics template when controller name is present" do @app = DevelopmentApp get("/runtime_error", {}, { diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index ec6ba494dc..bc7cad8db5 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -13,4 +13,9 @@ class HeaderTest < ActiveSupport::TestCase assert_equal "text/plain", @headers["CONTENT_TYPE"] assert_equal "text/plain", @headers["HTTP_CONTENT_TYPE"] end + + test "fetch" do + assert_equal "text/plain", @headers.fetch("content-type", nil) + assert_equal "not found", @headers.fetch('not-found', 'not found') + end end diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb new file mode 100644 index 0000000000..e16f23914b --- /dev/null +++ b/actionpack/test/dispatch/live_response_test.rb @@ -0,0 +1,83 @@ +require 'abstract_unit' +require 'active_support/concurrency/latch' + +module ActionController + module Live + class ResponseTest < ActiveSupport::TestCase + def setup + @response = Live::Response.new + end + + def test_header_merge + header = @response.header.merge('Foo' => 'Bar') + assert_kind_of(ActionController::Live::Response::Header, header) + refute_equal header, @response.header + end + + def test_initialize_with_default_headers + r = Class.new(Live::Response) do + def self.default_headers + { 'omg' => 'g' } + end + end + + header = r.new.header + assert_kind_of(ActionController::Live::Response::Header, header) + end + + def test_parallel + latch = ActiveSupport::Concurrency::Latch.new + + t = Thread.new { + @response.stream.write 'foo' + latch.await + @response.stream.close + } + + @response.each do |part| + assert_equal 'foo', part + latch.release + end + assert t.join + end + + def test_setting_body_populates_buffer + @response.body = 'omg' + @response.close + assert_equal ['omg'], @response.body_parts + end + + def test_cache_control_is_set + @response.stream.write 'omg' + assert_equal 'no-cache', @response.headers['Cache-Control'] + end + + def test_content_length_is_removed + @response.headers['Content-Length'] = "1234" + @response.stream.write 'omg' + assert_nil @response.headers['Content-Length'] + end + + def test_headers_cannot_be_written_after_write + @response.stream.write 'omg' + + assert @response.headers.frozen? + e = assert_raises(ActionDispatch::IllegalStateError) do + @response.headers['Content-Length'] = "zomg" + end + + assert_equal 'header already sent', e.message + end + + def test_headers_cannot_be_written_after_close + @response.stream.close + + assert @response.headers.frozen? + e = assert_raises(ActionDispatch::IllegalStateError) do + @response.headers['Content-Length'] = "zomg" + end + assert_equal 'header already sent', e.message + end + end + end +end diff --git a/actionpack/test/dispatch/mapper_test.rb b/actionpack/test/dispatch/mapper_test.rb index d3465589c1..58457b0c28 100644 --- a/actionpack/test/dispatch/mapper_test.rb +++ b/actionpack/test/dispatch/mapper_test.rb @@ -37,7 +37,7 @@ module ActionDispatch end def test_mapping_requirements - options = { :controller => 'foo', :action => 'bar' } + options = { :controller => 'foo', :action => 'bar', :via => :get } m = Mapper::Mapping.new FakeSet.new, {}, '/store/:name(*rest)', options _, _, requirements, _ = m.to_route assert_equal(/.+?/, requirements[:rest]) @@ -46,7 +46,7 @@ module ActionDispatch def test_map_slash fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/', :to => 'posts#index', :as => :main + mapper.get '/', :to => 'posts#index', :as => :main assert_equal '/', fakeset.conditions.first[:path_info] end @@ -55,14 +55,14 @@ module ActionDispatch mapper = Mapper.new fakeset # FIXME: is this a desired behavior? - mapper.match '/one/two/', :to => 'posts#index', :as => :main + mapper.get '/one/two/', :to => 'posts#index', :as => :main assert_equal '/one/two(.:format)', fakeset.conditions.first[:path_info] end def test_map_wildcard fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path', :to => 'pages#show' + mapper.get '/*path', :to => 'pages#show' assert_equal '/*path(.:format)', fakeset.conditions.first[:path_info] assert_equal(/.+?/, fakeset.requirements.first[:path]) end @@ -70,7 +70,7 @@ module ActionDispatch def test_map_wildcard_with_other_element fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path/foo/:bar', :to => 'pages#show' + mapper.get '/*path/foo/:bar', :to => 'pages#show' assert_equal '/*path/foo/:bar(.:format)', fakeset.conditions.first[:path_info] assert_nil fakeset.requirements.first[:path] end @@ -78,7 +78,7 @@ module ActionDispatch def test_map_wildcard_with_multiple_wildcard fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*foo/*bar', :to => 'pages#show' + mapper.get '/*foo/*bar', :to => 'pages#show' assert_equal '/*foo/*bar(.:format)', fakeset.conditions.first[:path_info] assert_nil fakeset.requirements.first[:foo] assert_equal(/.+?/, fakeset.requirements.first[:bar]) @@ -87,7 +87,7 @@ module ActionDispatch def test_map_wildcard_with_format_false fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path', :to => 'pages#show', :format => false + mapper.get '/*path', :to => 'pages#show', :format => false assert_equal '/*path', fakeset.conditions.first[:path_info] assert_nil fakeset.requirements.first[:path] end @@ -95,9 +95,18 @@ module ActionDispatch def test_map_wildcard_with_format_true fakeset = FakeSet.new mapper = Mapper.new fakeset - mapper.match '/*path', :to => 'pages#show', :format => true + mapper.get '/*path', :to => 'pages#show', :format => true assert_equal '/*path.:format', fakeset.conditions.first[:path_info] end + + def test_raising_helpful_error_on_invalid_arguments + fakeset = FakeSet.new + mapper = Mapper.new fakeset + app = lambda { |env| [200, {}, [""]] } + assert_raises ArgumentError do + mapper.mount app + end + end end end end diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb index 4191ed1ff4..948a690979 100644 --- a/actionpack/test/dispatch/middleware_stack_test.rb +++ b/actionpack/test/dispatch/middleware_stack_test.rb @@ -45,7 +45,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BazMiddleware, @stack.last.klass assert_equal([true, {:foo => "bar"}], @stack.last.args) end - + test "use should push middleware class with block arguments onto the stack" do proc = Proc.new {} assert_difference "@stack.size" do @@ -54,7 +54,7 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal BlockMiddleware, @stack.last.klass assert_equal proc, @stack.last.block end - + test "insert inserts middleware at the integer index" do @stack.insert(1, BazMiddleware) assert_equal BazMiddleware, @stack[1].klass @@ -87,6 +87,11 @@ class MiddlewareStackTest < ActiveSupport::TestCase assert_equal FooMiddleware, @stack[0].klass end + test "unshift adds a new middleware at the beginning of the stack" do + @stack.unshift :"MiddlewareStackTest::BazMiddleware" + assert_equal BazMiddleware, @stack.first.klass + end + test "raise an error on invalid index" do assert_raise RuntimeError do @stack.insert("HiyaMiddleware", BazMiddleware) diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb index 0372c42920..3e83f3d4fa 100644 --- a/actionpack/test/dispatch/mime_type_test.rb +++ b/actionpack/test/dispatch/mime_type_test.rb @@ -75,6 +75,12 @@ class MimeTypeTest < ActiveSupport::TestCase assert_equal expect, Mime::Type.parse(accept) end + test "parse arbitarry media type parameters" do + accept = 'multipart/form-data; boundary="simple boundary"' + expect = [Mime::MULTIPART_FORM] + assert_equal expect, Mime::Type.parse(accept) + end + # Accept header send with user HTTP_USER_AGENT: Sunrise/0.42j (Windows XP) test "parse broken acceptlines" do accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/*,,*/*;q=0.5" @@ -86,7 +92,7 @@ class MimeTypeTest < ActiveSupport::TestCase # (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; InfoPath.1) test "parse other broken acceptlines" do accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, , pronto/1.00.00, sslvpn/1.00.00.00, */*" - expect = ['image/gif', 'image/x-xbitmap', 'image/jpeg','image/pjpeg', 'application/x-shockwave-flash', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/msword', 'pronto/1.00.00', 'sslvpn/1.00.00.00', Mime::ALL ] + expect = ['image/gif', 'image/x-xbitmap', 'image/jpeg','image/pjpeg', 'application/x-shockwave-flash', 'application/vnd.ms-excel', 'application/vnd.ms-powerpoint', 'application/msword', 'pronto/1.00.00', 'sslvpn/1.00.00.00', Mime::ALL] assert_equal expect, Mime::Type.parse(accept).collect { |c| c.to_s } end @@ -112,6 +118,20 @@ class MimeTypeTest < ActiveSupport::TestCase end end + test "register callbacks" do + begin + registered_mimes = [] + Mime::Type.register_callback do |mime| + registered_mimes << mime + end + + Mime::Type.register("text/foo", :foo) + assert_equal registered_mimes, [Mime::FOO] + ensure + Mime::Type.unregister(:FOO) + end + end + test "custom type with extension aliases" do begin Mime::Type.register "text/foobar", :foobar, [], [:foo, "bar"] @@ -142,11 +162,11 @@ class MimeTypeTest < ActiveSupport::TestCase types = Mime::SET.symbols.uniq - [:all, :iphone] # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE - types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) } + types.delete_if { |type| !Mime.const_defined?(type.upcase) } types.each do |type| - mime = Mime.const_get(type.to_s.upcase) + mime = Mime.const_get(type.upcase) assert mime.respond_to?("#{type}?"), "#{mime.inspect} does not respond to #{type}?" assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?" invalid_types = types - [type] @@ -164,10 +184,10 @@ class MimeTypeTest < ActiveSupport::TestCase all_types = Mime::SET.symbols all_types.uniq! # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE - all_types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) } + all_types.delete_if { |type| !Mime.const_defined?(type.upcase) } verified, unverified = all_types.partition { |type| Mime::Type.browser_generated_types.include? type } - assert verified.each { |type| assert Mime.const_get(type.to_s.upcase).verify_request?, "Verifiable Mime Type is not verified: #{type.inspect}" } - assert unverified.each { |type| assert !Mime.const_get(type.to_s.upcase).verify_request?, "Nonverifiable Mime Type is verified: #{type.inspect}" } + assert verified.each { |type| assert Mime.const_get(type.upcase).verify_request?, "Verifiable Mime Type is not verified: #{type.inspect}" } + assert unverified.each { |type| assert !Mime.const_get(type.upcase).verify_request?, "Nonverifiable Mime Type is verified: #{type.inspect}" } end test "references gives preference to symbols before strings" do diff --git a/actionpack/test/dispatch/mount_test.rb b/actionpack/test/dispatch/mount_test.rb index f7a746120e..3b008fdff0 100644 --- a/actionpack/test/dispatch/mount_test.rb +++ b/actionpack/test/dispatch/mount_test.rb @@ -22,6 +22,7 @@ class TestRoutingMount < ActionDispatch::IntegrationTest mount SprocketsApp => "/shorthand" mount FakeEngine, :at => "/fakeengine" + mount FakeEngine, :at => "/getfake", :via => :get scope "/its_a" do mount SprocketsApp, :at => "/sprocket" @@ -37,6 +38,11 @@ class TestRoutingMount < ActionDispatch::IntegrationTest assert_equal "/sprockets -- /omg", response.body end + def test_mounting_works_with_nested_script_name + get "/foo/sprockets/omg", {}, 'SCRIPT_NAME' => '/foo', 'PATH_INFO' => '/sprockets/omg' + assert_equal "/foo/sprockets -- /omg", response.body + end + def test_mounting_works_with_scope get "/its_a/sprocket/omg" assert_equal "/its_a/sprocket -- /omg", response.body @@ -47,6 +53,14 @@ class TestRoutingMount < ActionDispatch::IntegrationTest assert_equal "/shorthand -- /omg", response.body end + def test_mounting_works_with_via + get "/getfake" + assert_equal "OK", response.body + + post "/getfake" + assert_response :not_found + end + def test_with_fake_engine_does_not_call_invalid_method get "/fakeengine" assert_equal "OK", response.body diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb index bd5b5edab0..cfbf970a37 100644 --- a/actionpack/test/dispatch/prefix_generation_test.rb +++ b/actionpack/test/dispatch/prefix_generation_test.rb @@ -25,12 +25,12 @@ module TestGenerationPrefix @routes ||= begin routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/posts/:id", :to => "inside_engine_generating#show", :as => :post - match "/posts", :to => "inside_engine_generating#index", :as => :posts - match "/url_to_application", :to => "inside_engine_generating#url_to_application" - match "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" - match "/conflicting_url", :to => "inside_engine_generating#conflicting" - match "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test + get "/posts/:id", :to => "inside_engine_generating#show", :as => :post + get "/posts", :to => "inside_engine_generating#index", :as => :posts + get "/url_to_application", :to => "inside_engine_generating#url_to_application" + get "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine" + get "/conflicting_url", :to => "inside_engine_generating#conflicting" + get "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test end routes @@ -51,12 +51,13 @@ module TestGenerationPrefix scope "/:omg", :omg => "awesome" do mount BlogEngine => "/blog", :as => "blog_engine" end - match "/posts/:id", :to => "outside_engine_generating#post", :as => :post - match "/generate", :to => "outside_engine_generating#index" - match "/polymorphic_path_for_app", :to => "outside_engine_generating#polymorphic_path_for_app" - match "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine" - match "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for" - match "/conflicting_url", :to => "outside_engine_generating#conflicting" + get "/posts/:id", :to => "outside_engine_generating#post", :as => :post + get "/generate", :to => "outside_engine_generating#index" + get "/polymorphic_path_for_app", :to => "outside_engine_generating#polymorphic_path_for_app" + get "/polymorphic_path_for_engine", :to => "outside_engine_generating#polymorphic_path_for_engine" + get "/polymorphic_with_url_for", :to => "outside_engine_generating#polymorphic_with_url_for" + get "/conflicting_url", :to => "outside_engine_generating#conflicting" + get "/ivar_usage", :to => "outside_engine_generating#ivar_usage" root :to => "outside_engine_generating#index" end @@ -125,6 +126,11 @@ module TestGenerationPrefix def conflicting render :text => "application" end + + def ivar_usage + @blog_engine = "Not the engine route helper" + render :text => blog_engine.post_path(:id => 1) + end end class EngineObject @@ -166,18 +172,6 @@ module TestGenerationPrefix assert_equal "/generate", last_response.body end - test "[ENGINE] generating application's url includes default_url_options[:script_name]" do - RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/pure-awesomeness/blog/url_to_application" - assert_equal "/something/generate", last_response.body - end - - test "[ENGINE] generating application's url should give higher priority to default_url_options[:script_name]" do - RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/pure-awesomeness/blog/url_to_application", {}, 'SCRIPT_NAME' => '/foo' - assert_equal "/something/generate", last_response.body - end - test "[ENGINE] generating engine's url with polymorphic path" do get "/pure-awesomeness/blog/polymorphic_path_for_engine" assert_equal "/pure-awesomeness/blog/posts/1", last_response.body @@ -200,12 +194,6 @@ module TestGenerationPrefix assert_equal "/something/awesome/blog/posts/1", last_response.body end - test "[APP] generating engine's route should give higher priority to default_url_options[:script_name]" do - RailsApplication.routes.default_url_options = {:script_name => "/something"} - get "/generate", {}, 'SCRIPT_NAME' => "/foo" - assert_equal "/something/awesome/blog/posts/1", last_response.body - end - test "[APP] generating engine's url with polymorphic path" do get "/polymorphic_path_for_engine" assert_equal "/awesome/blog/posts/1", last_response.body @@ -221,6 +209,11 @@ module TestGenerationPrefix assert_equal "http://example.org/awesome/blog/posts/1", last_response.body end + test "[APP] instance variable with same name as engine" do + get "/ivar_usage" + assert_equal "/awesome/blog/posts/1", last_response.body + end + # Inside any Object test "[OBJECT] proxy route should override respond_to?() as expected" do assert_respond_to blog_engine, :named_helper_that_should_be_invoked_only_in_respond_to_test_path @@ -282,7 +275,7 @@ module TestGenerationPrefix @routes ||= begin routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/posts/:id", :to => "posts#show", :as => :post + get "/posts/:id", :to => "posts#show", :as => :post end routes diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb index ae425dd406..302bff0696 100644 --- a/actionpack/test/dispatch/request/json_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb @@ -65,7 +65,7 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::JsonParamsParsingTest::TestController + post ':action', :to => ::JsonParamsParsingTest::TestController end yield end @@ -118,7 +118,7 @@ class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing(controller) with_routing do |set| set.draw do - match ':action', :to => controller + post ':action', :to => controller end yield end diff --git a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb index d144f013f5..63c5ea26a6 100644 --- a/actionpack/test/dispatch/request/multipart_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/multipart_params_parsing_test.rb @@ -144,7 +144,7 @@ class MultipartParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => 'multipart_params_parsing_test/test' + post ':action', :to => 'multipart_params_parsing_test/test' end yield end diff --git a/actionpack/test/dispatch/request/query_string_parsing_test.rb b/actionpack/test/dispatch/request/query_string_parsing_test.rb index f6a1475d04..3cb430d83d 100644 --- a/actionpack/test/dispatch/request/query_string_parsing_test.rb +++ b/actionpack/test/dispatch/request/query_string_parsing_test.rb @@ -81,7 +81,16 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest end test "query string without equal" do - assert_parses({ "action" => nil }, "action") + assert_parses({"action" => nil}, "action") + assert_parses({"action" => {"foo" => nil}}, "action[foo]") + assert_parses({"action" => {"foo" => { "bar" => nil }}}, "action[foo][bar]") + assert_parses({"action" => {"foo" => { "bar" => [] }}}, "action[foo][bar][]") + assert_parses({"action" => {"foo" => []}}, "action[foo][]") + assert_parses({"action"=>{"foo"=>[{"bar"=>nil}]}}, "action[foo][][bar]") + end + + def test_array_parses_without_nil + assert_parses({"action" => ['1']}, "action[]=1&action[]") end test "query string with empty key" do @@ -105,11 +114,22 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest ) end + test "ambiguous query string returns a bad request" do + with_routing do |set| + set.draw do + get ':action', :to => ::QueryStringParsingTest::TestController + end + + get "/parse", nil, "QUERY_STRING" => "foo[]=bar&foo[4]=bar" + assert_response :bad_request + end + end + private def assert_parses(expected, actual) with_routing do |set| set.draw do - match ':action', :to => ::QueryStringParsingTest::TestController + get ':action', :to => ::QueryStringParsingTest::TestController end get "/parse", actual diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb new file mode 100644 index 0000000000..3f36d4f1a9 --- /dev/null +++ b/actionpack/test/dispatch/request/session_test.rb @@ -0,0 +1,73 @@ +require 'abstract_unit' +require 'action_dispatch/middleware/session/abstract_store' + +module ActionDispatch + class Request + class SessionTest < ActiveSupport::TestCase + def test_create_adds_itself_to_env + env = {} + s = Session.create(store, env, {}) + assert_equal s, env[Rack::Session::Abstract::ENV_SESSION_KEY] + end + + def test_to_hash + env = {} + s = Session.create(store, env, {}) + s['foo'] = 'bar' + assert_equal 'bar', s['foo'] + assert_equal({'foo' => 'bar'}, s.to_hash) + end + + def test_create_merges_old + env = {} + s = Session.create(store, env, {}) + s['foo'] = 'bar' + + s1 = Session.create(store, env, {}) + refute_equal s, s1 + assert_equal 'bar', s1['foo'] + end + + def test_find + env = {} + assert_nil Session.find(env) + + s = Session.create(store, env, {}) + assert_equal s, Session.find(env) + end + + def test_keys + env = {} + s = Session.create(store, env, {}) + s['rails'] = 'ftw' + s['adequate'] = 'awesome' + assert_equal %w[rails adequate], s.keys + end + + def test_values + env = {} + s = Session.create(store, env, {}) + s['rails'] = 'ftw' + s['adequate'] = 'awesome' + assert_equal %w[ftw awesome], s.values + end + + def test_clear + env = {} + s = Session.create(store, env, {}) + s['rails'] = 'ftw' + s['adequate'] = 'awesome' + s.clear + assert_equal([], s.values) + end + + private + def store + Class.new { + def load_session(env); [1, {}]; end + def session_exists?(env); true; end + }.new + end + end + end +end diff --git a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb index 05569561d2..e9b59f55a7 100644 --- a/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb @@ -126,11 +126,22 @@ class UrlEncodedParamsParsingTest < ActionDispatch::IntegrationTest assert_parses expected, query end + test "ambiguous params returns a bad request" do + with_routing do |set| + set.draw do + post ':action', :to => ::UrlEncodedParamsParsingTest::TestController + end + + post "/parse", "foo[]=bar&foo[4]=bar" + assert_response :bad_request + end + end + private def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::UrlEncodedParamsParsingTest::TestController + post ':action', :to => ::UrlEncodedParamsParsingTest::TestController end yield end diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb index afd400c2a9..84823e2896 100644 --- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb +++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb @@ -106,7 +106,7 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::XmlParamsParsingTest::TestController + post ':action', :to => ::XmlParamsParsingTest::TestController end yield end @@ -155,7 +155,7 @@ class RootLessXmlParamsParsingTest < ActionDispatch::IntegrationTest def with_test_routing with_routing do |set| set.draw do - match ':action', :to => ::RootLessXmlParamsParsingTest::TestController + post ':action', :to => ::RootLessXmlParamsParsingTest::TestController end yield end diff --git a/actionpack/test/dispatch/request_id_test.rb b/actionpack/test/dispatch/request_id_test.rb index 4b98cd32f2..a8050b4fab 100644 --- a/actionpack/test/dispatch/request_id_test.rb +++ b/actionpack/test/dispatch/request_id_test.rb @@ -52,7 +52,7 @@ class RequestIdResponseTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match '/', :to => ::RequestIdResponseTest::TestController.action(:index) + get '/', :to => ::RequestIdResponseTest::TestController.action(:index) end @app = self.class.build_app(set) do |middleware| @@ -62,4 +62,4 @@ class RequestIdResponseTest < ActionDispatch::IntegrationTest yield end end -end
\ No newline at end of file +end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index 6c8b22c47f..a2b9571660 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -35,37 +35,40 @@ class RequestTest < ActiveSupport::TestCase assert_equal '1.2.3.4', request.remote_ip request = stub_request 'REMOTE_ADDR' => '1.2.3.4', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'REMOTE_ADDR' => '127.0.0.1', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,unknown' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '172.16.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '127.0.0.1,3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1' - assert_equal 'unknown', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 172.31.4.4' assert_equal '3.4.5.6', request.remote_ip + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address' + assert_equal nil, request.remote_ip + request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1', 'HTTP_CLIENT_IP' => '2.2.2.2' e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) { @@ -89,6 +92,68 @@ class RequestTest < ActiveSupport::TestCase assert_equal '9.9.9.9', request.remote_ip end + test "remote ip v6" do + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => '::1', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1, ::1, fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,::1' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, fc00::' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', + 'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334' + e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) { + request.remote_ip + } + assert_match(/IP spoofing attack/, e.message) + assert_match(/HTTP_X_FORWARDED_FOR="fe80:0000:0000:0000:0202:b3ff:fe1e:8329"/, e.message) + assert_match(/HTTP_CLIENT_IP="2001:0db8:85a3:0000:0000:8a2e:0370:7334"/, e.message) + + # Turn IP Spoofing detection off. + # This is useful for sites that are aimed at non-IP clients. The typical + # example is WAP. Since the cellular network is not IP based, it's a + # leap of faith to assume that their proxies are ever going to set the + # HTTP_CLIENT_IP/HTTP_X_FORWARDED_FOR headers properly. + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', + 'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + :ip_spoofing_check => false + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + end + test "remote ip when the remote ip middleware returns nil" do request = stub_request 'REMOTE_ADDR' => '127.0.0.1' assert_equal '127.0.0.1', request.remote_ip @@ -97,29 +162,47 @@ class RequestTest < ActiveSupport::TestCase test "remote ip with user specified trusted proxies String" do @trusted_proxies = "67.205.106.73" - request = stub_request 'REMOTE_ADDR' => '67.205.106.73', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + request = stub_request 'REMOTE_ADDR' => '3.4.5.6', + 'HTTP_X_FORWARDED_FOR' => '67.205.106.73' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'REMOTE_ADDR' => '172.16.0.1,67.205.106.73', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip + 'HTTP_X_FORWARDED_FOR' => '67.205.106.73' + assert_equal '172.16.0.1', request.remote_ip - request = stub_request 'REMOTE_ADDR' => '67.205.106.73,172.16.0.1', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' - assert_equal '3.4.5.6', request.remote_ip - - request = stub_request 'REMOTE_ADDR' => '67.205.106.74,172.16.0.1', - 'HTTP_X_FORWARDED_FOR' => '3.4.5.6' + request = stub_request 'REMOTE_ADDR' => '67.205.106.73,3.4.5.6', + 'HTTP_X_FORWARDED_FOR' => '67.205.106.73' assert_equal '3.4.5.6', request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,67.205.106.73' - assert_equal 'unknown', request.remote_ip + assert_equal nil, request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 67.205.106.73' assert_equal '3.4.5.6', request.remote_ip end + test "remote ip v6 with user specified trusted proxies String" do + @trusted_proxies = 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal nil, request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal nil, request.remote_ip + end + test "remote ip with user specified trusted proxies Regexp" do @trusted_proxies = /^67\.205\.106\.73$/i @@ -128,7 +211,18 @@ class RequestTest < ActiveSupport::TestCase assert_equal '3.4.5.6', request.remote_ip request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73, 10.0.0.1, 9.9.9.9, 3.4.5.6' - assert_equal '10.0.0.1', request.remote_ip + assert_equal nil, request.remote_ip + end + + test "remote ip v6 with user specified trusted proxies Regexp" do + @trusted_proxies = /^fe80:0000:0000:0000:0202:b3ff:fe1e:8329$/i + + request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334', + 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329' + assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip + + request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334' + assert_equal nil, request.remote_ip end test "domains" do @@ -367,14 +461,6 @@ class RequestTest < ActiveSupport::TestCase end end - test "head masquerading as get" do - request = stub_request 'REQUEST_METHOD' => 'GET', "rack.methodoverride.original_method" => "HEAD" - assert_equal "HEAD", request.method - assert_equal "GET", request.request_method - assert request.get? - assert request.head? - end - test "post masquerading as patch" do request = stub_request 'REQUEST_METHOD' => 'PATCH', "rack.methodoverride.original_method" => "POST" assert_equal "POST", request.method @@ -467,7 +553,7 @@ class RequestTest < ActiveSupport::TestCase begin request = stub_request(mock_rack_env) request.parameters - rescue TypeError + rescue ActionController::BadRequest # rack will raise a TypeError when parsing this query string end assert_equal({}, request.parameters) @@ -660,6 +746,45 @@ class RequestTest < ActiveSupport::TestCase assert_equal "/foo?bar", path end + test "if_none_match_etags none" do + request = stub_request + + assert_equal nil, request.if_none_match + assert_equal [], request.if_none_match_etags + assert !request.etag_matches?("foo") + assert !request.etag_matches?(nil) + end + + test "if_none_match_etags single" do + header = 'the-etag' + request = stub_request('HTTP_IF_NONE_MATCH' => header) + + assert_equal header, request.if_none_match + assert_equal [header], request.if_none_match_etags + assert request.etag_matches?("the-etag") + end + + test "if_none_match_etags quoted single" do + header = '"the-etag"' + request = stub_request('HTTP_IF_NONE_MATCH' => header) + + assert_equal header, request.if_none_match + assert_equal ['the-etag'], request.if_none_match_etags + assert request.etag_matches?("the-etag") + end + + test "if_none_match_etags multiple" do + header = 'etag1, etag2, "third etag", "etag4"' + expected = ['etag1', 'etag2', 'third etag', 'etag4'] + request = stub_request('HTTP_IF_NONE_MATCH' => header) + + assert_equal header, request.if_none_match + assert_equal expected, request.if_none_match_etags + expected.each do |etag| + assert request.etag_matches?(etag), etag + end + end + protected def stub_request(env = {}) diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index 82d1200f8e..185a9e9b18 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -5,6 +5,35 @@ class ResponseTest < ActiveSupport::TestCase @response = ActionDispatch::Response.new end + def test_can_wait_until_commit + t = Thread.new { + @response.await_commit + } + @response.commit! + assert @response.committed? + assert t.join(0.5) + end + + def test_stream_close + @response.stream.close + assert @response.stream.closed? + end + + def test_stream_write + @response.stream.write "foo" + @response.stream.close + assert_equal "foo", @response.body + end + + def test_write_after_close + @response.stream.close + + e = assert_raises(IOError) do + @response.stream.write "omg" + end + assert_equal "closed stream", e.message + end + def test_response_body_encoding body = ["hello".encode('utf-8')] response = ActionDispatch::Response.new 200, {}, body @@ -147,6 +176,42 @@ class ResponseTest < ActiveSupport::TestCase ActionDispatch::Response.default_charset = original end end + + test "read x_frame_options, x_content_type_options and x_xss_protection" do + begin + ActionDispatch::Response.default_headers = { + 'X-Frame-Options' => 'DENY', + 'X-Content-Type-Options' => 'nosniff', + 'X-XSS-Protection' => '1;' + } + resp = ActionDispatch::Response.new.tap { |response| + response.body = 'Hello' + } + resp.to_a + + assert_equal('DENY', resp.headers['X-Frame-Options']) + assert_equal('nosniff', resp.headers['X-Content-Type-Options']) + assert_equal('1;', resp.headers['X-XSS-Protection']) + ensure + ActionDispatch::Response.default_headers = nil + end + end + + test "read custom default_header" do + begin + ActionDispatch::Response.default_headers = { + 'X-XX-XXXX' => 'Here is my phone number' + } + resp = ActionDispatch::Response.new.tap { |response| + response.body = 'Hello' + } + resp.to_a + + assert_equal('Here is my phone number', resp.headers['X-XX-XXXX']) + ensure + ActionDispatch::Response.default_headers = nil + end + end end class ResponseIntegrationTest < ActionDispatch::IntegrationTest diff --git a/actionpack/test/dispatch/routing/concerns_test.rb b/actionpack/test/dispatch/routing/concerns_test.rb new file mode 100644 index 0000000000..9f37701656 --- /dev/null +++ b/actionpack/test/dispatch/routing/concerns_test.rb @@ -0,0 +1,119 @@ +require 'abstract_unit' + +class RoutingConcernsTest < ActionDispatch::IntegrationTest + class Reviewable + def self.call(mapper, options = {}) + mapper.resources :reviews, options + end + end + + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + concern :commentable do |options| + resources :comments, options + end + + concern :image_attachable do + resources :images, only: :index + end + + concern :reviewable, Reviewable + + resources :posts, concerns: [:commentable, :image_attachable, :reviewable] do + resource :video, concerns: :commentable do + concerns :reviewable, as: :video_reviews + end + end + + resource :picture, concerns: :commentable do + resources :posts, concerns: :commentable + end + + scope "/videos" do + concerns :commentable, except: :destroy + end + end + end + + include Routes.url_helpers + def app; Routes end + + def test_accessing_concern_from_resources + get "/posts/1/comments" + assert_equal "200", @response.code + assert_equal "/posts/1/comments", post_comments_path(post_id: 1) + end + + def test_accessing_concern_from_resource + get "/picture/comments" + assert_equal "200", @response.code + assert_equal "/picture/comments", picture_comments_path + end + + def test_accessing_concern_from_nested_resource + get "/posts/1/video/comments" + assert_equal "200", @response.code + assert_equal "/posts/1/video/comments", post_video_comments_path(post_id: 1) + end + + def test_accessing_concern_from_nested_resources + get "/picture/posts/1/comments" + assert_equal "200", @response.code + assert_equal "/picture/posts/1/comments", picture_post_comments_path(post_id: 1) + end + + def test_accessing_concern_from_resources_with_more_than_one_concern + get "/posts/1/images" + assert_equal "200", @response.code + assert_equal "/posts/1/images", post_images_path(post_id: 1) + end + + def test_accessing_concern_from_resources_using_only_option + get "/posts/1/image/1" + assert_equal "404", @response.code + end + + def test_accessing_callable_concern_ + get "/posts/1/reviews/1" + assert_equal "200", @response.code + assert_equal "/posts/1/reviews/1", post_review_path(post_id: 1, id: 1) + end + + def test_callable_concerns_accept_options + get "/posts/1/video/reviews/1" + assert_equal "200", @response.code + assert_equal "/posts/1/video/reviews/1", post_video_video_review_path(post_id: 1, id: 1) + end + + def test_accessing_concern_from_a_scope + get "/videos/comments" + assert_equal "200", @response.code + end + + def test_concerns_accept_options + delete "/videos/comments/1" + assert_equal "404", @response.code + end + + def test_with_an_invalid_concern_name + e = assert_raise ArgumentError do + ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + resources :posts, concerns: :foo + end + end + end + + assert_equal "No concern named foo was found!", e.message + end + + def test_concerns_executes_block_in_context_of_current_mapper + mapper = ActionDispatch::Routing::Mapper.new(ActionDispatch::Routing::RouteSet.new) + mapper.concern :test_concern do + resources :things + return self + end + + assert_equal mapper, mapper.concerns(:test_concern) + end +end diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb new file mode 100644 index 0000000000..97fc4f3e4b --- /dev/null +++ b/actionpack/test/dispatch/routing/inspector_test.rb @@ -0,0 +1,170 @@ +require 'minitest/autorun' +require 'action_controller' +require 'rails/engine' +require 'action_dispatch/routing/inspector' + +module ActionDispatch + module Routing + class RoutesInspectorTest < ActiveSupport::TestCase + def setup + @set = ActionDispatch::Routing::RouteSet.new + @inspector = ActionDispatch::Routing::RoutesInspector.new + app = ActiveSupport::OrderedOptions.new + app.config = ActiveSupport::OrderedOptions.new + app.config.assets = ActiveSupport::OrderedOptions.new + app.config.assets.prefix = '/sprockets' + Rails.stubs(:application).returns(app) + Rails.stubs(:env).returns("development") + end + + def draw(&block) + @set.draw(&block) + @inspector.format(@set.routes) + end + + def test_displaying_routes_for_engines + engine = Class.new(Rails::Engine) do + def self.to_s + "Blog::Engine" + end + end + engine.routes.draw do + get '/cart', :to => 'cart#show' + end + + output = draw do + get '/custom/assets', :to => 'custom_assets#show' + mount engine => "/blog", :as => "blog" + end + + expected = [ + "custom_assets GET /custom/assets(.:format) custom_assets#show", + " blog /blog Blog::Engine", + "\nRoutes for Blog::Engine:", + "cart GET /cart(.:format) cart#show" + ] + assert_equal expected, output + end + + def test_cart_inspect + output = draw do + get '/cart', :to => 'cart#show' + end + assert_equal ["cart GET /cart(.:format) cart#show"], output + end + + def test_inspect_shows_custom_assets + output = draw do + get '/custom/assets', :to => 'custom_assets#show' + end + assert_equal ["custom_assets GET /custom/assets(.:format) custom_assets#show"], output + end + + def test_inspect_routes_shows_resources_route + output = draw do + resources :articles + end + expected = [ + " articles GET /articles(.:format) articles#index", + " POST /articles(.:format) articles#create", + " new_article GET /articles/new(.:format) articles#new", + "edit_article GET /articles/:id/edit(.:format) articles#edit", + " article GET /articles/:id(.:format) articles#show", + " PATCH /articles/:id(.:format) articles#update", + " PUT /articles/:id(.:format) articles#update", + " DELETE /articles/:id(.:format) articles#destroy" ] + assert_equal expected, output + end + + def test_inspect_routes_shows_root_route + output = draw do + root :to => 'pages#main' + end + assert_equal ["root GET / pages#main"], output + end + + def test_inspect_routes_shows_dynamic_action_route + output = draw do + get 'api/:action' => 'api' + end + assert_equal [" GET /api/:action(.:format) api#:action"], output + end + + def test_inspect_routes_shows_controller_and_action_only_route + output = draw do + get ':controller/:action' + end + assert_equal [" GET /:controller/:action(.:format) :controller#:action"], output + end + + def test_inspect_routes_shows_controller_and_action_route_with_constraints + output = draw do + get ':controller(/:action(/:id))', :id => /\d+/ + end + assert_equal [" GET /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}"], output + end + + def test_rake_routes_shows_route_with_defaults + output = draw do + get 'photos/:id' => 'photos#show', :defaults => {:format => 'jpg'} + end + assert_equal [%Q[ GET /photos/:id(.:format) photos#show {:format=>"jpg"}]], output + end + + def test_rake_routes_shows_route_with_constraints + output = draw do + get 'photos/:id' => 'photos#show', :id => /[A-Z]\d{5}/ + end + assert_equal [" GET /photos/:id(.:format) photos#show {:id=>/[A-Z]\\d{5}/}"], output + end + + class RackApp + def self.call(env) + end + end + + def test_rake_routes_shows_route_with_rack_app + output = draw do + get 'foo/:id' => RackApp, :id => /[A-Z]\d{5}/ + end + assert_equal [" GET /foo/:id(.:format) #{RackApp.name} {:id=>/[A-Z]\\d{5}/}"], output + end + + def test_rake_routes_shows_route_with_rack_app_nested_with_dynamic_constraints + constraint = Class.new do + def to_s + "( my custom constraint )" + end + end + + output = draw do + scope :constraint => constraint.new do + mount RackApp => '/foo' + end + end + + assert_equal [" /foo #{RackApp.name} {:constraint=>( my custom constraint )}"], output + end + + def test_rake_routes_dont_show_app_mounted_in_assets_prefix + output = draw do + get '/sprockets' => RackApp + end + assert_no_match(/RackApp/, output.first) + assert_no_match(/\/sprockets/, output.first) + end + + def test_redirect + output = draw do + get "/foo" => redirect("/foo/bar"), :constraints => { :subdomain => "admin" } + get "/bar" => redirect(path: "/foo/bar", status: 307) + get "/foobar" => redirect{ "/foo/bar" } + end + + assert_equal " foo GET /foo(.:format) redirect(301, /foo/bar) {:subdomain=>\"admin\"}", output[0] + assert_equal " bar GET /bar(.:format) redirect(307, path: /foo/bar)", output[1] + assert_equal "foobar GET /foobar(.:format) redirect(301)", output[2] + end + end + end +end diff --git a/actionpack/test/dispatch/routing_assertions_test.rb b/actionpack/test/dispatch/routing_assertions_test.rb index 9f95d82129..aea4489852 100644 --- a/actionpack/test/dispatch/routing_assertions_test.rb +++ b/actionpack/test/dispatch/routing_assertions_test.rb @@ -3,6 +3,7 @@ require 'controller/fake_controllers' class SecureArticlesController < ArticlesController; end class BlockArticlesController < ArticlesController; end +class QueryArticlesController < ArticlesController; end class RoutingAssertionsTest < ActionController::TestCase @@ -18,6 +19,10 @@ class RoutingAssertionsTest < ActionController::TestCase scope 'block', :constraints => lambda { |r| r.ssl? } do resources :articles, :controller => 'block_articles' end + + scope 'query', :constraints => lambda { |r| r.params[:use_query] == 'true' } do + resources :articles, :controller => 'query_articles' + end end end @@ -42,26 +47,33 @@ class RoutingAssertionsTest < ActionController::TestCase def test_assert_recognizes_with_extras assert_recognizes({ :controller => 'articles', :action => 'index', :page => '1' }, '/articles', { :page => '1' }) end - + def test_assert_recognizes_with_method assert_recognizes({ :controller => 'articles', :action => 'create' }, { :path => '/articles', :method => :post }) assert_recognizes({ :controller => 'articles', :action => 'update', :id => '1' }, { :path => '/articles/1', :method => :put }) end def test_assert_recognizes_with_hash_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'http://test.host/secure/articles') end - assert_recognizes({ :controller => 'secure_articles', :action => 'index' }, 'https://test.host/secure/articles') + assert_recognizes({ :controller => 'secure_articles', :action => 'index', :protocol => 'https://' }, 'https://test.host/secure/articles') end def test_assert_recognizes_with_block_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_recognizes({ :controller => 'block_articles', :action => 'index' }, 'http://test.host/block/articles') end assert_recognizes({ :controller => 'block_articles', :action => 'index' }, 'https://test.host/block/articles') end + def test_assert_recognizes_with_query_constraint + assert_raise(Assertion) do + assert_recognizes({ :controller => 'query_articles', :action => 'index', :use_query => 'false' }, '/query/articles', { :use_query => 'false' }) + end + assert_recognizes({ :controller => 'query_articles', :action => 'index', :use_query => 'true' }, '/query/articles', { :use_query => 'true' }) + end + def test_assert_routing assert_routing('/articles', :controller => 'articles', :action => 'index') end @@ -75,14 +87,14 @@ class RoutingAssertionsTest < ActionController::TestCase end def test_assert_routing_with_hash_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_routing('http://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' }) end - assert_routing('https://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index' }) + assert_routing('https://test.host/secure/articles', { :controller => 'secure_articles', :action => 'index', :protocol => 'https://' }) end def test_assert_routing_with_block_constraint - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_routing('http://test.host/block/articles', { :controller => 'block_articles', :action => 'index' }) end assert_routing('https://test.host/block/articles', { :controller => 'block_articles', :action => 'index' }) @@ -95,7 +107,7 @@ class RoutingAssertionsTest < ActionController::TestCase end assert_routing('/artikel', :controller => 'articles', :action => 'index') - assert_raise(ActionController::RoutingError) do + assert_raise(Assertion) do assert_routing('/articles', { :controller => 'articles', :action => 'index' }) end end diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index e8da790e50..4e83ad16d7 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -2,7 +2,6 @@ require 'erb' require 'abstract_unit' require 'controller/fake_controllers' -require 'active_support/core_ext/object/inclusion' class TestRoutingMapper < ActionDispatch::IntegrationTest SprocketsApp = lambda { |env| @@ -58,41 +57,46 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "remove", :action => :destroy, :as => :remove end - match 'account/logout' => redirect("/logout"), :as => :logout_redirect - match 'account/login', :to => redirect("/login") - match 'secure', :to => redirect("/secure/login") + get 'account/logout' => redirect("/logout"), :as => :logout_redirect + get 'account/login', :to => redirect("/login") + get 'secure', :to => redirect("/secure/login") - match 'mobile', :to => redirect(:subdomain => 'mobile') - match 'super_new_documentation', :to => redirect(:host => 'super-docs.com') + get 'mobile', :to => redirect(:subdomain => 'mobile') + get 'documentation', :to => redirect(:domain => 'example-documentation.com', :path => '') + get 'new_documentation', :to => redirect(:path => '/documentation/new') + get 'super_new_documentation', :to => redirect(:host => 'super-docs.com') - match 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector) + get 'stores/:name', :to => redirect(:subdomain => 'stores', :path => '/%{name}') + get 'stores/:name(*rest)', :to => redirect(:subdomain => 'stores', :path => '/%{name}%{rest}') + + get 'youtube_favorites/:youtube_id/:name', :to => redirect(YoutubeFavoritesRedirector) constraints(lambda { |req| true }) do - match 'account/overview' + get 'account/overview' end - match '/account/nested/overview' - match 'sign_in' => "sessions#new" + get '/account/nested/overview' + get 'sign_in' => "sessions#new" - match 'account/modulo/:name', :to => redirect("/%{name}s") - match 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" } - match 'account/proc_req' => redirect {|params, req| "/#{req.method}" } + get 'account/modulo/:name', :to => redirect("/%{name}s") + get 'account/proc/:name', :to => redirect {|params, req| "/#{params[:name].pluralize}" } + get 'account/proc_req' => redirect {|params, req| "/#{req.method}" } - match 'account/google' => redirect('http://www.google.com/', :status => 302) + get 'account/google' => redirect('http://www.google.com/', :status => 302) match 'openid/login', :via => [:get, :post], :to => "openid#login" controller(:global) do get 'global/hide_notice' - match 'global/export', :to => :export, :as => :export_request - match '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ } - match 'global/:action' + get 'global/export', :to => :export, :as => :export_request + get '/export/:id/:file', :to => :export, :as => :export_download, :constraints => { :file => /.*/ } + get 'global/:action' end - match "/local/:action", :controller => "local" + get "/local/:action", :controller => "local" - match "/projects/status(.:format)" - match "/404", :to => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["NOT FOUND"]] } + get "/projects/status(.:format)" + get "/404", :to => lambda { |env| [404, {"Content-Type" => "text/plain"}, ["NOT FOUND"]] } constraints(:ip => /192\.168\.1\.\d\d\d/) do get 'admin' => "queenbee#index" @@ -166,6 +170,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post :preview, :on => :collection end end + + post 'new', :action => 'new', :on => :collection, :as => :new end resources :replies do @@ -277,25 +283,25 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - match 'sprockets.js' => ::TestRoutingMapper::SprocketsApp + get 'sprockets.js' => ::TestRoutingMapper::SprocketsApp - match 'people/:id/update', :to => 'people#update', :as => :update_person - match '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person + get 'people/:id/update', :to => 'people#update', :as => :update_person + get '/projects/:project_id/people/:id/update', :to => 'people#update', :as => :update_project_person # misc - match 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article + get 'articles/:year/:month/:day/:title', :to => "articles#show", :as => :article # default params - match 'inline_pages/(:id)', :to => 'pages#show', :id => 'home' - match 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' } + get 'inline_pages/(:id)', :to => 'pages#show', :id => 'home' + get 'default_pages/(:id)', :to => 'pages#show', :defaults => { :id => 'home' } defaults :id => 'home' do - match 'scoped_pages/(:id)', :to => 'pages#show' + get 'scoped_pages/(:id)', :to => 'pages#show' end namespace :account do - match 'shorthand' - match 'description', :to => :description, :as => "description" - match ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback + get 'shorthand' + get 'description', :to => :description, :as => "description" + get ':action/callback', :action => /twitter|github/, :to => "callbacks", :as => :callback resource :subscription, :credit, :credit_card root :to => "account#index" @@ -318,7 +324,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest controller :articles do scope '/articles', :as => 'article' do scope :path => '/:title', :title => /[a-z]+/, :as => :with_title do - match '/:id', :to => :with_id, :as => "" + get '/:id', :to => :with_id, :as => "" end end end @@ -327,7 +333,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :rooms end - match '/info' => 'projects#info', :as => 'info' + get '/info' => 'projects#info', :as => 'info' namespace :admin do scope '(:locale)', :locale => /en|pl/ do @@ -357,11 +363,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :errors, :shallow => true do resources :notices end + get 'api/version' end scope :path => 'api' do resource :me - match '/' => 'mes#index' + get '/' => 'mes#index' end get "(/:username)/followers" => "followers#index" @@ -374,7 +381,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest end end - match "whatever/:controller(/:action(/:id))", :id => /\d+/ + get "whatever/:controller(/:action(/:id))", :id => /\d+/ resource :profile do get :settings @@ -407,7 +414,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest namespace :private do root :to => redirect('/private/index') - match "index", :to => 'private#index' + get "index", :to => 'private#index' end scope :only => [:index, :show] do @@ -475,6 +482,17 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get :preview, :on => :member end + resources :profiles, :param => :username, :username => /[a-z]+/ do + get :details, :on => :member + resources :messages + end + + resources :orders do + constraints :download => /[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}/ do + resources :downloads, :param => :download, :shallow => true + end + end + scope :as => "routes" do get "/c/:id", :as => :collision, :to => "collision#show" get "/collision", :to => "collision#show" @@ -484,7 +502,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get "/forced_collision", :as => :forced_collision, :to => "forced_collision#show" end - match '/purchases/:token/:filename', + get '/purchases/:token/:filename', :to => 'purchases#fetch', :token => /[[:alnum:]]{10}/, :filename => /(.+)/, @@ -494,19 +512,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest resources :todos, :id => /\d+/ end - scope '/countries/:country', :constraints => lambda { |params, req| params[:country].in?(["all", "France"]) } do - match '/', :to => 'countries#index' - match '/cities', :to => 'countries#cities' + scope '/countries/:country', :constraints => lambda { |params, req| %w(all France).include?(params[:country]) } do + get '/', :to => 'countries#index' + get '/cities', :to => 'countries#cities' end - match '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' } + get '/countries/:country/(*other)', :to => redirect{ |params, req| params[:other] ? "/countries/all/#{params[:other]}" : '/countries/all' } - match '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/ + get '/:locale/*file.:format', :to => 'files#show', :file => /path\/to\/existing\/file/ scope '/italians' do - match '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor - match '/sculptors', :to => 'italians#sculptors' - match '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/} + get '/writers', :to => 'italians#writers', :constraints => ::TestRoutingMapper::IpRestrictor + get '/sculptors', :to => 'italians#sculptors' + get '/painters/:painter', :to => 'italians#painters', :constraints => {:painter => /michelangelo/} end end end @@ -622,7 +640,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest self.class.stub_controllers do |routes| routes.draw do namespace :admin do - match '/:controller(/:action(/:id(.:format)))' + get '/:controller(/:action(/:id(.:format)))' end end end @@ -688,11 +706,31 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest verify_redirect 'http://mobile.example.com/mobile' end + def test_redirect_hash_with_domain_and_path + get '/documentation' + verify_redirect 'http://www.example-documentation.com' + end + + def test_redirect_hash_with_path + get '/new_documentation' + verify_redirect 'http://www.example.com/documentation/new' + end + def test_redirect_hash_with_host get '/super_new_documentation?section=top' verify_redirect 'http://super-docs.com/super_new_documentation?section=top' end + def test_redirect_hash_path_substitution + get '/stores/iernest' + verify_redirect 'http://stores.example.com/iernest' + end + + def test_redirect_hash_path_substitution_with_catch_all + get '/stores/iernest/products' + verify_redirect 'http://stores.example.com/iernest/products' + end + def test_redirect_class get '/youtube_favorites/oHg5SJYRHA0/rick-rolld' verify_redirect 'http://www.youtube.com/watch?v=oHg5SJYRHA0' @@ -797,6 +835,15 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal original_options, options end + def test_url_for_does_not_modify_controller + controller = '/projects' + options = {:controller => controller, :action => 'status', :only_path => true} + url = url_for(options) + + assert_equal '/projects/status', url + assert_equal '/projects', controller + end + # tests the arguments modification free version of define_hash_access def test_named_route_with_no_side_effects original_options = { :host => 'test.host' } @@ -846,6 +893,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal '/projects/1/edit', edit_project_path(:id => '1') end + def test_projects_with_post_action_and_new_path_on_collection + post '/projects/new' + assert_equal "project#new", @response.body + assert_equal "/projects/new", new_projects_path + end + def test_projects_involvements get '/projects/1/involvements' assert_equal 'involvements#index', @response.body @@ -1026,6 +1079,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'pasts#destroy', @response.body assert_equal '/past', past_path + patch '/present' + assert_equal 'presents#update', @response.body + assert_equal '/present', present_path + put '/present' assert_equal 'presents#update', @response.body assert_equal '/present', present_path @@ -1044,6 +1101,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'relationships#destroy', @response.body assert_equal '/relationships/1', relationship_path(1) + patch '/friendships/1' + assert_equal 'friendships#update', @response.body + assert_equal '/friendships/1', friendship_path(1) + put '/friendships/1' assert_equal 'friendships#update', @response.body assert_equal '/friendships/1', friendship_path(1) @@ -1220,6 +1281,12 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal 'account#shorthand', @response.body end + def test_match_shorthand_with_module + assert_equal '/api/version', api_version_path + get '/api/version' + assert_equal 'api/api#version', @response.body + end + def test_dynamically_generated_helpers_on_collection_do_not_clobber_resources_url_helper assert_equal '/replies', replies_path end @@ -1739,7 +1806,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/movies/00001' assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_path(:id => '00001') } + assert_raises(ActionController::UrlGenerationError){ movie_path(:id => '00001') } get '/movies/0001/reviews' assert_equal 'reviews#index', @response.body @@ -1747,7 +1814,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/movies/00001/reviews' assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_reviews_path(:movie_id => '00001') } + assert_raises(ActionController::UrlGenerationError){ movie_reviews_path(:movie_id => '00001') } get '/movies/0001/reviews/0001' assert_equal 'reviews#show', @response.body @@ -1755,7 +1822,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/movies/00001/reviews/0001' assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_path(:movie_id => '00001', :id => '00001') } + assert_raises(ActionController::UrlGenerationError){ movie_path(:movie_id => '00001', :id => '00001') } get '/movies/0001/trailer' assert_equal 'trailers#show', @response.body @@ -1763,7 +1830,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/movies/00001/trailer' assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ movie_trailer_path(:movie_id => '00001') } + assert_raises(ActionController::UrlGenerationError){ movie_trailer_path(:movie_id => '00001') } end def test_only_should_be_read_from_scope @@ -2082,7 +2149,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/lists/2/todos/1' assert_equal 'Not Found', @response.body - assert_raises(ActionController::RoutingError){ list_todo_path(:list_id => '2', :id => '1') } + assert_raises(ActionController::UrlGenerationError){ list_todo_path(:list_id => '2', :id => '1') } end def test_named_routes_collision_is_avoided_unless_explicitly_given_as @@ -2175,6 +2242,36 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest assert_equal "/posts/1/admin", post_admin_root_path(:post_id => '1') end + def test_custom_param + get '/profiles/bob' + assert_equal 'profiles#show', @response.body + assert_equal 'bob', @request.params[:username] + + get '/profiles/bob/details' + assert_equal 'bob', @request.params[:username] + + get '/profiles/bob/messages/34' + assert_equal 'bob', @request.params[:profile_username] + assert_equal '34', @request.params[:id] + end + + def test_custom_param_constraint + get '/profiles/bob1' + assert_equal 404, @response.status + + get '/profiles/bob1/details' + assert_equal 404, @response.status + + get '/profiles/bob1/messages/34' + assert_equal 404, @response.status + end + + def test_shallow_custom_param + get '/downloads/0c0c0b68-d24b-11e1-a861-001ff3fffe6f.zip' + assert_equal 'downloads#show', @response.body + assert_equal '0c0c0b68-d24b-11e1-a861-001ff3fffe6f', @request.params[:download] + end + private def with_https old_https = https? @@ -2205,12 +2302,12 @@ class TestAppendingRoutes < ActionDispatch::IntegrationTest s = self @app = ActionDispatch::Routing::RouteSet.new @app.append do - match '/hello' => s.simple_app('fail') - match '/goodbye' => s.simple_app('goodbye') + get '/hello' => s.simple_app('fail') + get '/goodbye' => s.simple_app('goodbye') end @app.draw do - match '/hello' => s.simple_app('hello') + get '/hello' => s.simple_app('hello') end end @@ -2318,12 +2415,12 @@ end class TestUriPathEscaping < ActionDispatch::IntegrationTest Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| app.draw do - match '/:segment' => lambda { |env| + get '/:segment' => lambda { |env| path_params = env['action_dispatch.request.path_parameters'] [200, { 'Content-Type' => 'text/plain' }, [path_params[:segment]]] }, :as => :segment - match '/*splat' => lambda { |env| + get '/*splat' => lambda { |env| path_params = env['action_dispatch.request.path_parameters'] [200, { 'Content-Type' => 'text/plain' }, [path_params[:splat]]] }, :as => :splat @@ -2355,7 +2452,7 @@ end class TestUnicodePaths < ActionDispatch::IntegrationTest Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| app.draw do - match "/#{Rack::Utils.escape("ă»ă")}" => lambda { |env| + get "/ă»ă" => lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] }, :as => :unicode_path end @@ -2385,10 +2482,10 @@ class TestMultipleNestedController < ActionDispatch::IntegrationTest app.draw do namespace :foo do namespace :bar do - match "baz" => "baz#index" + get "baz" => "baz#index" end end - match "pooh" => "pooh#index" + get "pooh" => "pooh#index" end end @@ -2399,18 +2496,15 @@ class TestMultipleNestedController < ActionDispatch::IntegrationTest get "/foo/bar/baz" assert_equal "/pooh", @response.body end - end class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| app.draw do - match "/~user" => lambda { |env| - [200, { 'Content-Type' => 'text/plain' }, []] - }, :as => :tilde_path - match "/young-and-fine" => lambda { |env| - [200, { 'Content-Type' => 'text/plain' }, []] - }, :as => :tilde_path + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get "/~user" => ok + get "/young-and-fine" => ok end end @@ -2428,3 +2522,216 @@ class TestTildeAndMinusPaths < ActionDispatch::IntegrationTest end end + +class TestRedirectInterpolation < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get "/foo/:id" => redirect("/foo/bar/%{id}") + get "/bar/:id" => redirect(:path => "/foo/bar/%{id}") + get "/foo/bar/:id" => ok + end + end + + def app; Routes end + + test "redirect escapes interpolated parameters with redirect proc" do + get "/foo/1%3E" + verify_redirect "http://www.example.com/foo/bar/1%3E" + end + + test "redirect escapes interpolated parameters with option proc" do + get "/bar/1%3E" + verify_redirect "http://www.example.com/foo/bar/1%3E" + end + +private + def verify_redirect(url, status=301) + assert_equal status, @response.status + assert_equal url, @response.headers['Location'] + assert_equal expected_redirect_body(url), @response.body + end + + def expected_redirect_body(url) + %(<html><body>You are being <a href="#{ERB::Util.h(url)}">redirected</a>.</body></html>) + end +end + +class TestConstraintsAccessingParameters < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + get "/:foo" => ok, :constraints => lambda { |r| r.params[:foo] == 'foo' } + get "/:bar" => ok + end + end + + def app; Routes end + + test "parameters are reset between constraint checks" do + get "/bar" + assert_equal nil, @request.params[:foo] + assert_equal "bar", @request.params[:bar] + end +end + +class TestOptimizedNamedRoutes < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + get '/foo' => ok, as: :foo + end + end + + include Routes.url_helpers + def app; Routes end + + test 'enabled when not mounted and default_url_options is empty' do + assert Routes.url_helpers.optimize_routes_generation? + end + + test 'named route called as singleton method' do + assert_equal '/foo', Routes.url_helpers.foo_path + end + + test 'named route called on included module' do + assert_equal '/foo', foo_path + end +end + +class TestNamedRouteUrlHelpers < ActionDispatch::IntegrationTest + class CategoriesController < ActionController::Base + def show + render :text => "categories#show" + end + end + + class ProductsController < ActionController::Base + def show + render :text => "products#show" + end + end + + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + scope :module => "test_named_route_url_helpers" do + get "/categories/:id" => 'categories#show', :as => :category + get "/products/:id" => 'products#show', :as => :product + end + end + end + + def app; Routes end + + include Routes.url_helpers + + test "url helpers do not ignore nil parameters when using non-optimized routes" do + Routes.stubs(:optimize_routes_generation?).returns(false) + + get "/categories/1" + assert_response :success + assert_raises(ActionController::UrlGenerationError) { product_path(nil) } + end +end + +class TestUrlConstraints < ActionDispatch::IntegrationTest + Routes = ActionDispatch::Routing::RouteSet.new.tap do |app| + app.draw do + ok = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, []] } + + constraints :subdomain => 'admin' do + get '/' => ok, :as => :admin_root + end + + scope :constraints => { :protocol => 'https://' } do + get '/' => ok, :as => :secure_root + end + + get '/' => ok, :as => :alternate_root, :constraints => { :port => 8080 } + end + end + + include Routes.url_helpers + def app; Routes end + + test "constraints are copied to defaults when using constraints method" do + assert_equal 'http://admin.example.com/', admin_root_url + + get 'http://admin.example.com/' + assert_response :success + end + + test "constraints are copied to defaults when using scope constraints hash" do + assert_equal 'https://www.example.com/', secure_root_url + + get 'https://www.example.com/' + assert_response :success + end + + test "constraints are copied to defaults when using route constraints hash" do + assert_equal 'http://www.example.com:8080/', alternate_root_url + + get 'http://www.example.com:8080/' + assert_response :success + end +end + +class TestInvalidUrls < ActionDispatch::IntegrationTest + class FooController < ActionController::Base + def show + render :text => "foo#show" + end + end + + test "invalid UTF-8 encoding returns a 400 Bad Request" do + with_routing do |set| + set.draw do + get "/bar/:id", :to => redirect("/foo/show/%{id}") + get "/foo/show(/:id)", :to => "test_invalid_urls/foo#show" + get "/foo(/:action(/:id))", :to => "test_invalid_urls/foo" + get "/:controller(/:action(/:id))" + end + + get "/%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/foo/%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/foo/show/%E2%EF%BF%BD%A6" + assert_response :bad_request + + get "/bar/%E2%EF%BF%BD%A6" + assert_response :bad_request + end + end +end + +class TestOptionalRootSegments < ActionDispatch::IntegrationTest + stub_controllers do |routes| + Routes = routes + Routes.draw do + get '/(page/:page)', :to => 'pages#index', :as => :root + end + end + + def app + Routes + end + + include Routes.url_helpers + + def test_optional_root_segments + get '/' + assert_equal 'pages#index', @response.body + assert_equal '/', root_path + + get '/page/1' + assert_equal 'pages#index', @response.body + assert_equal '1', @request.params[:page] + assert_equal '/page/1', root_path('1') + assert_equal '/page/1', root_path(:page => '1') + end +end diff --git a/actionpack/test/dispatch/session/abstract_store_test.rb b/actionpack/test/dispatch/session/abstract_store_test.rb new file mode 100644 index 0000000000..8daf3d3f5e --- /dev/null +++ b/actionpack/test/dispatch/session/abstract_store_test.rb @@ -0,0 +1,56 @@ +require 'abstract_unit' +require 'action_dispatch/middleware/session/abstract_store' + +module ActionDispatch + module Session + class AbstractStoreTest < ActiveSupport::TestCase + class MemoryStore < AbstractStore + def initialize(app) + @sessions = {} + super + end + + def get_session(env, sid) + sid ||= 1 + session = @sessions[sid] ||= {} + [sid, session] + end + + def set_session(env, sid, session, options) + @sessions[sid] = session + end + end + + def test_session_is_set + env = {} + as = MemoryStore.new app + as.call(env) + + assert @env + assert Request::Session.find @env + end + + def test_new_session_object_is_merged_with_old + env = {} + as = MemoryStore.new app + as.call(env) + + assert @env + session = Request::Session.find @env + session['foo'] = 'bar' + + as.call(@env) + session1 = Request::Session.find @env + + refute_equal session, session1 + assert_equal session.to_hash, session1.to_hash + end + + private + def app(&block) + @env = nil + lambda { |env| @env = env } + end + end + end +end diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb index 12405bf45d..a74e165826 100644 --- a/actionpack/test/dispatch/session/cache_store_test.rb +++ b/actionpack/test/dispatch/session/cache_store_test.rb @@ -164,7 +164,7 @@ class CacheStoreTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match ':action', :to => ::CacheStoreTest::TestController + get ':action', :to => ::CacheStoreTest::TestController end @app = self.class.build_app(set) do |middleware| diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 19969394cd..41fa036a92 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -30,6 +30,11 @@ class CookieStoreTest < ActionDispatch::IntegrationTest render :text => "id: #{request.session_options[:id]}" end + def get_class_after_reset_session + reset_session + render :text => "class: #{session.class}" + end + def call_session_clear session.clear head :ok @@ -187,6 +192,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest get '/call_reset_session' assert_response :success assert_not_equal [], headers['Set-Cookie'] + assert_not_nil session_payload assert_not_equal session_payload, cookies[SessionKey] get '/get_session_value' @@ -195,6 +201,20 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end end + def test_class_type_after_session_reset + with_test_route_set do + get '/set_session_value' + assert_response :success + assert_equal "_myapp_session=#{response.body}; path=/; HttpOnly", + headers['Set-Cookie'] + + get '/get_class_after_reset_session' + assert_response :success + assert_not_equal [], headers['Set-Cookie'] + assert_equal 'class: ActionDispatch::Request::Session', response.body + end + end + def test_getting_from_nonexistent_session with_test_route_set do get '/get_session_value' @@ -317,7 +337,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest def with_test_route_set(options = {}) with_routing do |set| set.draw do - match ':action', :to => ::CookieStoreTest::TestController + get ':action', :to => ::CookieStoreTest::TestController end options = { :key => SessionKey }.merge!(options) diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index 5277c92b55..e53ce4195b 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -34,9 +34,9 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest end begin - require 'memcache' - memcache = MemCache.new('localhost:11211') - memcache.set('ping', '') + require 'dalli' + ss = Dalli::Client.new('localhost:11211').stats + raise Dalli::DalliError unless ss['localhost:11211'] def test_setting_and_getting_session_value with_test_route_set do @@ -131,11 +131,6 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest get '/get_session_id' assert_response :success end - with_autoload_path "session_autoload_test" do - get '/get_session_value' - assert_response :success - assert_equal 'foo: #<SessionAutoloadTest::Foo bar:"baz">', response.body, "should auto-load unloaded class" - end end end @@ -165,7 +160,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest assert_not_equal session_id, cookies['_session_id'] end end - rescue LoadError, RuntimeError + rescue LoadError, RuntimeError, Dalli::DalliError $stderr.puts "Skipping MemCacheStoreTest tests. Start memcached and try again." end @@ -173,7 +168,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest def with_test_route_set with_routing do |set| set.draw do - match ':action', :to => ::MemCacheStoreTest::TestController + get ':action', :to => ::MemCacheStoreTest::TestController end @app = self.class.build_app(set) do |middleware| diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb new file mode 100644 index 0000000000..6f075a9074 --- /dev/null +++ b/actionpack/test/dispatch/ssl_test.rb @@ -0,0 +1,157 @@ +require 'abstract_unit' + +class SSLTest < ActionDispatch::IntegrationTest + def default_app + lambda { |env| + headers = {'Content-Type' => "text/html"} + headers['Set-Cookie'] = "id=1; path=/\ntoken=abc; path=/; secure; HttpOnly" + [200, headers, ["OK"]] + } + end + + def app + @app ||= ActionDispatch::SSL.new(default_app) + end + attr_writer :app + + def test_allows_https_url + get "https://example.org/path?key=value" + assert_response :success + end + + def test_allows_https_proxy_header_url + get "http://example.org/", {}, 'HTTP_X_FORWARDED_PROTO' => "https" + assert_response :success + end + + def test_redirects_http_to_https + get "http://example.org/path?key=value" + assert_response :redirect + assert_equal "https://example.org/path?key=value", + response.headers['Location'] + end + + def test_hsts_header_by_default + get "https://example.org/" + assert_equal "max-age=31536000", + response.headers['Strict-Transport-Security'] + end + + def test_hsts_header + self.app = ActionDispatch::SSL.new(default_app, :hsts => true) + get "https://example.org/" + assert_equal "max-age=31536000", + response.headers['Strict-Transport-Security'] + end + + def test_disable_hsts_header + self.app = ActionDispatch::SSL.new(default_app, :hsts => false) + get "https://example.org/" + refute response.headers['Strict-Transport-Security'] + end + + def test_hsts_expires + self.app = ActionDispatch::SSL.new(default_app, :hsts => { :expires => 500 }) + get "https://example.org/" + assert_equal "max-age=500", + response.headers['Strict-Transport-Security'] + end + + def test_hsts_include_subdomains + self.app = ActionDispatch::SSL.new(default_app, :hsts => { :subdomains => true }) + get "https://example.org/" + assert_equal "max-age=31536000; includeSubDomains", + response.headers['Strict-Transport-Security'] + end + + def test_flag_cookies_as_secure + get "https://example.org/" + assert_equal ["id=1; path=/; secure", "token=abc; path=/; secure; HttpOnly" ], + response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure_at_end_of_line + self.app = ActionDispatch::SSL.new(lambda { |env| + headers = { + 'Content-Type' => "text/html", + 'Set-Cookie' => "problem=def; path=/; HttpOnly; secure" + } + [200, headers, ["OK"]] + }) + + get "https://example.org/" + assert_equal ["problem=def; path=/; HttpOnly; secure"], + response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure_with_more_spaces_before + self.app = ActionDispatch::SSL.new(lambda { |env| + headers = { + 'Content-Type' => "text/html", + 'Set-Cookie' => "problem=def; path=/; HttpOnly; secure" + } + [200, headers, ["OK"]] + }) + + get "https://example.org/" + assert_equal ["problem=def; path=/; HttpOnly; secure"], + response.headers['Set-Cookie'].split("\n") + end + + def test_flag_cookies_as_secure_with_more_spaces_after + self.app = ActionDispatch::SSL.new(lambda { |env| + headers = { + 'Content-Type' => "text/html", + 'Set-Cookie' => "problem=def; path=/; secure; HttpOnly" + } + [200, headers, ["OK"]] + }) + + get "https://example.org/" + assert_equal ["problem=def; path=/; secure; HttpOnly"], + response.headers['Set-Cookie'].split("\n") + end + + def test_no_cookies + self.app = ActionDispatch::SSL.new(lambda { |env| + [200, {'Content-Type' => "text/html"}, ["OK"]] + }) + get "https://example.org/" + assert !response.headers['Set-Cookie'] + end + + def test_redirect_to_host + self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org") + get "http://example.org/path?key=value" + assert_equal "https://ssl.example.org/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_port + self.app = ActionDispatch::SSL.new(default_app, :port => 8443) + get "http://example.org/path?key=value" + assert_equal "https://example.org:8443/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_host_and_port + self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org", :port => 8443) + get "http://example.org/path?key=value" + assert_equal "https://ssl.example.org:8443/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_secure_host_when_on_subdomain + self.app = ActionDispatch::SSL.new(default_app, :host => "ssl.example.org") + get "http://ssl.example.org/path?key=value" + assert_equal "https://ssl.example.org/path?key=value", + response.headers['Location'] + end + + def test_redirect_to_secure_subdomain_when_on_deep_subdomain + self.app = ActionDispatch::SSL.new(default_app, :host => "example.co.uk") + get "http://double.rainbow.what.does.it.mean.example.co.uk/path?key=value" + assert_equal "https://example.co.uk/path?key=value", + response.headers['Location'] + end +end diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index 092ca3e20a..112f470786 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -7,6 +7,10 @@ module StaticTests assert_equal "Hello, World!", get("/nofile").body end + def test_handles_urls_with_bad_encoding + assert_equal "Hello, World!", get("/doorkeeper%E3E4").body + end + def test_sets_cache_control response = get("/index.html") assert_html "/index.html", response diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb index 4ee1d61146..6047631ba3 100644 --- a/actionpack/test/dispatch/test_request_test.rb +++ b/actionpack/test/dispatch/test_request_test.rb @@ -55,6 +55,13 @@ class TestRequestTest < ActiveSupport::TestCase assert_cookies({"user_name" => "david"}, req.cookie_jar) end + test "does not complain when Rails.application is nil" do + Rails.stubs(:application).returns(nil) + req = ActionDispatch::TestRequest.new + + assert_equal false, req.env.empty? + end + private def assert_cookies(expected, cookie_jar) assert_equal(expected, cookie_jar.instance_variable_get("@cookies")) diff --git a/actionpack/test/dispatch/uploaded_file_test.rb b/actionpack/test/dispatch/uploaded_file_test.rb index 0b95291e18..e69c1fbed4 100644 --- a/actionpack/test/dispatch/uploaded_file_test.rb +++ b/actionpack/test/dispatch/uploaded_file_test.rb @@ -12,7 +12,7 @@ module ActionDispatch uf = Http::UploadedFile.new(:filename => 'foo', :tempfile => Object.new) assert_equal 'foo', uf.original_filename end - + def test_filename_should_be_in_utf_8 uf = Http::UploadedFile.new(:filename => 'foo', :tempfile => Object.new) assert_equal "UTF-8", uf.original_filename.encoding.to_s @@ -65,6 +65,12 @@ module ActionDispatch end end + def test_delegate_eof_to_tempfile + tf = Class.new { def eof?; true end; } + uf = Http::UploadedFile.new(:tempfile => tf.new) + assert uf.eof? + end + def test_respond_to? tf = Class.new { def read; yield end } uf = Http::UploadedFile.new(:tempfile => tf.new) diff --git a/actionpack/test/dispatch/url_generation_test.rb b/actionpack/test/dispatch/url_generation_test.rb index 2b54bc62b0..e56e8ddc57 100644 --- a/actionpack/test/dispatch/url_generation_test.rb +++ b/actionpack/test/dispatch/url_generation_test.rb @@ -3,7 +3,7 @@ require 'abstract_unit' module TestUrlGeneration class WithMountPoint < ActionDispatch::IntegrationTest Routes = ActionDispatch::Routing::RouteSet.new - Routes.draw { match "/foo", :to => "my_route_generating#index", :as => :foo } + include Routes.url_helpers class ::MyRouteGeneratingController < ActionController::Base include Routes.url_helpers @@ -12,7 +12,11 @@ module TestUrlGeneration end end - include Routes.url_helpers + Routes.draw do + get "/foo", :to => "my_route_generating#index", :as => :foo + + mount MyRouteGeneratingController.action(:index), at: '/bar' + end def _routes Routes @@ -30,11 +34,16 @@ module TestUrlGeneration assert_equal "/bar/foo", foo_path(:script_name => "/bar") end - test "the request's SCRIPT_NAME takes precedence over the routes'" do + test "the request's SCRIPT_NAME takes precedence over the route" do get "/foo", {}, 'SCRIPT_NAME' => "/new", 'action_dispatch.routes' => Routes assert_equal "/new/foo", response.body end + test "the request's SCRIPT_NAME wraps the mounted app's" do + get '/new/bar/foo', {}, 'SCRIPT_NAME' => '/new', 'PATH_INFO' => '/bar/foo', 'action_dispatch.routes' => Routes + assert_equal "/new/bar/foo", response.body + end + test "handling http protocol with https set" do https! assert_equal "http://www.example.com/foo", foo_url(:protocol => "http") diff --git a/actionpack/test/fixtures/company.rb b/actionpack/test/fixtures/company.rb index e29978801e..f3ac3642fa 100644 --- a/actionpack/test/fixtures/company.rb +++ b/actionpack/test/fixtures/company.rb @@ -1,6 +1,5 @@ class Company < ActiveRecord::Base has_one :mascot - attr_protected :rating self.sequence_name = :companies_nonstd_seq validates_presence_of :name diff --git a/actionpack/test/fixtures/digestor/comments/_comment.html.erb b/actionpack/test/fixtures/digestor/comments/_comment.html.erb new file mode 100644 index 0000000000..f172e749da --- /dev/null +++ b/actionpack/test/fixtures/digestor/comments/_comment.html.erb @@ -0,0 +1 @@ +Great story, bro! diff --git a/actionpack/test/fixtures/digestor/comments/_comments.html.erb b/actionpack/test/fixtures/digestor/comments/_comments.html.erb new file mode 100644 index 0000000000..c28646a283 --- /dev/null +++ b/actionpack/test/fixtures/digestor/comments/_comments.html.erb @@ -0,0 +1 @@ +<%= render partial: "comments/comment", collection: commentable.comments %> diff --git a/actionpack/test/fixtures/sprockets/app/fonts/dir/font.ttf b/actionpack/test/fixtures/digestor/events/_event.html.erb index e69de29bb2..e69de29bb2 100644 --- a/actionpack/test/fixtures/sprockets/app/fonts/dir/font.ttf +++ b/actionpack/test/fixtures/digestor/events/_event.html.erb diff --git a/actionpack/test/fixtures/sprockets/app/fonts/font.ttf b/actionpack/test/fixtures/digestor/messages/_form.html.erb index e69de29bb2..e69de29bb2 100644 --- a/actionpack/test/fixtures/sprockets/app/fonts/font.ttf +++ b/actionpack/test/fixtures/digestor/messages/_form.html.erb diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/dir/xmlhr.js b/actionpack/test/fixtures/digestor/messages/_header.html.erb index e69de29bb2..e69de29bb2 100644 --- a/actionpack/test/fixtures/sprockets/app/javascripts/dir/xmlhr.js +++ b/actionpack/test/fixtures/digestor/messages/_header.html.erb diff --git a/actionpack/test/fixtures/digestor/messages/_message.html.erb b/actionpack/test/fixtures/digestor/messages/_message.html.erb new file mode 100644 index 0000000000..406a0fb848 --- /dev/null +++ b/actionpack/test/fixtures/digestor/messages/_message.html.erb @@ -0,0 +1 @@ +THIS BE WHERE THEM MESSAGE GO, YO!
\ No newline at end of file diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/extra.js b/actionpack/test/fixtures/digestor/messages/actions/_move.html.erb index e69de29bb2..e69de29bb2 100644 --- a/actionpack/test/fixtures/sprockets/app/javascripts/extra.js +++ b/actionpack/test/fixtures/digestor/messages/actions/_move.html.erb diff --git a/actionpack/test/fixtures/digestor/messages/edit.html.erb b/actionpack/test/fixtures/digestor/messages/edit.html.erb new file mode 100644 index 0000000000..a9e0a88e32 --- /dev/null +++ b/actionpack/test/fixtures/digestor/messages/edit.html.erb @@ -0,0 +1,5 @@ +<%= render "header" %> +<%= render partial: "form" %> +<%= render @message %> +<%= render ( @message.events ) %> +<%= render :partial => "comments/comment", :collection => @message.comments %> diff --git a/actionpack/test/fixtures/digestor/messages/index.html.erb b/actionpack/test/fixtures/digestor/messages/index.html.erb new file mode 100644 index 0000000000..1937b652e4 --- /dev/null +++ b/actionpack/test/fixtures/digestor/messages/index.html.erb @@ -0,0 +1,2 @@ +<%= render @messages %> +<%= render @events %> diff --git a/actionpack/test/fixtures/digestor/messages/show.html.erb b/actionpack/test/fixtures/digestor/messages/show.html.erb new file mode 100644 index 0000000000..9f73345a9f --- /dev/null +++ b/actionpack/test/fixtures/digestor/messages/show.html.erb @@ -0,0 +1,9 @@ +<%# Template Dependency: messages/message %> +<%= render "header" %> +<%= render "comments/comments" %> + +<%= render "messages/actions/move" %> + +<%= render @message.history.events %> + +<%# render "something_missing" %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/fun/games/_game.erb b/actionpack/test/fixtures/fun/games/_game.erb index d51b7b3ebc..f0f542ff92 100644 --- a/actionpack/test/fixtures/fun/games/_game.erb +++ b/actionpack/test/fixtures/fun/games/_game.erb @@ -1 +1 @@ -<%= game.name %>
\ No newline at end of file +Fun <%= game.name %> diff --git a/actionpack/test/fixtures/fun/serious/games/_game.erb b/actionpack/test/fixtures/fun/serious/games/_game.erb index d51b7b3ebc..523bc55bd7 100644 --- a/actionpack/test/fixtures/fun/serious/games/_game.erb +++ b/actionpack/test/fixtures/fun/serious/games/_game.erb @@ -1 +1 @@ -<%= game.name %>
\ No newline at end of file +Serious <%= game.name %> diff --git a/actionpack/test/fixtures/games/_game.erb b/actionpack/test/fixtures/games/_game.erb new file mode 100644 index 0000000000..1aeb81fcba --- /dev/null +++ b/actionpack/test/fixtures/games/_game.erb @@ -0,0 +1 @@ +Just <%= game.name %> diff --git a/actionpack/test/fixtures/helpers1_pack/pack1_helper.rb b/actionpack/test/fixtures/helpers1_pack/pack1_helper.rb new file mode 100644 index 0000000000..9faa427736 --- /dev/null +++ b/actionpack/test/fixtures/helpers1_pack/pack1_helper.rb @@ -0,0 +1,5 @@ +module Pack1Helper + def conflicting_helper + "pack1" + end +end diff --git a/actionpack/test/fixtures/helpers2_pack/pack2_helper.rb b/actionpack/test/fixtures/helpers2_pack/pack2_helper.rb new file mode 100644 index 0000000000..cf56697dfb --- /dev/null +++ b/actionpack/test/fixtures/helpers2_pack/pack2_helper.rb @@ -0,0 +1,5 @@ +module Pack2Helper + def conflicting_helper + "pack2" + end +end diff --git a/actionpack/test/fixtures/layouts/with_html_partial.html.erb b/actionpack/test/fixtures/layouts/with_html_partial.html.erb new file mode 100644 index 0000000000..fd2896aeaa --- /dev/null +++ b/actionpack/test/fixtures/layouts/with_html_partial.html.erb @@ -0,0 +1 @@ +<%= render :partial => "partial_only_html" %><%= yield %> diff --git a/actionpack/test/fixtures/plain_text.raw b/actionpack/test/fixtures/plain_text.raw new file mode 100644 index 0000000000..b13985337f --- /dev/null +++ b/actionpack/test/fixtures/plain_text.raw @@ -0,0 +1 @@ +<%= hello_world %> diff --git a/actionpack/test/fixtures/plain_text_with_characters.raw b/actionpack/test/fixtures/plain_text_with_characters.raw new file mode 100644 index 0000000000..1e86e44fb4 --- /dev/null +++ b/actionpack/test/fixtures/plain_text_with_characters.raw @@ -0,0 +1 @@ +Here are some characters: !@#$%^&*()-="'}{` diff --git a/actionpack/test/fixtures/project.rb b/actionpack/test/fixtures/project.rb index 2b53d39ed5..c124a9e605 100644 --- a/actionpack/test/fixtures/project.rb +++ b/actionpack/test/fixtures/project.rb @@ -1,3 +1,3 @@ class Project < ActiveRecord::Base - has_and_belongs_to_many :developers, :uniq => true + has_and_belongs_to_many :developers, -> { uniq } end diff --git a/actionpack/test/fixtures/public/foo/baz.css b/actionpack/test/fixtures/public/foo/baz.css new file mode 100644 index 0000000000..b5173fbef2 --- /dev/null +++ b/actionpack/test/fixtures/public/foo/baz.css @@ -0,0 +1,3 @@ +body { +background: #000; +} diff --git a/actionpack/test/fixtures/reply.rb b/actionpack/test/fixtures/reply.rb index 19cba93673..047522c55b 100644 --- a/actionpack/test/fixtures/reply.rb +++ b/actionpack/test/fixtures/reply.rb @@ -1,6 +1,6 @@ class Reply < ActiveRecord::Base - scope :base - belongs_to :topic, :include => [:replies] + scope :base, -> { all } + belongs_to :topic, -> { includes(:replies) } belongs_to :developer validates_presence_of :content diff --git a/actionpack/test/fixtures/ruby_template.ruby b/actionpack/test/fixtures/ruby_template.ruby new file mode 100644 index 0000000000..5097bce47c --- /dev/null +++ b/actionpack/test/fixtures/ruby_template.ruby @@ -0,0 +1,2 @@ +body = "" +body << ["Hello", "from", "Ruby", "code"].join(" ") diff --git a/actionpack/test/fixtures/sprockets/alternate/stylesheets/style.css b/actionpack/test/fixtures/sprockets/alternate/stylesheets/style.css deleted file mode 100644 index bfb90bfa48..0000000000 --- a/actionpack/test/fixtures/sprockets/alternate/stylesheets/style.css +++ /dev/null @@ -1 +0,0 @@ -/* Different from other style.css */
\ No newline at end of file diff --git a/actionpack/test/fixtures/sprockets/app/images/logo.png b/actionpack/test/fixtures/sprockets/app/images/logo.png Binary files differdeleted file mode 100644 index d5edc04e65..0000000000 --- a/actionpack/test/fixtures/sprockets/app/images/logo.png +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/application.js b/actionpack/test/fixtures/sprockets/app/javascripts/application.js deleted file mode 100644 index e611d2b129..0000000000 --- a/actionpack/test/fixtures/sprockets/app/javascripts/application.js +++ /dev/null @@ -1 +0,0 @@ -//= require xmlhr diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/application.css b/actionpack/test/fixtures/sprockets/app/stylesheets/application.css deleted file mode 100644 index 2365eaa4cd..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/application.css +++ /dev/null @@ -1 +0,0 @@ -/*= require style */ diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css b/actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/extra.css b/actionpack/test/fixtures/sprockets/app/stylesheets/extra.css deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/extra.css +++ /dev/null diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/style.css b/actionpack/test/fixtures/sprockets/app/stylesheets/style.css deleted file mode 100644 index e69de29bb2..0000000000 --- a/actionpack/test/fixtures/sprockets/app/stylesheets/style.css +++ /dev/null diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial.html.erb new file mode 100644 index 0000000000..e918ba8f83 --- /dev/null +++ b/actionpack/test/fixtures/test/_b_layout_for_partial.html.erb @@ -0,0 +1 @@ +<b><%= yield %></b>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb new file mode 100644 index 0000000000..bdd53014cd --- /dev/null +++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object.html.erb @@ -0,0 +1 @@ +<b class="<%= customer.name.downcase %>"><%= yield %></b>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb new file mode 100644 index 0000000000..44d6121297 --- /dev/null +++ b/actionpack/test/fixtures/test/_b_layout_for_partial_with_object_counter.html.erb @@ -0,0 +1 @@ +<b data-counter="<%= customer_counter %>"><%= yield %></b>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_changing_priority.html.erb b/actionpack/test/fixtures/test/_changing_priority.html.erb new file mode 100644 index 0000000000..3225efc49a --- /dev/null +++ b/actionpack/test/fixtures/test/_changing_priority.html.erb @@ -0,0 +1 @@ +HTML
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_changing_priority.json.erb b/actionpack/test/fixtures/test/_changing_priority.json.erb new file mode 100644 index 0000000000..7fa41dce66 --- /dev/null +++ b/actionpack/test/fixtures/test/_changing_priority.json.erb @@ -0,0 +1 @@ +JSON
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_first_json_partial.json.erb b/actionpack/test/fixtures/test/_first_json_partial.json.erb new file mode 100644 index 0000000000..790ee896db --- /dev/null +++ b/actionpack/test/fixtures/test/_first_json_partial.json.erb @@ -0,0 +1 @@ +<%= render :partial => "test/second_json_partial" %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/xmlhr.js b/actionpack/test/fixtures/test/_json_change_priority.json.erb index e69de29bb2..e69de29bb2 100644 --- a/actionpack/test/fixtures/sprockets/app/javascripts/xmlhr.js +++ b/actionpack/test/fixtures/test/_json_change_priority.json.erb diff --git a/actionpack/test/fixtures/test/_partial_html_erb.html.erb b/actionpack/test/fixtures/test/_partial_html_erb.html.erb new file mode 100644 index 0000000000..4b54875782 --- /dev/null +++ b/actionpack/test/fixtures/test/_partial_html_erb.html.erb @@ -0,0 +1 @@ +<%= "partial.html.erb" %> diff --git a/actionpack/test/fixtures/test/_partial_only_html.html b/actionpack/test/fixtures/test/_partial_only_html.html new file mode 100644 index 0000000000..d2d630bd40 --- /dev/null +++ b/actionpack/test/fixtures/test/_partial_only_html.html @@ -0,0 +1 @@ +only html partial
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_raise_indentation.html.erb b/actionpack/test/fixtures/test/_raise_indentation.html.erb new file mode 100644 index 0000000000..f9a93728fe --- /dev/null +++ b/actionpack/test/fixtures/test/_raise_indentation.html.erb @@ -0,0 +1,13 @@ +<p>First paragraph</p> +<p>Second paragraph</p> +<p>Third paragraph</p> +<p>Fourth paragraph</p> +<p>Fifth paragraph</p> +<p>Sixth paragraph</p> +<p>Seventh paragraph</p> +<p>Eight paragraph</p> +<p>Ninth paragraph</p> +<p>Tenth paragraph</p> +<%= raise "error here!" %> +<p>Eleventh paragraph</p> +<p>Twelfth paragraph</p>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/_second_json_partial.json.erb b/actionpack/test/fixtures/test/_second_json_partial.json.erb new file mode 100644 index 0000000000..5ebb7f1afd --- /dev/null +++ b/actionpack/test/fixtures/test/_second_json_partial.json.erb @@ -0,0 +1 @@ +Third level
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/change_priorty.html.erb b/actionpack/test/fixtures/test/change_priorty.html.erb new file mode 100644 index 0000000000..5618977d05 --- /dev/null +++ b/actionpack/test/fixtures/test/change_priorty.html.erb @@ -0,0 +1,2 @@ +<%= render :partial => "test/json_change_priority", formats: :json %> +HTML Template, but <%= render :partial => "test/changing_priority" %> partial
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/hello_world_with_partial.html.erb b/actionpack/test/fixtures/test/hello_world_with_partial.html.erb new file mode 100644 index 0000000000..ec31545356 --- /dev/null +++ b/actionpack/test/fixtures/test/hello_world_with_partial.html.erb @@ -0,0 +1,2 @@ +Hello world! +<%= render '/test/partial' %> diff --git a/actionpack/test/fixtures/test/html_template.html.erb b/actionpack/test/fixtures/test/html_template.html.erb new file mode 100644 index 0000000000..1bbc2b7f09 --- /dev/null +++ b/actionpack/test/fixtures/test/html_template.html.erb @@ -0,0 +1 @@ +<%= render :partial => "test/first_json_partial", formats: :json %>
\ No newline at end of file diff --git a/actionpack/test/fixtures/test/with_html_partial.html.erb b/actionpack/test/fixtures/test/with_html_partial.html.erb new file mode 100644 index 0000000000..d84d909d64 --- /dev/null +++ b/actionpack/test/fixtures/test/with_html_partial.html.erb @@ -0,0 +1 @@ +<strong><%= render :partial => "partial_only_html" %></strong> diff --git a/actionpack/test/fixtures/test/with_partial.html.erb b/actionpack/test/fixtures/test/with_partial.html.erb new file mode 100644 index 0000000000..7502364cf5 --- /dev/null +++ b/actionpack/test/fixtures/test/with_partial.html.erb @@ -0,0 +1 @@ +<strong><%= render :partial => "partial_only" %></strong> diff --git a/actionpack/test/fixtures/test/with_partial.text.erb b/actionpack/test/fixtures/test/with_partial.text.erb new file mode 100644 index 0000000000..5f068ebf27 --- /dev/null +++ b/actionpack/test/fixtures/test/with_partial.text.erb @@ -0,0 +1 @@ +**<%= render :partial => "partial_only" %>** diff --git a/actionpack/test/fixtures/test/with_xml_template.html.erb b/actionpack/test/fixtures/test/with_xml_template.html.erb new file mode 100644 index 0000000000..e54a7cd001 --- /dev/null +++ b/actionpack/test/fixtures/test/with_xml_template.html.erb @@ -0,0 +1 @@ +<%= render :template => "test/greeting", :formats => :xml %> diff --git a/actionpack/test/fixtures/translations/templates/default.erb b/actionpack/test/fixtures/translations/templates/default.erb new file mode 100644 index 0000000000..8b70031071 --- /dev/null +++ b/actionpack/test/fixtures/translations/templates/default.erb @@ -0,0 +1 @@ +<%= t('.missing', :default => :'.foo') %> diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index bbb4cc5ef3..82f38b5309 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -214,3 +214,6 @@ class RenderJsonTestException < Exception return { :error => self.class.name, :message => self.to_s }.to_json end end + +class Car < Struct.new(:color) +end diff --git a/actionpack/test/metal/caching_test.rb b/actionpack/test/metal/caching_test.rb new file mode 100644 index 0000000000..a2b6763754 --- /dev/null +++ b/actionpack/test/metal/caching_test.rb @@ -0,0 +1,32 @@ +require 'abstract_unit' + +CACHE_DIR = 'test_cache' +# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed +FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) + +class CachingController < ActionController::Metal + abstract! + + include ActionController::Caching + + self.page_cache_directory = FILE_STORE_PATH + self.cache_store = :file_store, FILE_STORE_PATH +end + +class PageCachingTestController < CachingController + caches_page :ok + + def ok + self.response_body = "ok" + end +end + +class PageCachingTest < ActionController::TestCase + tests PageCachingTestController + + def test_should_cache_get_with_ok_status + get :ok + assert_response :ok + assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/ok.html"), "get with ok status should have been cached" + end +end diff --git a/actionpack/test/template/active_model_helper_test.rb b/actionpack/test/template/active_model_helper_test.rb index 52be0f1762..86bccdfade 100644 --- a/actionpack/test/template/active_model_helper_test.rb +++ b/actionpack/test/template/active_model_helper_test.rb @@ -29,28 +29,41 @@ class ActiveModelHelperTest < ActionView::TestCase def test_text_area_with_errors assert_dom_equal( - %(<div class="field_with_errors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div>), + %(<div class="field_with_errors"><textarea id="post_body" name="post[body]">\nBack to the hill and over it again!</textarea></div>), text_area("post", "body") ) end def test_text_field_with_errors assert_dom_equal( - %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>), + %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" type="text" value="" /></div>), text_field("post", "author_name") ) end + def test_select_with_errors + assert_dom_equal( + %(<div class="field_with_errors"><select name="post[author_name]" id="post_author_name"><option value="a">a</option>\n<option value="b">b</option></select></div>), + select("post", "author_name", [:a, :b]) + ) + end + + def test_select_with_errors_and_blank_option + expected_dom = %(<div class="field_with_errors"><select name="post[author_name]" id="post_author_name"><option value="">Choose one...</option>\n<option value="a">a</option>\n<option value="b">b</option></select></div>) + assert_dom_equal(expected_dom, select("post", "author_name", [:a, :b], :include_blank => 'Choose one...')) + assert_dom_equal(expected_dom, select("post", "author_name", [:a, :b], :prompt => 'Choose one...')) + end + def test_date_select_with_errors assert_dom_equal( - %(<div class="field_with_errors"><select id="post_updated_at_1i" name="post[updated_at(1i)]">\n<option selected="selected" value="2004">2004</option>\n<option value="2005">2005</option>\n</select>\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="15" />\n</div>), + %(<div class="field_with_errors"><select id="post_updated_at_1i" name="post[updated_at(1i)]">\n<option selected="selected" value="2004">2004</option>\n<option value="2005">2005</option>\n</select>\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="1" />\n</div>), date_select("post", "updated_at", :discard_month => true, :discard_day => true, :start_year => 2004, :end_year => 2005) ) end def test_datetime_select_with_errors assert_dom_equal( - %(<div class="field_with_errors"><input id="post_updated_at_1i" name="post[updated_at(1i)]" type="hidden" value="2004" />\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="15" />\n<select id="post_updated_at_4i" name="post[updated_at(4i)]">\n<option selected="selected" value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">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</select>\n : <select id="post_updated_at_5i" name="post[updated_at(5i)]">\n<option selected="selected" value="00">00</option>\n</select>\n</div>), + %(<div class="field_with_errors"><input id="post_updated_at_1i" name="post[updated_at(1i)]" type="hidden" value="2004" />\n<input id="post_updated_at_2i" name="post[updated_at(2i)]" type="hidden" value="6" />\n<input id="post_updated_at_3i" name="post[updated_at(3i)]" type="hidden" value="1" />\n<select id="post_updated_at_4i" name="post[updated_at(4i)]">\n<option selected="selected" value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">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</select>\n : <select id="post_updated_at_5i" name="post[updated_at(5i)]">\n<option selected="selected" value="00">00</option>\n</select>\n</div>), datetime_select("post", "updated_at", :discard_year => true, :discard_month => true, :discard_day => true, :minute_step => 60) ) end @@ -76,10 +89,11 @@ class ActiveModelHelperTest < ActionView::TestCase end assert_dom_equal( - %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /> <span class="error">can't be empty</span></div>), + %(<div class="field_with_errors"><input id="post_author_name" name="post[author_name]" type="text" value="" /> <span class="error">can't be empty</span></div>), text_field("post", "author_name") ) ensure ActionView::Base.field_error_proc = old_proc if old_proc end + end diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb index 3d2eeea503..25d85c47c7 100644 --- a/actionpack/test/template/asset_tag_helper_test.rb +++ b/actionpack/test/template/asset_tag_helper_test.rb @@ -38,6 +38,7 @@ class AssetTagHelperTest < ActionView::TestCase @controller = BasicController.new @request = Class.new do + attr_accessor :script_name def protocol() 'http://' end def ssl?() false end def host_with_port() 'localhost' end @@ -64,7 +65,6 @@ class AssetTagHelperTest < ActionView::TestCase %(auto_discovery_link_tag) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />), %(auto_discovery_link_tag(:rss)) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />), %(auto_discovery_link_tag(:atom)) => %(<link href="http://www.example.com" rel="alternate" title="ATOM" type="application/atom+xml" />), - %(auto_discovery_link_tag(:xml)) => %(<link href="http://www.example.com" rel="alternate" title="XML" type="application/xml" />), %(auto_discovery_link_tag(:rss, :action => "feed")) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />), %(auto_discovery_link_tag(:rss, "http://localhost/feed")) => %(<link href="http://localhost/feed" rel="alternate" title="RSS" type="application/rss+xml" />), %(auto_discovery_link_tag(:rss, "//localhost/feed")) => %(<link href="//localhost/feed" rel="alternate" title="RSS" type="application/rss+xml" />), @@ -101,20 +101,20 @@ class AssetTagHelperTest < ActionView::TestCase } JavascriptIncludeToTag = { - %(javascript_include_tag("bank")) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>), - %(javascript_include_tag("bank.js")) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>), - %(javascript_include_tag("bank", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/bank.js" type="text/javascript"></script>), - %(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" type="text/javascript"></script>\n<script src="/elsewhere/cools.js" type="text/javascript"></script>), - %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:all)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:all, :recursive => true)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/subdir/subdir.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:defaults, "bank")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag(:defaults, "application")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - %(javascript_include_tag("bank", :defaults)) => %(<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), - - %(javascript_include_tag("http://example.com/all")) => %(<script src="http://example.com/all" type="text/javascript"></script>), - %(javascript_include_tag("http://example.com/all.js")) => %(<script src="http://example.com/all.js" type="text/javascript"></script>), - %(javascript_include_tag("//example.com/all.js")) => %(<script src="//example.com/all.js" type="text/javascript"></script>), + %(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("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" ></script>\n<script src="/elsewhere/cools.js" ></script>), + %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" ></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:all)) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:all, :recursive => true)) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/subdir/subdir.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:defaults, "bank")) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag(:defaults, "application")) => %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), + %(javascript_include_tag("bank", :defaults)) => %(<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.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>), + %(javascript_include_tag("//example.com/all.js")) => %(<script src="//example.com/all.js"></script>), } StylePathToTag = { @@ -146,19 +146,19 @@ class AssetTagHelperTest < ActionView::TestCase } StyleLinkToTag = { - %(stylesheet_link_tag("bank")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("bank.css")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("/elsewhere/file")) => %(<link href="/elsewhere/file.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("subdir/subdir")) => %(<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("bank", :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all, :recursive => true)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag(:all, :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="all" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="all" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("random.styles", "/elsewhere/file")) => %(<link href="/stylesheets/random.styles" media="screen" rel="stylesheet" type="text/css" />\n<link href="/elsewhere/file.css" media="screen" rel="stylesheet" type="text/css" />), - - %(stylesheet_link_tag("http://www.example.com/styles/style")) => %(<link href="http://www.example.com/styles/style" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("http://www.example.com/styles/style.css")) => %(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />), - %(stylesheet_link_tag("//www.example.com/styles/style.css")) => %(<link href="//www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />), + %(stylesheet_link_tag("bank")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag("bank.css")) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />), + %(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(:all)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag(:all, :recursive => true)) => %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), + %(stylesheet_link_tag(:all, :media => "all")) => %(<link href="/stylesheets/bank.css" media="all" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="all" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="all" rel="stylesheet" />), + %(stylesheet_link_tag("random.styles", "/elsewhere/file")) => %(<link href="/stylesheets/random.styles" media="screen" rel="stylesheet" />\n<link href="/elsewhere/file.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" />), + %(stylesheet_link_tag("//www.example.com/styles/style.css")) => %(<link href="//www.example.com/styles/style.css" media="screen" rel="stylesheet" />), } ImagePathToTag = { @@ -202,9 +202,9 @@ class AssetTagHelperTest < ActionView::TestCase %(image_tag(".pdf.png")) => %(<img alt=".pdf" src="/images/.pdf.png" />), %(image_tag("http://www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="http://www.rubyonrails.com/images/rails.png" />), %(image_tag("//www.rubyonrails.com/images/rails.png")) => %(<img alt="Rails" src="//www.rubyonrails.com/images/rails.png" />), - %(image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) => %(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />), - %(image_tag("mouse.png", :mouseover => image_path("mouse_over.png"))) => %(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />), - %(image_tag("mouse.png", :alt => nil)) => %(<img src="/images/mouse.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="" />) } FaviconLinkToTag = { @@ -298,6 +298,16 @@ class AssetTagHelperTest < ActionView::TestCase %(audio_tag(["audio.mp3", "audio.ogg"], :autobuffer => true, :controls => true)) => %(<audio autobuffer="autobuffer" controls="controls"><source src="/audios/audio.mp3" /><source src="/audios/audio.ogg" /></audio>) } + def test_autodiscovery_link_tag_deprecated_types + result = nil + assert_deprecated do + result = auto_discovery_link_tag(:xml) + end + + expected = %(<link href="http://www.example.com" rel="alternate" title="XML" type="application/xml" />) + assert_equal expected, result + end + def test_auto_discovery_link_tag AutoDiscoveryToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end @@ -339,7 +349,7 @@ class AssetTagHelperTest < ActionView::TestCase def test_javascript_include_tag_with_given_asset_id ENV["RAILS_ASSET_ID"] = "1" - assert_dom_equal(%(<script src="/javascripts/prototype.js?1" type="text/javascript"></script>\n<script src="/javascripts/effects.js?1" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js?1" type="text/javascript"></script>\n<script src="/javascripts/controls.js?1" type="text/javascript"></script>\n<script src="/javascripts/rails.js?1" type="text/javascript"></script>\n<script src="/javascripts/application.js?1" type="text/javascript"></script>), javascript_include_tag(:defaults)) + assert_dom_equal(%(<script src="/javascripts/prototype.js?1"></script>\n<script src="/javascripts/effects.js?1"></script>\n<script src="/javascripts/dragdrop.js?1"></script>\n<script src="/javascripts/controls.js?1"></script>\n<script src="/javascripts/rails.js?1"></script>\n<script src="/javascripts/application.js?1"></script>), javascript_include_tag(:defaults)) end def test_javascript_include_tag_is_html_safe @@ -350,35 +360,35 @@ class AssetTagHelperTest < ActionView::TestCase def test_custom_javascript_expansions ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"] - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>), javascript_include_tag('controls', :robbery, 'effects') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/effects.js"></script>), javascript_include_tag('controls', :robbery, 'effects') end def test_custom_javascript_expansions_return_unique_set ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :defaults => %w(prototype effects dragdrop controls rails application) - assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag(:defaults) + assert_dom_equal %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:defaults) end def test_custom_javascript_expansions_and_defaults_puts_application_js_at_the_end ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"] - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls',:defaults, :robbery, 'effects') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('controls',:defaults, :robbery, 'effects') end def test_javascript_include_tag_should_not_output_the_same_asset_twice ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('prototype', 'effects', :defaults) + assert_dom_equal %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('prototype', 'effects', :defaults) end def test_javascript_include_tag_should_not_output_the_same_expansion_twice ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag(:defaults, :defaults) + assert_dom_equal %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:defaults, :defaults) end def test_single_javascript_asset_keys_should_take_precedence_over_expansions ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls', :defaults, 'effects') - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/rails.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), javascript_include_tag('controls', 'effects', :defaults) + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('controls', :defaults, 'effects') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/rails.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag('controls', 'effects', :defaults) end def test_registering_javascript_expansions_merges_with_existing_expansions @@ -386,7 +396,7 @@ class AssetTagHelperTest < ActionView::TestCase ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['bank'] ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['robber'] ActionView::Helpers::AssetTagHelper::register_javascript_expansion :can_merge => ['bank'] - assert_dom_equal %(<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>), javascript_include_tag(:can_merge) + assert_dom_equal %(<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>), javascript_include_tag(:can_merge) end def test_custom_javascript_expansions_with_undefined_symbol @@ -395,20 +405,20 @@ class AssetTagHelperTest < ActionView::TestCase def test_custom_javascript_expansions_with_nil_value ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => nil - assert_dom_equal %(<script src="/javascripts/first.js" type="text/javascript"></script>\n<script src="/javascripts/last.js" type="text/javascript"></script>), javascript_include_tag('first', :monkey, 'last') + assert_dom_equal %(<script src="/javascripts/first.js"></script>\n<script src="/javascripts/last.js"></script>), javascript_include_tag('first', :monkey, 'last') end def test_custom_javascript_expansions_with_empty_array_value ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => [] - assert_dom_equal %(<script src="/javascripts/first.js" type="text/javascript"></script>\n<script src="/javascripts/last.js" type="text/javascript"></script>), javascript_include_tag('first', :monkey, 'last') + assert_dom_equal %(<script src="/javascripts/first.js"></script>\n<script src="/javascripts/last.js"></script>), javascript_include_tag('first', :monkey, 'last') end def test_custom_javascript_and_stylesheet_expansion_with_same_name ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"] ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :robbery => ["money", "security"] - assert_dom_equal %(<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>), javascript_include_tag('controls', :robbery, 'effects') - assert_dom_equal %(<link href="/stylesheets/style.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/money.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/security.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/print.css" rel="stylesheet" type="text/css" media="screen" />), stylesheet_link_tag('style', :robbery, 'print') + assert_dom_equal %(<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/effects.js"></script>), javascript_include_tag('controls', :robbery, 'effects') + assert_dom_equal %(<link href="/stylesheets/style.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/money.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/security.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/print.css" rel="stylesheet" media="screen" />), stylesheet_link_tag('style', :robbery, 'print') end def test_reset_javascript_expansions @@ -416,6 +426,15 @@ class AssetTagHelperTest < ActionView::TestCase assert_raise(ArgumentError) { javascript_include_tag(:defaults) } end + def test_all_javascript_expansion_not_include_application_js_if_not_exists + FileUtils.mv(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'application.js'), + File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'application.bak')) + assert_no_match(/application\.js/, javascript_include_tag(:all)) + ensure + FileUtils.mv(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'application.bak'), + File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'application.js')) + end + def test_stylesheet_path ENV["RAILS_ASSET_ID"] = "" StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } @@ -456,36 +475,36 @@ class AssetTagHelperTest < ActionView::TestCase end def test_stylesheet_link_tag_escapes_options - assert_dom_equal %(<link href="/file.css" media="<script>" rel="stylesheet" type="text/css" />), stylesheet_link_tag('/file', :media => '<script>') + assert_dom_equal %(<link href="/file.css" media="<script>" rel="stylesheet" />), stylesheet_link_tag('/file', :media => '<script>') end def test_custom_stylesheet_expansions ENV["RAILS_ASSET_ID"] = '' ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :robbery => ["bank", "robber"] - assert_dom_equal %(<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('version.1.0', :robbery, 'subdir/subdir') + assert_dom_equal %(<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('version.1.0', :robbery, 'subdir/subdir') end def test_custom_stylesheet_expansions_return_unique_set ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :cities => %w(wellington amsterdam london) - assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:cities) + assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:cities) end def test_stylesheet_link_tag_should_not_output_the_same_asset_twice ENV["RAILS_ASSET_ID"] = "" - assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('wellington', 'wellington', 'amsterdam') + assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('wellington', 'wellington', 'amsterdam') end def test_stylesheet_link_tag_should_not_output_the_same_expansion_twice ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :cities => %w(wellington amsterdam london) - assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:cities, :cities) + assert_dom_equal %(<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/london.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:cities, :cities) end def test_single_stylesheet_asset_keys_should_take_precedence_over_expansions ENV["RAILS_ASSET_ID"] = "" ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :cities => %w(wellington amsterdam london) - assert_dom_equal %(<link href="/stylesheets/london.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag('london', :cities) + assert_dom_equal %(<link href="/stylesheets/london.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/wellington.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/amsterdam.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('london', :cities) end def test_custom_stylesheet_expansions_with_unknown_symbol @@ -494,12 +513,12 @@ class AssetTagHelperTest < ActionView::TestCase def test_custom_stylesheet_expansions_with_nil_value ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :monkey => nil - assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" type="text/css" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') + assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') end def test_custom_stylesheet_expansions_with_empty_array_value ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :monkey => [] - assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" type="text/css" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" type="text/css" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') + assert_dom_equal %(<link href="/stylesheets/first.css" rel="stylesheet" media="screen" />\n<link href="/stylesheets/last.css" rel="stylesheet" media="screen" />), stylesheet_link_tag('first', :monkey, 'last') end def test_registering_stylesheet_expansions_merges_with_existing_expansions @@ -507,7 +526,7 @@ class AssetTagHelperTest < ActionView::TestCase ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['bank'] ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['robber'] ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :can_merge => ['bank'] - assert_dom_equal %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag(:can_merge) + assert_dom_equal %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:can_merge) end def test_image_path @@ -647,6 +666,13 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal %(<img alt="Rails" src="#{@controller.config.relative_url_root}/images/rails.png?#{expected_time}" />), image_tag("rails.png") end + # Same as above, but with script_name + def test_timebased_asset_id_with_script_name + @request.script_name = "/collaboration/hieraki" + expected_time = File.mtime(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).to_i.to_s + assert_equal %(<img alt="Rails" src="#{@request.script_name}/images/rails.png?#{expected_time}" />), image_tag("rails.png") + end + def test_should_skip_asset_id_on_complete_url assert_equal %(<img alt="Rails" src="http://www.example.com/rails.png" />), image_tag("http://www.example.com/rails.png") end @@ -695,21 +721,21 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/all.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/all.js"></script>), javascript_include_tag(:all, :cache => true) ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/money.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/money.js"></script>), javascript_include_tag(:all, :cache => "money") ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) assert_dom_equal( - %(<script src="http://a0.example.com/absolute/test.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/absolute/test.js"></script>), javascript_include_tag(:all, :cache => "/absolute/test") ) @@ -728,7 +754,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/scripts.js'.length, 23 assert_dom_equal( - %(<script src="http://a23.example.com/javascripts/scripts.js" type="text/javascript"></script>), + %(<script src="http://a23.example.com/javascripts/scripts.js"></script>), javascript_include_tag(:all, :cache => 'scripts') ) @@ -751,7 +777,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/vanilla.js'.length, 23 assert_dom_equal( - %(<script src="http://assets23.example.com/javascripts/vanilla.js" type="text/javascript"></script>), + %(<script src="http://assets23.example.com/javascripts/vanilla.js"></script>), javascript_include_tag(:all, :cache => 'vanilla') ) @@ -764,7 +790,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/secure.js'.length, 22 assert_dom_equal( - %(<script src="https://localhost/javascripts/secure.js" type="text/javascript"></script>), + %(<script src="https://localhost/javascripts/secure.js"></script>), javascript_include_tag(:all, :cache => 'secure') ) @@ -791,7 +817,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/vanilla.js'.length, 23 assert_dom_equal( - %(<script src="http://assets23.example.com/javascripts/vanilla.js" type="text/javascript"></script>), + %(<script src="http://assets23.example.com/javascripts/vanilla.js"></script>), javascript_include_tag(:all, :cache => 'vanilla') ) @@ -804,7 +830,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/javascripts/secure.js'.length, 22 assert_dom_equal( - %(<script src="https://localhost/javascripts/secure.js" type="text/javascript"></script>), + %(<script src="https://localhost/javascripts/secure.js"></script>), javascript_include_tag(:all, :cache => 'secure') ) @@ -822,7 +848,7 @@ class AssetTagHelperTest < ActionView::TestCase number = Zlib.crc32('/javascripts/cache/money.js') % 4 assert_dom_equal( - %(<script src="http://a#{number}.example.com/javascripts/cache/money.js" type="text/javascript"></script>), + %(<script src="http://a#{number}.example.com/javascripts/cache/money.js"></script>), javascript_include_tag(:all, :cache => "cache/money") ) @@ -837,7 +863,7 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/combined.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/combined.js"></script>), javascript_include_tag(:all, :cache => "combined", :recursive => true) ) @@ -858,7 +884,7 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="http://a0.example.com/javascripts/combined.js" type="text/javascript"></script>), + %(<script src="http://a0.example.com/javascripts/combined.js"></script>), javascript_include_tag(:all, :cache => "combined") ) @@ -879,14 +905,39 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/all.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/all.js"></script>), + javascript_include_tag(:all, :cache => true) + ) + + assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/money.js"></script>), + javascript_include_tag(:all, :cache => "money") + ) + + assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + + ensure + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + end + + # Same as above, but with script_name + def test_caching_javascript_include_tag_with_script_name + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = true + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/all.js"></script>), javascript_include_tag(:all, :cache => true) ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/money.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/money.js"></script>), javascript_include_tag(:all, :cache => "money") ) @@ -903,14 +954,35 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/robber.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), + javascript_include_tag('robber', :cache => true) + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), + javascript_include_tag('robber', :cache => "money", :recursive => true) + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js')) + end + + # Same as above, but with script_name + def test_caching_javascript_include_tag_with_named_paths_and_script_name_when_caching_off + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = false + + assert_dom_equal( + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), javascript_include_tag('robber', :cache => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/collaboration/hieraki/javascripts/robber.js" type="text/javascript"></script>), + %(<script src="/collaboration/hieraki/javascripts/robber.js"></script>), javascript_include_tag('robber', :cache => "money", :recursive => true) ) @@ -922,24 +994,24 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => true) ) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/subdir/subdir.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/subdir/subdir.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => true, :recursive => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js')) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => "money") ) assert_dom_equal( - %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/bank.js" type="text/javascript"></script>\n<script src="/javascripts/robber.js" type="text/javascript"></script>\n<script src="/javascripts/subdir/subdir.js" type="text/javascript"></script>\n<script src="/javascripts/version.1.0.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>), + %(<script src="/javascripts/prototype.js"></script>\n<script src="/javascripts/effects.js"></script>\n<script src="/javascripts/dragdrop.js"></script>\n<script src="/javascripts/controls.js"></script>\n<script src="/javascripts/bank.js"></script>\n<script src="/javascripts/robber.js"></script>\n<script src="/javascripts/subdir/subdir.js"></script>\n<script src="/javascripts/version.1.0.js"></script>\n<script src="/javascripts/application.js"></script>), javascript_include_tag(:all, :cache => "money", :recursive => true) ) @@ -997,7 +1069,7 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<link href="http://a0.example.com/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a0.example.com/stylesheets/all.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true) ) @@ -1011,14 +1083,14 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal expected_size, File.size(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="http://a0.example.com/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a0.example.com/stylesheets/money.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money") ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) assert_dom_equal( - %(<link href="http://a0.example.com/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a0.example.com/absolute/test.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "/absolute/test") ) @@ -1033,7 +1105,7 @@ class AssetTagHelperTest < ActionView::TestCase ENV["RAILS_ASSET_ID"] = "" assert_dom_equal( - %(<link href="/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/all.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :concat => true) ) @@ -1041,14 +1113,14 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal expected, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/money.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :concat => "money") ) assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) assert_dom_equal( - %(<link href="/absolute/test.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/absolute/test.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :concat => "/absolute/test") ) @@ -1108,7 +1180,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal '/stylesheets/styles.css'.length, 23 assert_dom_equal( - %(<link href="http://a23.example.com/stylesheets/styles.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="http://a23.example.com/stylesheets/styles.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => 'styles') ) @@ -1124,7 +1196,34 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = true assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag(:all, :cache => true) + ) + + files_to_be_joined = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/[^all]*.css"] + + expected_mtime = files_to_be_joined.map { |p| File.mtime(p) }.max + assert_equal expected_mtime, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/money.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag(:all, :cache => "money") + ) + + assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + ensure + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + end + + # Same as above, but with script_name + def test_caching_stylesheet_link_tag_with_script_name + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = true + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/all.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true) ) @@ -1134,7 +1233,7 @@ class AssetTagHelperTest < ActionView::TestCase assert_equal expected_mtime, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/money.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/money.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money") ) @@ -1151,51 +1250,80 @@ class AssetTagHelperTest < ActionView::TestCase config.perform_caching = false assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('robber', :cache => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), stylesheet_link_tag('robber', :cache => "money") ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) end + # Same as above, but with script_name + def test_caching_stylesheet_link_tag_with_named_paths_and_script_name_when_caching_off + ENV["RAILS_ASSET_ID"] = "" + @request.script_name = "/collaboration/hieraki" + config.perform_caching = false + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag('robber', :cache => true) + ) + + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + + assert_dom_equal( + %(<link href="/collaboration/hieraki/stylesheets/robber.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag('robber', :cache => "money") + ) + assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) + end def test_caching_stylesheet_include_tag_when_caching_off ENV["RAILS_ASSET_ID"] = "" config.perform_caching = false assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true) ) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => true, :recursive => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money") ) assert_dom_equal( - %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" type="text/css" />), + %(<link href="/stylesheets/bank.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/robber.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/subdir/subdir.css" media="screen" rel="stylesheet" />\n<link href="/stylesheets/version.1.0.css" media="screen" rel="stylesheet" />), stylesheet_link_tag(:all, :cache => "money", :recursive => true) ) assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css')) end + + def test_caching_stylesheet_include_tag_with_absolute_uri + ENV["RAILS_ASSET_ID"] = "" + + assert_dom_equal( + %(<link href="/stylesheets/all.css" media="screen" rel="stylesheet" />), + stylesheet_link_tag("/foo/baz", :cache => true) + ) + + FileUtils.rm(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css')) + end end class AssetTagHelperNonVhostTest < ActionView::TestCase @@ -1221,8 +1349,6 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase assert_dom_equal(%(/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) assert_dom_equal(%(/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) assert_dom_equal(%(/collaboration/hieraki/images/xml.png), image_path("xml.png")) - assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='/collaboration/hieraki/images/mouse.png'" src="/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) - assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='/collaboration/hieraki/images/mouse2.png'" src="/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) end def test_should_ignore_relative_root_path_on_complete_url @@ -1235,8 +1361,6 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) - assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) - assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) end def test_should_compute_proper_path_with_asset_host_and_default_protocol @@ -1245,8 +1369,6 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr")) assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/stylesheets/style.css), stylesheet_path("style")) assert_dom_equal(%(gopher://assets.example.com/collaboration/hieraki/images/xml.png), image_path("xml.png")) - assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse.png" />), image_tag("mouse.png", :mouseover => "/images/mouse_over.png")) - assert_dom_equal(%(<img alt="Mouse2" onmouseover="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse_over2.png'" onmouseout="this.src='gopher://assets.example.com/collaboration/hieraki/images/mouse2.png'" src="gopher://assets.example.com/collaboration/hieraki/images/mouse2.png" />), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png"))) end def test_should_compute_proper_url_with_asset_host @@ -1267,12 +1389,12 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase def test_should_ignore_asset_host_on_complete_url @controller.config.asset_host = "http://assets.example.com" - assert_dom_equal(%(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("http://bar.example.com/stylesheets/style.css")) + assert_dom_equal(%(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" />), stylesheet_link_tag("http://bar.example.com/stylesheets/style.css")) end def test_should_ignore_asset_host_on_scheme_relative_url @controller.config.asset_host = "http://assets.example.com" - assert_dom_equal(%(<link href="//bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" type="text/css" />), stylesheet_link_tag("//bar.example.com/stylesheets/style.css")) + assert_dom_equal(%(<link href="//bar.example.com/stylesheets/style.css" media="screen" rel="stylesheet" />), stylesheet_link_tag("//bar.example.com/stylesheets/style.css")) end def test_should_wildcard_asset_host_between_zero_and_four diff --git a/actionpack/test/template/atom_feed_helper_test.rb b/actionpack/test/template/atom_feed_helper_test.rb index d26aa9aa85..89aae4ac56 100644 --- a/actionpack/test/template/atom_feed_helper_test.rb +++ b/actionpack/test/template/atom_feed_helper_test.rb @@ -45,6 +45,23 @@ class ScrollsController < ActionController::Base end end EOT + FEEDS["entry_type_options"] = <<-EOT + atom_feed(:schema_date => '2008') do |feed| + feed.title("My great blog!") + feed.updated((@scrolls.first.created_at)) + + @scrolls.each do |scroll| + feed.entry(scroll, :type => 'text/xml') do |entry| + entry.title(scroll.title) + entry.content(scroll.body, :type => 'html') + + entry.author do |author| + author.name("DHH") + end + end + end + end + EOT FEEDS["xml_block"] = <<-EOT atom_feed do |feed| feed.title("My great blog!") @@ -306,6 +323,20 @@ class AtomFeedTest < ActionController::TestCase end end + def test_feed_entry_type_option_default_to_text_html + with_restful_routing(:scrolls) do + get :index, :id => 'defaults' + assert_select "entry link[rel=alternate][type=text/html]" + end + end + + def test_feed_entry_type_option_specified + with_restful_routing(:scrolls) do + get :index, :id => 'entry_type_options' + assert_select "entry link[rel=alternate][type=text/xml]" + end + end + private def with_restful_routing(resources) with_routing do |set| diff --git a/actionpack/test/template/benchmark_helper_test.rb b/actionpack/test/template/benchmark_helper_test.rb index 1bdda22959..8c198d2562 100644 --- a/actionpack/test/template/benchmark_helper_test.rb +++ b/actionpack/test/template/benchmark_helper_test.rb @@ -19,6 +19,6 @@ class BenchmarkHelperTest < ActionView::TestCase log = StringIO.new self.stubs(:logger).returns(Logger.new(log)) benchmark {} - assert_match(log.rewind && log.read, /Benchmarking \(\d+.\d+ms\)/) + assert_match(/Benchmarking \(\d+.\d+ms\)/, log.rewind && log.read) end end diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index 17469f8c3e..234ac3252d 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -56,7 +56,7 @@ class CaptureHelperTest < ActionView::TestCase def test_content_for_with_multiple_calls_and_flush assert ! content_for?(:title) content_for :title, 'foo' - content_for :title, 'bar', true + content_for :title, 'bar', flush: true assert_equal 'bar', content_for(:title) end @@ -75,7 +75,7 @@ class CaptureHelperTest < ActionView::TestCase content_for :title do 'foo' end - content_for :title, true do + content_for :title, flush: true do 'bar' end assert_equal 'bar', content_for(:title) @@ -86,7 +86,7 @@ class CaptureHelperTest < ActionView::TestCase content_for :title do 'foo' end - content_for :title, nil, true do + content_for :title, nil, flush: true do 'bar' end assert_equal 'bar', content_for(:title) @@ -97,7 +97,7 @@ class CaptureHelperTest < ActionView::TestCase content_for :title do 'foo' end - content_for :title, false do + content_for :title, flush: false do 'bar' end assert_equal 'foobar', content_for(:title) @@ -117,11 +117,11 @@ class CaptureHelperTest < ActionView::TestCase def test_content_for_with_whitespace_block_and_flush assert ! content_for?(:title) content_for :title, 'foo' - content_for :title, true do + content_for :title, flush: true do output_buffer << " \n " nil end - content_for :title, 'bar', true + content_for :title, 'bar', flush: true assert_equal 'bar', content_for(:title) end @@ -131,9 +131,9 @@ class CaptureHelperTest < ActionView::TestCase assert_equal nil, content_for(:title) { output_buffer << 'bar'; nil } assert_equal nil, content_for(:title) { output_buffer << " \n "; nil } assert_equal 'foobar', content_for(:title) - assert_equal nil, content_for(:title, 'foo', true) - assert_equal nil, content_for(:title, true) { output_buffer << 'bar'; nil } - assert_equal nil, content_for(:title, true) { output_buffer << " \n "; nil } + assert_equal nil, content_for(:title, 'foo', flush: true) + assert_equal nil, content_for(:title, flush: true) { output_buffer << 'bar'; nil } + assert_equal nil, content_for(:title, flush: true) { output_buffer << " \n "; nil } assert_equal 'bar', content_for(:title) end diff --git a/actionpack/test/template/compressors_test.rb b/actionpack/test/template/compressors_test.rb deleted file mode 100644 index a273f15bd7..0000000000 --- a/actionpack/test/template/compressors_test.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'abstract_unit' -require 'sprockets/compressors' - -class CompressorsTest < ActiveSupport::TestCase - def test_register_css_compressor - Sprockets::Compressors.register_css_compressor(:null, Sprockets::NullCompressor) - compressor = Sprockets::Compressors.registered_css_compressor(:null) - assert_kind_of Sprockets::NullCompressor, compressor - end - - def test_register_js_compressor - Sprockets::Compressors.register_js_compressor(:uglifier, 'Uglifier', :require => 'uglifier') - compressor = Sprockets::Compressors.registered_js_compressor(:uglifier) - assert_kind_of Uglifier, compressor - end - - def test_register_default_css_compressor - Sprockets::Compressors.register_css_compressor(:null, Sprockets::NullCompressor, :default => true) - compressor = Sprockets::Compressors.registered_css_compressor(:default) - assert_kind_of Sprockets::NullCompressor, compressor - end - - def test_register_default_js_compressor - Sprockets::Compressors.register_js_compressor(:null, Sprockets::NullCompressor, :default => true) - compressor = Sprockets::Compressors.registered_js_compressor(:default) - assert_kind_of Sprockets::NullCompressor, compressor - end -end diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb index 82b62e64f3..63066d40cd 100644 --- a/actionpack/test/template/date_helper_i18n_test.rb +++ b/actionpack/test/template/date_helper_i18n_test.rb @@ -12,24 +12,24 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase def test_distance_of_time_in_words_calls_i18n { # with include_seconds - [2.seconds, true] => [:'less_than_x_seconds', 5], - [9.seconds, true] => [:'less_than_x_seconds', 10], - [19.seconds, true] => [:'less_than_x_seconds', 20], - [30.seconds, true] => [:'half_a_minute', nil], - [59.seconds, true] => [:'less_than_x_minutes', 1], - [60.seconds, true] => [:'x_minutes', 1], + [2.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 5], + [9.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 10], + [19.seconds, { :include_seconds => true }] => [:'less_than_x_seconds', 20], + [30.seconds, { :include_seconds => true }] => [:'half_a_minute', nil], + [59.seconds, { :include_seconds => true }] => [:'less_than_x_minutes', 1], + [60.seconds, { :include_seconds => true }] => [:'x_minutes', 1], # without include_seconds - [29.seconds, false] => [:'less_than_x_minutes', 1], - [60.seconds, false] => [:'x_minutes', 1], - [44.minutes, false] => [:'x_minutes', 44], - [61.minutes, false] => [:'about_x_hours', 1], - [24.hours, false] => [:'x_days', 1], - [30.days, false] => [:'about_x_months', 1], - [60.days, false] => [:'x_months', 2], - [1.year, false] => [:'about_x_years', 1], - [3.years + 6.months, false] => [:'over_x_years', 3], - [3.years + 10.months, false] => [:'almost_x_years', 4] + [29.seconds, { :include_seconds => false }] => [:'less_than_x_minutes', 1], + [60.seconds, { :include_seconds => false }] => [:'x_minutes', 1], + [44.minutes, { :include_seconds => false }] => [:'x_minutes', 44], + [61.minutes, { :include_seconds => false }] => [:'about_x_hours', 1], + [24.hours, { :include_seconds => false }] => [:'x_days', 1], + [30.days, { :include_seconds => false }] => [:'about_x_months', 1], + [60.days, { :include_seconds => false }] => [:'x_months', 2], + [1.year, { :include_seconds => false }] => [:'about_x_years', 1], + [3.years + 6.months, { :include_seconds => false }] => [:'over_x_years', 3], + [3.years + 10.months, { :include_seconds => false }] => [:'almost_x_years', 4] }.each do |passed, expected| assert_distance_of_time_in_words_translates_key passed, expected @@ -37,7 +37,7 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase end def assert_distance_of_time_in_words_translates_key(passed, expected) - diff, include_seconds = *passed + diff, passed_options = *passed key, count = *expected to = @from + diff @@ -45,7 +45,12 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase options[:count] = count if count I18n.expects(:t).with(key, options) - distance_of_time_in_words(@from, to, include_seconds, :locale => 'en') + distance_of_time_in_words(@from, to, passed_options.merge(:locale => 'en')) + 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') end def test_distance_of_time_pluralizations diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index 9e2f4ec347..a4da7cd4b0 100644 --- a/actionpack/test/template/date_helper_test.rb +++ b/actionpack/test/template/date_helper_test.rb @@ -21,56 +21,80 @@ class DateHelperTest < ActionView::TestCase def assert_distance_of_time_in_words(from, to=nil) to ||= from - # 0..1 with include_seconds - assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 0.seconds, true) - assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 4.seconds, true) - assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 5.seconds, true) - assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 9.seconds, true) - assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 10.seconds, true) - assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 19.seconds, true) - assert_equal "half a minute", distance_of_time_in_words(from, to + 20.seconds, true) - assert_equal "half a minute", distance_of_time_in_words(from, to + 39.seconds, true) - assert_equal "less than a minute", distance_of_time_in_words(from, to + 40.seconds, true) - assert_equal "less than a minute", distance_of_time_in_words(from, to + 59.seconds, true) - assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, true) - assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, true) - - # First case 0..1 + # 0..1 minute with :include_seconds => true + assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 0.seconds, :include_seconds => true) + assert_equal "less than 5 seconds", distance_of_time_in_words(from, to + 4.seconds, :include_seconds => true) + assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 5.seconds, :include_seconds => true) + assert_equal "less than 10 seconds", distance_of_time_in_words(from, to + 9.seconds, :include_seconds => true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 10.seconds, :include_seconds => true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from, to + 19.seconds, :include_seconds => true) + assert_equal "half a minute", distance_of_time_in_words(from, to + 20.seconds, :include_seconds => true) + assert_equal "half a minute", distance_of_time_in_words(from, to + 39.seconds, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 40.seconds, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 59.seconds, :include_seconds => true) + assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, :include_seconds => true) + assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, :include_seconds => true) + + # 0..1 minute with :include_seconds => false + assert_equal "less than a minute", distance_of_time_in_words(from, to + 0.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 4.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 5.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 9.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 10.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 19.seconds, :include_seconds => false) + assert_equal "less than a minute", distance_of_time_in_words(from, to + 20.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 39.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 40.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 59.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 60.seconds, :include_seconds => false) + assert_equal "1 minute", distance_of_time_in_words(from, to + 89.seconds, :include_seconds => false) + + # Note that we are including a 30-second boundary around the interval we + # want to test. For instance, "1 minute" is actually 30s to 1m29s. The + # reason for doing this is simple -- in `distance_of_time_to_words`, when we + # take the distance between our two Time objects in seconds and convert it + # to minutes, we round the number. So 29s gets rounded down to 0m, 30s gets + # rounded up to 1m, and 1m29s gets rounded down to 1m. A similar thing + # happens with the other cases. + + # First case 0..1 minute assert_equal "less than a minute", distance_of_time_in_words(from, to + 0.seconds) assert_equal "less than a minute", distance_of_time_in_words(from, to + 29.seconds) assert_equal "1 minute", distance_of_time_in_words(from, to + 30.seconds) assert_equal "1 minute", distance_of_time_in_words(from, to + 1.minutes + 29.seconds) - # 2..44 + # 2 minutes up to 45 minutes assert_equal "2 minutes", distance_of_time_in_words(from, to + 1.minutes + 30.seconds) assert_equal "44 minutes", distance_of_time_in_words(from, to + 44.minutes + 29.seconds) - # 45..89 + # 45 minutes up to 90 minutes assert_equal "about 1 hour", distance_of_time_in_words(from, to + 44.minutes + 30.seconds) assert_equal "about 1 hour", distance_of_time_in_words(from, to + 89.minutes + 29.seconds) - # 90..1439 + # 90 minutes up to 24 hours assert_equal "about 2 hours", distance_of_time_in_words(from, to + 89.minutes + 30.seconds) assert_equal "about 24 hours", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 29.seconds) - # 1440..2519 + # 24 hours up to 42 hours assert_equal "1 day", distance_of_time_in_words(from, to + 23.hours + 59.minutes + 30.seconds) assert_equal "1 day", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 29.seconds) - # 2520..43199 + # 42 hours up to 30 days assert_equal "2 days", distance_of_time_in_words(from, to + 41.hours + 59.minutes + 30.seconds) assert_equal "3 days", distance_of_time_in_words(from, to + 2.days + 12.hours) assert_equal "30 days", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 29.seconds) - # 43200..86399 + # 30 days up to 60 days assert_equal "about 1 month", distance_of_time_in_words(from, to + 29.days + 23.hours + 59.minutes + 30.seconds) - assert_equal "about 1 month", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 29.seconds) + assert_equal "about 1 month", distance_of_time_in_words(from, to + 44.days + 23.hours + 59.minutes + 29.seconds) + assert_equal "about 2 months", distance_of_time_in_words(from, to + 44.days + 23.hours + 59.minutes + 30.seconds) + assert_equal "about 2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 29.seconds) - # 86400..525599 + # 60 days up to 365 days assert_equal "2 months", distance_of_time_in_words(from, to + 59.days + 23.hours + 59.minutes + 30.seconds) assert_equal "12 months", distance_of_time_in_words(from, to + 1.years - 31.seconds) - # > 525599 + # >= 365 days assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years - 30.seconds) assert_equal "about 1 year", distance_of_time_in_words(from, to + 1.years + 3.months - 1.day) assert_equal "over 1 year", distance_of_time_in_words(from, to + 1.years + 6.months) @@ -95,7 +119,8 @@ class DateHelperTest < ActionView::TestCase # test to < from assert_equal "about 4 hours", distance_of_time_in_words(from + 4.hours, to) - assert_equal "less than 20 seconds", distance_of_time_in_words(from + 19.seconds, to, true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from + 19.seconds, to, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(from + 19.seconds, to, :include_seconds => false) end def test_distance_in_words @@ -103,6 +128,11 @@ class DateHelperTest < ActionView::TestCase assert_distance_of_time_in_words(from) end + def test_time_ago_in_words_passes_include_seconds + assert_equal "less than 20 seconds", time_ago_in_words(15.seconds.ago, :include_seconds => true) + assert_equal "less than a minute", time_ago_in_words(15.seconds.ago, :include_seconds => false) + end + def test_distance_in_words_with_time_zones from = Time.mktime(2004, 6, 6, 21, 45, 0) assert_distance_of_time_in_words(from.in_time_zone('Alaska')) @@ -125,13 +155,33 @@ class DateHelperTest < ActionView::TestCase start_date = Date.new 1982, 12, 3 end_date = Date.new 2010, 11, 30 assert_equal("almost 28 years", distance_of_time_in_words(start_date, end_date)) + assert_equal("almost 28 years", distance_of_time_in_words(end_date, start_date)) end def test_distance_in_words_with_integers - assert_equal "less than a minute", distance_of_time_in_words(59) + assert_equal "1 minute", distance_of_time_in_words(59) assert_equal "about 1 hour", distance_of_time_in_words(60*60) - assert_equal "less than a minute", distance_of_time_in_words(0, 59) + assert_equal "1 minute", distance_of_time_in_words(0, 59) assert_equal "about 1 hour", distance_of_time_in_words(60*60, 0) + assert_equal "about 3 years", distance_of_time_in_words(10**8) + assert_equal "about 3 years", distance_of_time_in_words(0, 10**8) + end + + def test_distance_in_words_with_times + assert_equal "1 minute", distance_of_time_in_words(30.seconds) + assert_equal "1 minute", distance_of_time_in_words(59.seconds) + assert_equal "2 minutes", distance_of_time_in_words(119.seconds) + assert_equal "2 minutes", distance_of_time_in_words(1.minute + 59.seconds) + assert_equal "3 minutes", distance_of_time_in_words(2.minute + 30.seconds) + assert_equal "44 minutes", distance_of_time_in_words(44.minutes + 29.seconds) + assert_equal "about 1 hour", distance_of_time_in_words(44.minutes + 30.seconds) + assert_equal "about 1 hour", distance_of_time_in_words(60.minutes) + + # include seconds + assert_equal "half a minute", distance_of_time_in_words(39.seconds, 0, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(40.seconds, 0, :include_seconds => true) + assert_equal "less than a minute", distance_of_time_in_words(59.seconds, 0, :include_seconds => true) + assert_equal "1 minute", distance_of_time_in_words(60.seconds, 0, :include_seconds => true) end def test_time_ago_in_words @@ -567,7 +617,7 @@ class DateHelperTest < ActionView::TestCase end def test_select_minute_with_html_options - expected = expected = %(<select id="date_minute" name="date[minute]" class="selector" accesskey="M">\n) + expected = %(<select id="date_minute" name="date[minute]" class="selector" accesskey="M">\n) expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">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<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) expected << "</select>\n" @@ -711,7 +761,7 @@ class DateHelperTest < ActionView::TestCase # Since the order is incomplete nothing will be shown expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n) expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) - expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="1" />\n) assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :order => [:day]) end @@ -943,11 +993,20 @@ class DateHelperTest < ActionView::TestCase expected << "</select>\n" expected << %(<input type="hidden" id="date_first_month" name="date[first][month]" value="8" />\n) - expected << %(<input type="hidden" id="date_first_day" name="date[first][day]" value="16" />\n) + expected << %(<input type="hidden" id="date_first_day" name="date[first][day]" value="1" />\n) assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :discard_month => true, :discard_day => true, :start_year => 2003, :end_year => 2005, :prefix => "date[first]"}) end + def test_select_date_with_hidden + expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003"/>\n) + expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + + assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :prefix => "date[first]", :use_hidden => true }) + assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :prefix => "date[first]", :use_hidden => true }) + end + def test_select_datetime expected = %(<select id="date_first_year" name="date[first][year]">\n) expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) @@ -1184,6 +1243,47 @@ class DateHelperTest < ActionView::TestCase :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year', :hour => 'Choose hour', :minute => 'Choose minute'}) end + def test_select_datetime_with_custom_hours + expected = %(<select id="date_first_year" name="date[first][year]">\n) + expected << %(<option value="">Choose year</option>\n<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + expected << %(<select id="date_first_month" name="date[first][month]">\n) + expected << %(<option value="">Choose month</option>\n<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">July</option>\n<option value="8" selected="selected">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="date_first_day" name="date[first][day]">\n) + expected << %(<option value="">Choose day</option>\n<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">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" selected="selected">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" + + expected << " — " + + expected << %(<select id="date_first_hour" name="date[first][hour]">\n) + expected << %(<option value="">Choose hour</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n) + expected << "</select>\n" + + expected << " : " + + expected << %(<select id="date_first_minute" name="date[first][minute]">\n) + expected << %(<option value="">Choose minute</option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">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<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :start_year => 2003, :end_year => 2005, :start_hour => 1, :end_hour => 9, :prefix => "date[first]", + :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year', :hour => 'Choose hour', :minute => 'Choose minute'}) + end + + def test_select_datetime_with_hidden + expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n) + expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + expected << %(<input id="date_first_hour" name="date[first][hour]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_minute" name="date[first][minute]" type="hidden" value="4" />\n) + + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :prefix => "date[first]", :use_hidden => true) + assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), :datetime_separator => "—", :date_separator => "/", + :time_separator => ":", :prefix => "date[first]", :use_hidden => true) + end + def test_select_time expected = %(<input name="date[year]" id="date_year" value="2003" type="hidden" />\n) expected << %(<input name="date[month]" id="date_month" value="8" type="hidden" />\n) @@ -1359,6 +1459,17 @@ class DateHelperTest < ActionView::TestCase :prompt => {:hour => 'Choose hour', :minute => 'Choose minute', :second => 'Choose seconds'}) end + def test_select_time_with_hidden + expected = %(<input id="date_first_year" name="date[first][year]" type="hidden" value="2003" />\n) + expected << %(<input id="date_first_month" name="date[first][month]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_day" name="date[first][day]" type="hidden" value="16" />\n) + expected << %(<input id="date_first_hour" name="date[first][hour]" type="hidden" value="8" />\n) + expected << %(<input id="date_first_minute" name="date[first][minute]" type="hidden" value="4" />\n) + + assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :prefix => "date[first]", :use_hidden => true) + assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :time_separator => ":", :prefix => "date[first]", :use_hidden => true) + end + def test_date_select @post = Post.new @post.written_on = Date.new(2004, 6, 15) @@ -1396,6 +1507,20 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, date_select("post", "written_on", :order => [ :month, :year ]) end + def test_date_select_without_day_and_month + @post = Post.new + @post.written_on = Date.new(2004, 2, 29) + + expected = "<input type=\"hidden\" id=\"post_written_on_2i\" name=\"post[written_on(2i)]\" value=\"2\" />\n" + expected << "<input type=\"hidden\" id=\"post_written_on_3i\" name=\"post[written_on(3i)]\" value=\"1\" />\n" + + 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 value="2004" selected="selected">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" + + assert_dom_equal expected, date_select("post", "written_on", :order => [ :year ]) + end + def test_date_select_without_day_with_separator @post = Post.new @post.written_on = Date.new(2004, 6, 15) @@ -2118,6 +2243,18 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, datetime_select("post", "updated_at", { :date_separator => " / ", :datetime_separator => " , ", :time_separator => " - ", :include_seconds => true }) end + def test_datetime_select_with_integer + @post = Post.new + @post.updated_at = 3 + datetime_select("post", "updated_at") + end + + def test_datetime_select_with_infinity # Float + @post = Post.new + @post.updated_at = (-1.0/0) + datetime_select("post", "updated_at") + end + def test_datetime_select_with_default_prompt @post = Post.new @post.updated_at = nil @@ -2427,7 +2564,7 @@ class DateHelperTest < ActionView::TestCase 1999.upto(2009) { |i| expected << %(<option value="#{i}"#{' selected="selected"' if i == 2004}>#{i}</option>\n) } expected << "</select>\n" expected << %{<input type="hidden" id="post_updated_at_2i" name="post[updated_at(2i)]" value="6" />\n} - expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="15" />\n} + expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="1" />\n} expected << " — " @@ -2448,7 +2585,7 @@ class DateHelperTest < ActionView::TestCase expected = %{<input type="hidden" id="post_updated_at_1i" name="post[updated_at(1i)]" value="2004" />\n} expected << %{<input type="hidden" id="post_updated_at_2i" name="post[updated_at(2i)]" value="6" />\n} - expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="15" />\n} + expected << %{<input type="hidden" id="post_updated_at_3i" name="post[updated_at(3i)]" value="1" />\n} expected << %{<select id="post_updated_at_4i" name="post[updated_at(4i)]">\n} 0.upto(23) { |i| expected << %(<option value="#{sprintf("%02d", i)}"#{' selected="selected"' if i == 15}>#{sprintf("%02d", i)}</option>\n) } @@ -2467,7 +2604,7 @@ class DateHelperTest < ActionView::TestCase expected = %{<input type="hidden" id="post_updated_at_1i" disabled="disabled" name="post[updated_at(1i)]" value="2004" />\n} expected << %{<input type="hidden" id="post_updated_at_2i" disabled="disabled" name="post[updated_at(2i)]" value="6" />\n} - expected << %{<input type="hidden" id="post_updated_at_3i" disabled="disabled" name="post[updated_at(3i)]" value="15" />\n} + expected << %{<input type="hidden" id="post_updated_at_3i" disabled="disabled" name="post[updated_at(3i)]" value="1" />\n} expected << %{<select id="post_updated_at_4i" disabled="disabled" name="post[updated_at(4i)]">\n} 0.upto(23) { |i| expected << %(<option value="#{sprintf("%02d", i)}"#{' selected="selected"' if i == 15}>#{sprintf("%02d", i)}</option>\n) } @@ -2521,6 +2658,30 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, datetime_select("post", "updated_at", :discard_minute => true) end + def test_datetime_select_disabled_and_discard_minute + @post = Post.new + @post.updated_at = Time.local(2004, 6, 15, 15, 16, 35) + + expected = %{<select id="post_updated_at_1i" disabled="disabled" name="post[updated_at(1i)]">\n} + 1999.upto(2009) { |i| expected << %(<option value="#{i}"#{' selected="selected"' if i == 2004}>#{i}</option>\n) } + expected << "</select>\n" + expected << %{<select id="post_updated_at_2i" disabled="disabled" name="post[updated_at(2i)]">\n} + 1.upto(12) { |i| expected << %(<option value="#{i}"#{' selected="selected"' if i == 6}>#{Date::MONTHNAMES[i]}</option>\n) } + expected << "</select>\n" + expected << %{<select id="post_updated_at_3i" disabled="disabled" name="post[updated_at(3i)]">\n} + 1.upto(31) { |i| expected << %(<option value="#{i}"#{' selected="selected"' if i == 15}>#{i}</option>\n) } + expected << "</select>\n" + + expected << " — " + + expected << %{<select id="post_updated_at_4i" disabled="disabled" name="post[updated_at(4i)]">\n} + 0.upto(23) { |i| expected << %(<option value="#{sprintf("%02d", i)}"#{' selected="selected"' if i == 15}>#{sprintf("%02d", i)}</option>\n) } + expected << "</select>\n" + expected << %{<input type="hidden" id="post_updated_at_5i" disabled="disabled" name="post[updated_at(5i)]" value="16" />\n} + + assert_dom_equal expected, datetime_select("post", "updated_at", :discard_minute => true, :disabled => true) + end + def test_datetime_select_invalid_order @post = Post.new @post.updated_at = Time.local(2004, 6, 15, 15, 16, 35) @@ -2865,6 +3026,10 @@ class DateHelperTest < ActionView::TestCase assert_match(/<time.*>Right now<\/time>/, time_tag(Time.now, 'Right now')) end + def test_time_tag_with_given_block + assert_match(/<time.*><span>Right now<\/span><\/time>/, time_tag(Time.now){ '<span>Right now</span>'.html_safe }) + end + def test_time_tag_with_different_format time = Time.now expected = "<time datetime=\"#{time.xmlschema}\">#{I18n.l(time, :format => :short)}</time>" diff --git a/actionpack/test/template/digestor_test.rb b/actionpack/test/template/digestor_test.rb new file mode 100644 index 0000000000..01b101cb49 --- /dev/null +++ b/actionpack/test/template/digestor_test.rb @@ -0,0 +1,160 @@ +require 'abstract_unit' +require 'fileutils' + +class FixtureTemplate + attr_reader :source + + def initialize(template_path) + @source = File.read(template_path) + rescue Errno::ENOENT + raise ActionView::MissingTemplate.new([], "", [], true, []) + end +end + +class FixtureFinder + FIXTURES_DIR = "#{File.dirname(__FILE__)}/../fixtures/digestor" + TMP_DIR = "#{File.dirname(__FILE__)}/../tmp" + + def find(logical_name, keys, partial, options) + FixtureTemplate.new("#{TMP_DIR}/digestor/#{partial ? logical_name.gsub(%r|/([^/]+)$|, '/_\1') : logical_name}.#{options[:formats].first}.erb") + end +end + +class TemplateDigestorTest < ActionView::TestCase + def setup + FileUtils.cp_r FixtureFinder::FIXTURES_DIR, FixtureFinder::TMP_DIR + end + + def teardown + FileUtils.rm_r File.join(FixtureFinder::TMP_DIR, "digestor") + ActionView::Digestor.cache.clear + end + + def test_top_level_change_reflected + assert_digest_difference("messages/show") do + change_template("messages/show") + end + end + + def test_explicit_dependency + assert_digest_difference("messages/show") do + change_template("messages/_message") + end + end + + def test_second_level_dependency + assert_digest_difference("messages/show") do + change_template("comments/_comments") + end + end + + def test_second_level_dependency_within_same_directory + assert_digest_difference("messages/show") do + change_template("messages/_header") + end + end + + def test_third_level_dependency + assert_digest_difference("messages/show") do + change_template("comments/_comment") + end + end + + def test_logging_of_missing_template + assert_logged "Couldn't find template for digesting: messages/something_missing.html" do + digest("messages/show") + end + end + + def test_nested_template_directory + assert_digest_difference("messages/show") do + change_template("messages/actions/_move") + end + end + + def test_dont_generate_a_digest_for_missing_templates + assert_equal '', digest("nothing/there") + end + + def test_collection_dependency + assert_digest_difference("messages/index") do + change_template("messages/_message") + end + + assert_digest_difference("messages/index") do + change_template("events/_event") + end + end + + def test_collection_derived_from_record_dependency + assert_digest_difference("messages/show") do + change_template("events/_event") + end + end + + def test_extra_whitespace_in_render_partial + assert_digest_difference("messages/edit") do + change_template("messages/_form") + end + end + + def test_extra_whitespace_in_render_named_partial + assert_digest_difference("messages/edit") do + change_template("messages/_header") + end + end + + def test_extra_whitespace_in_render_record + assert_digest_difference("messages/edit") do + change_template("messages/_message") + end + end + + def test_extra_whitespace_in_render_with_parenthesis + assert_digest_difference("messages/edit") do + change_template("events/_event") + end + end + + def test_old_style_hash_in_render_invocation + assert_digest_difference("messages/edit") do + change_template("comments/_comment") + end + end + + private + def assert_logged(message) + old_logger = ActionView::Base.logger + log = StringIO.new + ActionView::Base.logger = Logger.new(log) + + begin + yield + + log.rewind + assert_match message, log.read + ensure + ActionView::Base.logger = old_logger + end + end + + def assert_digest_difference(template_name) + previous_digest = digest(template_name) + ActionView::Digestor.cache.clear + + yield + + assert previous_digest != digest(template_name), "digest didn't change" + ActionView::Digestor.cache.clear + end + + def digest(template_name) + ActionView::Digestor.digest(template_name, :html, FixtureFinder.new) + end + + def change_template(template_name) + File.open("#{FixtureFinder::TMP_DIR}/digestor/#{template_name}.html.erb", "w") do |f| + f.write "\nTHIS WAS CHANGED!" + end + end +end diff --git a/actionpack/test/template/erb/helper.rb b/actionpack/test/template/erb/helper.rb index 799f9e4036..a1973068d5 100644 --- a/actionpack/test/template/erb/helper.rb +++ b/actionpack/test/template/erb/helper.rb @@ -1,5 +1,6 @@ module ERBTest class ViewContext + include ActionView::Helpers::UrlHelper include SharedTestRoutes.url_helpers include ActionView::Helpers::TagHelper include ActionView::Helpers::JavaScriptHelper @@ -20,4 +21,4 @@ module ERBTest "<%= #{str} do %>#{rest}<% end %>" end end -end
\ No newline at end of file +end diff --git a/actionpack/test/template/erb/tag_helper_test.rb b/actionpack/test/template/erb/tag_helper_test.rb index a384e94766..84e328d8be 100644 --- a/actionpack/test/template/erb/tag_helper_test.rb +++ b/actionpack/test/template/erb/tag_helper_test.rb @@ -3,20 +3,17 @@ require "template/erb/helper" module ERBTest class TagHelperTest < BlockTestCase - - extend ActiveSupport::Testing::Declarative - test "percent equals works for content_tag and does not require parenthesis on method call" do assert_equal "<div>Hello world</div>", render_content("content_tag :div", "Hello world") end test "percent equals works for javascript_tag" do - expected_output = "<script type=\"text/javascript\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" + expected_output = "<script>\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" assert_equal expected_output, render_content("javascript_tag", "alert('Hello')") end test "percent equals works for javascript_tag with options" do - expected_output = "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" + expected_output = "<script id=\"the_js_tag\">\n//<![CDATA[\nalert('Hello')\n//]]>\n</script>" assert_equal expected_output, render_content("javascript_tag(:id => 'the_js_tag')", "alert('Hello')") end @@ -30,4 +27,4 @@ module ERBTest assert_equal expected_output, render_content("field_set_tag('foo')", "<%= 'hello' %>") end end -end
\ No newline at end of file +end diff --git a/actionpack/test/template/erb_util_test.rb b/actionpack/test/template/erb_util_test.rb index ca2710e9b3..3e5b029cea 100644 --- a/actionpack/test/template/erb_util_test.rb +++ b/actionpack/test/template/erb_util_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'active_support/core_ext/object/inclusion' class ErbUtilTest < ActiveSupport::TestCase include ERB::Util @@ -8,11 +7,11 @@ class ErbUtilTest < ActiveSupport::TestCase define_method "test_html_escape_#{expected.gsub(/\W/, '')}" do assert_equal expected, html_escape(given) end + end - unless given == '"' - define_method "test_json_escape_#{expected.gsub(/\W/, '')}" do - assert_equal ERB::Util::JSON_ESCAPE[given], json_escape(given) - end + ERB::Util::JSON_ESCAPE.each do |given, expected| + define_method "test_json_escape_#{expected.gsub(/\W/, '')}" do + assert_equal ERB::Util::JSON_ESCAPE[given], json_escape(given) end end @@ -40,13 +39,13 @@ class ErbUtilTest < ActiveSupport::TestCase def test_rest_in_ascii (0..127).to_a.map {|int| int.chr }.each do |chr| - next if chr.in?('&"<>') + next if %('"&<>).include?(chr) assert_equal chr, html_escape(chr) end end def test_html_escape_once - assert_equal '1 < 2 & 3', html_escape_once('1 < 2 & 3') + assert_equal '1 <>&"' 2 & 3', html_escape_once('1 <>&"\' 2 & 3') end def test_html_escape_once_returns_unsafe_strings_when_passed_unsafe_strings diff --git a/actionpack/test/template/form_collections_helper_test.rb b/actionpack/test/template/form_collections_helper_test.rb index 4d878635ef..c73e80ed88 100644 --- a/actionpack/test/template/form_collections_helper_test.rb +++ b/actionpack/test/template/form_collections_helper_test.rb @@ -195,6 +195,15 @@ class FormCollectionsHelperTest < ActionView::TestCase assert_no_select 'input[type=checkbox][value=2][checked=checked]' end + test 'collection check boxes accepts selected string values as :checked option' do + collection = (1..3).map{|i| [i, "Category #{i}"] } + with_collection_check_boxes :user, :category_ids, collection, :first, :last, :checked => ['1', '3'] + + assert_select 'input[type=checkbox][value=1][checked=checked]' + assert_select 'input[type=checkbox][value=3][checked=checked]' + assert_no_select 'input[type=checkbox][value=2][checked=checked]' + end + test 'collection check boxes accepts a single checked value' do collection = (1..3).map{|i| [i, "Category #{i}"] } with_collection_check_boxes :user, :category_ids, collection, :first, :last, :checked => 3 diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index e4cb7e02a0..246c4bfada 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'controller/fake_models' -require 'active_support/core_ext/object/inclusion' class FormHelperTest < ActionView::TestCase include RenderERBUtils @@ -82,7 +81,7 @@ class FormHelperTest < ActionView::TestCase @post.tags = [] @post.tags << Tag.new - @blog_post = Blog::Post.new("And his name will be forty and four.", 44) + @car = Car.new("#000FFF") end Routes = ActionDispatch::Routing::RouteSet.new @@ -97,7 +96,7 @@ class FormHelperTest < ActionView::TestCase end end - match "/foo", :to => "controller#action" + get "/foo", :to => "controller#action" root :to => "main#index" end @@ -181,7 +180,7 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put") do + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch') do "<label for=\"post_comments_attributes_0_body\">Write body here</label>" end @@ -198,7 +197,7 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put") do + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch') do "<label for=\"post_tags_attributes_0_value\">Tag</label>" end @@ -249,35 +248,35 @@ class FormHelperTest < ActionView::TestCase end def test_label_with_block_in_erb - assert_equal "<label for=\"post_message\">\n Message\n <input id=\"post_message\" name=\"post[message]\" size=\"30\" type=\"text\" />\n</label>", view.render("test/label_with_block") + assert_equal "<label for=\"post_message\">\n Message\n <input id=\"post_message\" name=\"post[message]\" type=\"text\" />\n</label>", view.render("test/label_with_block") end def test_text_field assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title") + '<input id="post_title" name="post[title]" type="text" value="Hello World" />', text_field("post", "title") ) assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="password" />', password_field("post", "title") + '<input id="post_title" name="post[title]" type="password" />', password_field("post", "title") ) assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="password" value="Hello World" />', password_field("post", "title", :value => @post.title) + '<input id="post_title" name="post[title]" type="password" value="Hello World" />', password_field("post", "title", :value => @post.title) ) assert_dom_equal( - '<input id="person_name" name="person[name]" size="30" type="password" />', password_field("person", "name") + '<input id="person_name" name="person[name]" type="password" />', password_field("person", "name") ) end def test_text_field_with_escapes @post.title = "<b>Hello World</b>" assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="text" value="<b>Hello World</b>" />', text_field("post", "title") + '<input id="post_title" name="post[title]" type="text" value="<b>Hello World</b>" />', text_field("post", "title") ) end def test_text_field_with_html_entities @post.title = "The HTML Entity for & is &" assert_dom_equal( - '<input id="post_title" name="post[title]" size="30" type="text" value="The HTML Entity for & is &amp;" />', + '<input id="post_title" name="post[title]" type="text" value="The HTML Entity for & is &amp;" />', text_field("post", "title") ) end @@ -301,13 +300,18 @@ class FormHelperTest < ActionView::TestCase end def test_text_field_with_nil_value - expected = '<input id="post_title" name="post[title]" size="30" type="text" />' + expected = '<input id="post_title" name="post[title]" type="text" />' assert_dom_equal expected, text_field("post", "title", :value => nil) end + def test_text_field_with_nil_name + expected = '<input id="post_title" type="text" value="Hello World" />' + assert_dom_equal expected, text_field("post", "title", :name => nil) + end + def test_text_field_doesnt_change_param_values object_name = 'post[]' - expected = '<input id="post_123_title" name="post[123][title]" size="30" type="text" value="Hello World" />' + expected = '<input id="post_123_title" name="post[123][title]" type="text" value="Hello World" />' assert_equal expected, text_field(object_name, "title") assert_equal object_name, "post[]" end @@ -341,40 +345,56 @@ class FormHelperTest < ActionView::TestCase end def test_text_field_with_custom_type - assert_dom_equal '<input id="user_email" size="30" name="user[email]" type="email" />', + assert_dom_equal '<input id="user_email" name="user[email]" type="email" />', text_field("user", "email", :type => "email") end - def test_check_box + def test_check_box_is_html_safe assert check_box("post", "secret").html_safe? + end + + def test_check_box_checked_if_object_value_is_same_that_check_value assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + end + + def test_check_box_not_checked_if_object_value_is_same_that_unchecked_value @post.secret = 0 assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + end + + def test_check_box_checked_if_option_checked_is_present assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret" ,{"checked"=>"checked"}) ) + end + + def test_check_box_checked_if_object_value_is_true @post.secret = true assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret?") ) + end + def test_check_box_checked_if_object_value_includes_checked_value @post.secret = ['0'] assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret") ) + @post.secret = ['1'] assert_dom_equal( '<input name="post[secret]" type="hidden" value="0" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" />', @@ -382,12 +402,97 @@ class FormHelperTest < ActionView::TestCase ) end - def test_check_box_with_explicit_checked_and_unchecked_values + def test_check_box_with_include_hidden_false + @post.secret = false + assert_dom_equal('<input id="post_secret" name="post[secret]" type="checkbox" value="1" />', check_box("post", "secret", :include_hidden => false)) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_string @post.secret = "on" assert_dom_equal( '<input name="post[secret]" type="hidden" value="off" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" />', check_box("post", "secret", {}, "on", "off") ) + + @post.secret = "off" + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="off" /><input id="post_secret" name="post[secret]" type="checkbox" value="on" />', + check_box("post", "secret", {}, "on", "off") + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_boolean + @post.secret = false + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="true" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="false" />', + check_box("post", "secret", {}, false, true) + ) + + @post.secret = true + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="true" /><input id="post_secret" name="post[secret]" type="checkbox" value="false" />', + check_box("post", "secret", {}, false, true) + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_integer + @post.secret = 0 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 1 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 2 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_float + @post.secret = 0.0 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 1.1 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = 2.2 + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values_when_object_value_is_big_decimal + @post.secret = BigDecimal.new(0) + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = BigDecimal.new(1) + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) + + @post.secret = BigDecimal.new(2.2, 1) + assert_dom_equal( + '<input name="post[secret]" type="hidden" value="1" /><input id="post_secret" name="post[secret]" type="checkbox" value="0" />', + check_box("post", "secret", {}, 0, 1) + ) end def test_check_box_with_nil_unchecked_value @@ -469,7 +574,7 @@ class FormHelperTest < ActionView::TestCase def test_text_area assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea id="post_body" name="post[body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body") ) end @@ -477,14 +582,14 @@ class FormHelperTest < ActionView::TestCase def test_text_area_with_escapes @post.body = "Back to <i>the</i> hill and over it again!" assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to <i>the</i> hill and over it again!</textarea>', + %{<textarea id="post_body" name="post[body]">\nBack to <i>the</i> hill and over it again!</textarea>}, text_area("post", "body") ) end def test_text_area_with_alternate_value assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">Testing alternate values.</textarea>', + %{<textarea id="post_body" name="post[body]">\nTesting alternate values.</textarea>}, text_area("post", "body", :value => 'Testing alternate values.') ) end @@ -492,25 +597,36 @@ class FormHelperTest < ActionView::TestCase def test_text_area_with_html_entities @post.body = "The HTML Entity for & is &" assert_dom_equal( - '<textarea cols="40" id="post_body" name="post[body]" rows="20">The HTML Entity for & is &amp;</textarea>', + %{<textarea id="post_body" name="post[body]">\nThe HTML Entity for & is &amp;</textarea>}, text_area("post", "body") ) end def test_text_area_with_size_option assert_dom_equal( - '<textarea cols="183" id="post_body" name="post[body]" rows="820">Back to the hill and over it again!</textarea>', + %{<textarea cols="183" id="post_body" name="post[body]" rows="820">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", :size => "183x820") ) end + def test_color_field_with_valid_hex_color_string + expected = %{<input id="car_color" name="car[color]" type="color" value="#000fff" />} + assert_dom_equal(expected, color_field("car", "color")) + end + + def test_color_field_with_invalid_hex_color_string + expected = %{<input id="car_color" name="car[color]" type="color" value="#000000" />} + @car.color = "#1234TR" + assert_dom_equal(expected, color_field("car", "color")) + end + def test_search_field - expected = %{<input id="contact_notes_query" size="30" name="contact[notes_query]" type="search" />} + expected = %{<input id="contact_notes_query" name="contact[notes_query]" type="search" />} assert_dom_equal(expected, search_field("contact", "notes_query")) end def test_telephone_field - expected = %{<input id="user_cell" size="30" name="user[cell]" type="tel" />} + expected = %{<input id="user_cell" name="user[cell]" type="tel" />} assert_dom_equal(expected, telephone_field("user", "cell")) end @@ -525,6 +641,15 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal(expected, date_field("post", "written_on")) end + def test_date_field_with_extra_attrs + expected = %{<input id="post_written_on" step="2" max="2010-08-15" min="2000-06-15" name="post[written_on]" type="date" value="2004-06-15" />} + @post.written_on = DateTime.new(2004, 6, 15) + min_value = DateTime.new(2000, 6, 15) + max_value = DateTime.new(2010, 8, 15) + step = 2 + assert_dom_equal(expected, date_field("post", "written_on", :min => min_value, :max => max_value, :step => step)) + end + def test_date_field_with_timewithzone_value previous_time_zone, Time.zone = Time.zone, 'UTC' expected = %{<input id="post_written_on" name="post[written_on]" type="date" value="2004-06-15" />} @@ -540,13 +665,188 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal(expected, date_field("post", "written_on")) end + def test_time_field + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="00:00:00.000" />} + assert_dom_equal(expected, time_field("post", "written_on")) + end + + def test_time_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + assert_dom_equal(expected, time_field("post", "written_on")) + end + + def test_time_field_with_extra_attrs + expected = %{<input id="post_written_on" step="60" max="10:25:00.000" min="20:45:30.000" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = DateTime.new(2000, 6, 15, 20, 45, 30) + max_value = DateTime.new(2010, 8, 15, 10, 25, 00) + step = 60 + assert_dom_equal(expected, time_field("post", "written_on", :min => min_value, :max => max_value, :step => step)) + end + + def test_time_field_with_timewithzone_value + previous_time_zone, Time.zone = Time.zone, 'UTC' + expected = %{<input id="post_written_on" name="post[written_on]" type="time" value="01:02:03.000" />} + @post.written_on = Time.zone.parse('2004-06-15 01:02:03') + assert_dom_equal(expected, time_field("post", "written_on")) + ensure + Time.zone = previous_time_zone + end + + def test_time_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="time" />} + @post.written_on = nil + assert_dom_equal(expected, time_field("post", "written_on")) + end + + def test_datetime_field + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T00:00:00.000+0000" />} + assert_dom_equal(expected, datetime_field("post", "written_on")) + end + + def test_datetime_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + assert_dom_equal(expected, datetime_field("post", "written_on")) + end + + def test_datetime_field_with_extra_attrs + expected = %{<input id="post_written_on" step="60" max="2010-08-15T10:25:00.000+0000" min="2000-06-15T20:45:30.000+0000" name="post[written_on]" type="datetime" value="2004-06-15T01:02:03.000+0000" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = DateTime.new(2000, 6, 15, 20, 45, 30) + max_value = DateTime.new(2010, 8, 15, 10, 25, 00) + step = 60 + assert_dom_equal(expected, datetime_field("post", "written_on", :min => min_value, :max => max_value, :step => step)) + end + + def test_datetime_field_with_timewithzone_value + previous_time_zone, Time.zone = Time.zone, 'UTC' + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" value="2004-06-15T15:30:45.000+0000" />} + @post.written_on = Time.zone.parse('2004-06-15 15:30:45') + assert_dom_equal(expected, datetime_field("post", "written_on")) + ensure + Time.zone = previous_time_zone + end + + def test_datetime_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime" />} + @post.written_on = nil + assert_dom_equal(expected, datetime_field("post", "written_on")) + end + + def test_datetime_local_field + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T00:00:00" />} + assert_dom_equal(expected, datetime_local_field("post", "written_on")) + end + + def test_datetime_local_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + assert_dom_equal(expected, datetime_local_field("post", "written_on")) + end + + def test_datetime_local_field_with_extra_attrs + expected = %{<input id="post_written_on" step="60" max="2010-08-15T10:25:00" min="2000-06-15T20:45:30" name="post[written_on]" type="datetime-local" value="2004-06-15T01:02:03" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + min_value = DateTime.new(2000, 6, 15, 20, 45, 30) + max_value = DateTime.new(2010, 8, 15, 10, 25, 00) + step = 60 + assert_dom_equal(expected, datetime_local_field("post", "written_on", :min => min_value, :max => max_value, :step => step)) + end + + def test_datetime_local_field_with_timewithzone_value + previous_time_zone, Time.zone = Time.zone, 'UTC' + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" value="2004-06-15T15:30:45" />} + @post.written_on = Time.zone.parse('2004-06-15 15:30:45') + assert_dom_equal(expected, datetime_local_field("post", "written_on")) + ensure + Time.zone = previous_time_zone + end + + def test_datetime_local_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="datetime-local" />} + @post.written_on = nil + assert_dom_equal(expected, datetime_local_field("post", "written_on")) + end + + def test_month_field + expected = %{<input id="post_written_on" name="post[written_on]" type="month" value="2004-06" />} + assert_dom_equal(expected, month_field("post", "written_on")) + end + + def test_month_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="month" />} + @post.written_on = nil + assert_dom_equal(expected, month_field("post", "written_on")) + end + + def test_month_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="month" value="2004-06" />} + @post.written_on = DateTime.new(2004, 6, 15, 1, 2, 3) + assert_dom_equal(expected, month_field("post", "written_on")) + end + + def test_month_field_with_extra_attrs + expected = %{<input id="post_written_on" step="2" max="2010-12" min="2000-02" name="post[written_on]" type="month" value="2004-06" />} + @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) + step = 2 + assert_dom_equal(expected, month_field("post", "written_on", :min => min_value, :max => max_value, :step => step)) + end + + def test_month_field_with_timewithzone_value + previous_time_zone, Time.zone = Time.zone, 'UTC' + expected = %{<input id="post_written_on" name="post[written_on]" type="month" value="2004-06" />} + @post.written_on = Time.zone.parse('2004-06-15 15:30:45') + assert_dom_equal(expected, month_field("post", "written_on")) + ensure + Time.zone = previous_time_zone + end + + def test_week_field + expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W24" />} + assert_dom_equal(expected, week_field("post", "written_on")) + end + + def test_week_field_with_nil_value + expected = %{<input id="post_written_on" name="post[written_on]" type="week" />} + @post.written_on = nil + assert_dom_equal(expected, week_field("post", "written_on")) + end + + def test_week_field_with_datetime_value + expected = %{<input id="post_written_on" name="post[written_on]" type="week" value="2004-W24" />} + @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" />} + @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) + step = 2 + assert_dom_equal(expected, week_field("post", "written_on", :min => min_value, :max => max_value, :step => step)) + end + + 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" />} + @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_url_field - expected = %{<input id="user_homepage" size="30" name="user[homepage]" type="url" />} + expected = %{<input id="user_homepage" name="user[homepage]" type="url" />} assert_dom_equal(expected, url_field("user", "homepage")) end def test_email_field - expected = %{<input id="user_address" size="30" name="user[address]" type="email" />} + expected = %{<input id="user_address" name="user[address]" type="email" />} assert_dom_equal(expected, email_field("user", "address")) end @@ -566,10 +866,10 @@ class FormHelperTest < ActionView::TestCase def test_explicit_name assert_dom_equal( - '<input id="post_title" name="dont guess" size="30" type="text" value="Hello World" />', text_field("post", "title", "name" => "dont guess") + '<input id="post_title" name="dont guess" type="text" value="Hello World" />', text_field("post", "title", "name" => "dont guess") ) assert_dom_equal( - '<textarea cols="40" id="post_body" name="really!" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea id="post_body" name="really!">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "name" => "really!") ) assert_dom_equal( @@ -586,10 +886,10 @@ class FormHelperTest < ActionView::TestCase def test_explicit_id assert_dom_equal( - '<input id="dont guess" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title", "id" => "dont guess") + '<input id="dont guess" name="post[title]" type="text" value="Hello World" />', text_field("post", "title", "id" => "dont guess") ) assert_dom_equal( - '<textarea cols="40" id="really!" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea id="really!" name="post[body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "id" => "really!") ) assert_dom_equal( @@ -606,10 +906,10 @@ class FormHelperTest < ActionView::TestCase def test_nil_id assert_dom_equal( - '<input name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title", "id" => nil) + '<input name="post[title]" type="text" value="Hello World" />', text_field("post", "title", "id" => nil) ) assert_dom_equal( - '<textarea cols="40" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea name="post[body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "id" => nil) ) assert_dom_equal( @@ -636,11 +936,11 @@ class FormHelperTest < ActionView::TestCase def test_index assert_dom_equal( - '<input name="post[5][title]" size="30" id="post_5_title" type="text" value="Hello World" />', + '<input name="post[5][title]" id="post_5_title" type="text" value="Hello World" />', text_field("post", "title", "index" => 5) ) assert_dom_equal( - '<textarea cols="40" name="post[5][body]" id="post_5_body" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea name="post[5][body]" id="post_5_body">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "index" => 5) ) assert_dom_equal( @@ -663,11 +963,11 @@ class FormHelperTest < ActionView::TestCase def test_index_with_nil_id assert_dom_equal( - '<input name="post[5][title]" size="30" type="text" value="Hello World" />', + '<input name="post[5][title]" type="text" value="Hello World" />', text_field("post", "title", "index" => 5, 'id' => nil) ) assert_dom_equal( - '<textarea cols="40" name="post[5][body]" rows="20">Back to the hill and over it again!</textarea>', + %{<textarea name="post[5][body]">\nBack to the hill and over it again!</textarea>}, text_area("post", "body", "index" => 5, 'id' => nil) ) assert_dom_equal( @@ -695,10 +995,10 @@ class FormHelperTest < ActionView::TestCase label("post[]", "title") ) assert_dom_equal( - "<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title") + "<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title") ) assert_dom_equal( - "<textarea cols=\"40\" id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\" rows=\"20\">Back to the hill and over it again!</textarea>", + "<textarea id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\">\nBack to the hill and over it again!</textarea>", text_area("post[]", "body") ) assert_dom_equal( @@ -706,7 +1006,7 @@ class FormHelperTest < ActionView::TestCase check_box("post[]", "secret") ) assert_dom_equal( -"<input checked=\"checked\" id=\"post_#{pid}_title_hello_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Hello World\" />", + "<input checked=\"checked\" id=\"post_#{pid}_title_hello_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Hello World\" />", radio_button("post[]", "title", "Hello World") ) assert_dom_equal("<input id=\"post_#{pid}_title_goodbye_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Goodbye World\" />", @@ -717,11 +1017,11 @@ class FormHelperTest < ActionView::TestCase def test_auto_index_with_nil_id pid = 123 assert_dom_equal( - "<input name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", + "<input name=\"post[#{pid}][title]\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title", :id => nil) ) assert_dom_equal( - "<textarea cols=\"40\" name=\"post[#{pid}][body]\" rows=\"20\">Back to the hill and over it again!</textarea>", + "<textarea name=\"post[#{pid}][body]\">\nBack to the hill and over it again!</textarea>", text_area("post[]", "body", :id => nil) ) assert_dom_equal( @@ -743,6 +1043,20 @@ class FormHelperTest < ActionView::TestCase end end + def test_form_for_requires_arguments + error = assert_raises(ArgumentError) do + form_for(nil, :html => { :id => 'create-post' }) do + end + end + assert_equal "First argument in form cannot contain nil or be empty", error.message + + error = assert_raises(ArgumentError) do + form_for([nil, nil], :html => { :id => 'create-post' }) do + end + end + assert_equal "First argument in form cannot contain nil or be empty", error.message + end + def test_form_for form_for(@post, :html => { :id => 'create-post' }) do |f| concat f.label(:title) { "The Title" } @@ -751,16 +1065,58 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) concat f.submit('Create post') concat f.button('Create post') + concat f.button { + concat content_tag(:span, 'Create post') + } end - expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put") do + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch') do "<label for='post_title'>The Title</label>" + - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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' />" + "<input name='commit' type='submit' value='Create post' />" + - "<button name='button' type='submit'>Create post</button>" + "<button name='button' type='submit'>Create post</button>" + + "<button name='button' type='submit'><span>Create post</span></button>" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_collection_radio_buttons + post = Post.new + def post.active; false; end + form_for(post) do |f| + concat f.collection_radio_buttons(:active, [true, false], :to_s, :to_s) + end + + expected = whole_form("/posts", "new_post" , "new_post") do + "<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' />" + + "<label for='post_active_false'>false</label>" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_collection_check_boxes + post = Post.new + def post.tag_ids; [1, 3]; end + collection = (1..3).map{|i| [i, "Tag #{i}"] } + form_for(post) do |f| + concat f.collection_check_boxes(:tag_ids, collection, :first, :last) + end + + expected = whole_form("/posts", "new_post" , "new_post") do + "<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='' />" end assert_dom_equal expected, output_buffer @@ -773,7 +1129,7 @@ class FormHelperTest < ActionView::TestCase concat f.file_field(:file) end - expected = whole_form("/posts/123", "create-post" , "edit_post", :method => "put", :multipart => true) do + expected = whole_form("/posts/123", "create-post" , "edit_post", :method => 'patch', :multipart => true) do "<input name='post[file]' type='file' id='post_file' />" end @@ -789,7 +1145,7 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form("/posts/123", "edit_post_123" , "edit_post", :method => "put", :multipart => true) do + expected = whole_form("/posts/123", "edit_post_123" , "edit_post", :method => 'patch', :multipart => true) do "<input name='post[comment][file]' type='file' id='post_comment_file' />" end @@ -802,7 +1158,7 @@ class FormHelperTest < ActionView::TestCase concat f.label(:title) end - expected = whole_form("/posts/123.json", "edit_post_123" , "edit_post", :method => "put") do + expected = whole_form("/posts/123.json", "edit_post_123" , "edit_post", :method => 'patch') do "<label for='post_title'>Title</label>" end @@ -810,13 +1166,15 @@ class FormHelperTest < ActionView::TestCase end def test_form_for_with_model_using_relative_model_naming - form_for(@blog_post) do |f| + blog_post = Blog::Post.new("And his name will be forty and four.", 44) + + form_for(blog_post) do |f| concat f.text_field :title concat f.submit('Edit post') end - expected = whole_form("/posts/44", "edit_post_44" , "edit_post", :method => "put") do - "<input name='post[title]' size='30' type='text' id='post_title' value='And his name will be forty and four.' />" + + 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' />" end @@ -832,10 +1190,10 @@ class FormHelperTest < ActionView::TestCase concat f.submit('Create post') end - expected = whole_form("/posts/123", "create-post", "edit_other_name", :method => "put") do + expected = whole_form("/posts/123", "create-post", "edit_other_name", :method => 'patch') do "<label for='other_name_title' class='post_title'>Title</label>" + - "<input name='other_name[title]' size='30' id='other_name_title' value='Hello World' type='text' />" + - "<textarea name='other_name[body]' id='other_name_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='other_name[title]' id='other_name_title' value='Hello World' type='text' />" + + "<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' />" @@ -852,8 +1210,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/", "create-post", "edit_post", "delete") do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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 @@ -869,8 +1227,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/", "create-post", "edit_post", "delete") do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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 @@ -886,22 +1244,22 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/search", "search-post", "new_post", "get") do - "<input name='post[title]' size='30' type='search' id='post_title' />" + "<input name='post[title]' type='search' id='post_title' />" end assert_dom_equal expected, output_buffer end def test_form_for_with_remote - form_for(@post, :url => '/', :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| + form_for(@post, :url => '/', :remote => true, :html => { :id => 'create-post', :method => :patch}) do |f| concat f.text_field(:title) concat f.text_area(:body) concat f.check_box(:secret) end - expected = whole_form("/", "create-post", "edit_post", :method => "put", :remote => true) do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form("/", "create-post", "edit_post", :method => 'patch', :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 @@ -910,15 +1268,15 @@ class FormHelperTest < ActionView::TestCase end def test_form_for_with_remote_in_html - form_for(@post, :url => '/', :html => { :remote => true, :id => 'create-post', :method => :put }) do |f| + form_for(@post, :url => '/', :html => { :remote => true, :id => 'create-post', :method => :patch }) do |f| concat f.text_field(:title) concat f.text_area(:body) concat f.check_box(:secret) end - expected = whole_form("/", "create-post", "edit_post", :method => "put", :remote => true) do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form("/", "create-post", "edit_post", :method => 'patch', :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 @@ -936,8 +1294,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/posts", 'new_post', 'new_post', :remote => true) do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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 @@ -953,8 +1311,8 @@ class FormHelperTest < ActionView::TestCase end expected = whole_form("/", "create-post") do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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 @@ -970,10 +1328,10 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'put') do + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do "<label for='post_123_title'>Title</label>" + - "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" + - "<textarea name='post[123][body]' id='post_123_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[123][title]' type='text' id='post_123_title' value='Hello World' />" + + "<textarea name='post[123][body]' id='post_123_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[123][secret]' type='hidden' value='0' />" + "<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />" end @@ -988,9 +1346,9 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'put') do - "<input name='post[][title]' size='30' type='text' id='post__title' value='Hello World' />" + - "<textarea name='post[][body]' id='post__body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') 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 @@ -998,6 +1356,54 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_label_error_wrapping + form_for(@post) do |f| + concat f.label(:author_name, :class => 'label') + concat f.text_field(:author_name) + concat f.submit('Create post') + end + + expected = whole_form('/posts/123', 'edit_post_123' , 'edit_post', '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' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_label_error_wrapping_without_conventional_instance_variable + post = remove_instance_variable :@post + + form_for(post) do |f| + concat f.label(:author_name, :class => 'label') + concat f.text_field(:author_name) + concat f.submit('Create post') + end + + expected = whole_form('/posts/123', 'edit_post_123' , 'edit_post', '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' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_label_error_wrapping_block_and_non_block_versions + form_for(@post) do |f| + concat f.label(:author_name, 'Name', :class => 'label') + concat f.label(:author_name, :class => 'label') { 'Name' } + end + + expected = whole_form('/posts/123', 'edit_post_123' , 'edit_post', 'patch') do + "<div class='field_with_errors'><label for='post_author_name' class='label'>Name</label></div>" + + "<div class='field_with_errors'><label for='post_author_name' class='label'>Name</label></div>" + end + + assert_dom_equal expected, output_buffer + end + def test_form_for_with_namespace form_for(@post, :namespace => 'namespace') do |f| concat f.text_field(:title) @@ -1005,9 +1411,9 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'put') do - "<input name='post[title]' size='30' type='text' id='namespace_post_title' value='Hello World' />" + - "<textarea name='post[body]' id='namespace_post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'patch') do + "<input name='post[title]' type='text' id='namespace_post_title' value='Hello World' />" + + "<textarea name='post[body]' id='namespace_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='namespace_post_secret' value='1' />" end @@ -1015,15 +1421,23 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_namespace_with_date_select + form_for(@post, :namespace => 'namespace') do |f| + concat f.date_select(:written_on) + end + + assert_select 'select#namespace_post_written_on_1i' + end + def test_form_for_with_namespace_with_label form_for(@post, :namespace => 'namespace') do |f| concat f.label(:title) concat f.text_field(:title) end - expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'put') do + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'patch') do "<label for='namespace_post_title'>Title</label>" + - "<input name='post[title]' size='30' type='text' id='namespace_post_title' value='Hello World' />" + "<input name='post[title]' type='text' id='namespace_post_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1035,9 +1449,9 @@ class FormHelperTest < ActionView::TestCase concat f.text_field(:title) end - expected_1 = whole_form('/posts/123', 'namespace_1_edit_post_123', 'edit_post', 'put') do + expected_1 = whole_form('/posts/123', 'namespace_1_edit_post_123', 'edit_post', 'patch') do "<label for='namespace_1_post_title'>Title</label>" + - "<input name='post[title]' size='30' type='text' id='namespace_1_post_title' value='Hello World' />" + "<input name='post[title]' type='text' id='namespace_1_post_title' value='Hello World' />" end assert_dom_equal expected_1, output_buffer @@ -1047,9 +1461,9 @@ class FormHelperTest < ActionView::TestCase concat f.text_field(:title) end - expected_2 = whole_form('/posts/123', 'namespace_2_edit_post_123', 'edit_post', 'put') do + expected_2 = whole_form('/posts/123', 'namespace_2_edit_post_123', 'edit_post', 'patch') do "<label for='namespace_2_post_title'>Title</label>" + - "<input name='post[title]' size='30' type='text' id='namespace_2_post_title' value='Hello World' />" + "<input name='post[title]' type='text' id='namespace_2_post_title' value='Hello World' />" end assert_dom_equal expected_2, output_buffer @@ -1065,10 +1479,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'put') do - "<input name='post[title]' size='30' type='text' id='namespace_post_title' value='Hello World' />" + - "<textarea name='post[body]' id='namespace_post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + - "<input name='post[comment][body]' size='30' type='text' id='namespace_post_comment_body' value='Hello World' />" + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'patch') do + "<input name='post[title]' type='text' id='namespace_post_title' value='Hello World' />" + + "<textarea name='post[body]' id='namespace_post_body'>\nBack to the hill and over it again!</textarea>" + + "<input name='post[comment][body]' type='text' id='namespace_post_comment_body' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1099,7 +1513,7 @@ class FormHelperTest < ActionView::TestCase concat f.submit end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do "<input name='commit' type='submit' value='Confirm Post changes' />" end @@ -1131,7 +1545,7 @@ class FormHelperTest < ActionView::TestCase concat f.submit end - expected = whole_form('/posts/123', 'edit_another_post', 'edit_another_post', :method => 'put') do + expected = whole_form('/posts/123', 'edit_another_post', 'edit_another_post', :method => 'patch') do "<input name='commit' type='submit' value='Update your Post' />" end @@ -1148,8 +1562,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - "<input name='post[comment][body]' size='30' type='text' id='post_comment_body' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<input name='post[comment][body]' type='text' id='post_comment_body' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1163,9 +1577,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'put') do - "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" + - "<input name='post[123][comment][][name]' size='30' type='text' id='post_123_comment__name' value='new comment' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][title]' type='text' id='post_123_title' value='Hello World' />" + + "<input name='post[123][comment][][name]' type='text' id='post_123_comment__name' value='new comment' />" end assert_dom_equal expected, output_buffer @@ -1179,9 +1593,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[1][title]' size='30' type='text' id='post_1_title' value='Hello World' />" + - "<input name='post[1][comment][1][name]' size='30' type='text' id='post_1_comment_1_name' value='new comment' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[1][title]' type='text' id='post_1_title' value='Hello World' />" + + "<input name='post[1][comment][1][name]' type='text' id='post_1_comment_1_name' value='new comment' />" end assert_dom_equal expected, output_buffer @@ -1194,8 +1608,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[1][comment][title]' size='30' type='text' id='post_1_comment_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[1][comment][title]' type='text' id='post_1_comment_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1208,8 +1622,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[1][comment][5][title]' size='30' type='text' id='post_1_comment_5_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[1][comment][5][title]' type='text' id='post_1_comment_5_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1222,8 +1636,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'put') do - "<input name='post[123][comment][title]' size='30' type='text' id='post_123_comment_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][comment][title]' type='text' id='post_123_comment_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1236,7 +1650,7 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do "<input name='post[comment][5][title]' type='radio' id='post_comment_5_title_hello' value='hello' />" end @@ -1250,8 +1664,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'put') do - "<input name='post[123][comment][123][title]' size='30' type='text' id='post_123_comment_123_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][comment][123][title]' type='text' id='post_123_comment_123_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1270,10 +1684,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'put') do - "<input name='post[123][comment][5][title]' size='30' type='text' id='post_123_comment_5_title' value='Hello World' />" - end + whole_form('/posts/123', 'edit_post', 'edit_post', 'put') do - "<input name='post[1][comment][123][title]' size='30' type='text' id='post_1_comment_123_title' value='Hello World' />" + expected = whole_form('/posts/123', 'edit_post[]', 'edit_post[]', 'patch') do + "<input name='post[123][comment][5][title]' type='text' id='post_123_comment_5_title' value='Hello World' />" + end + whole_form('/posts/123', 'edit_post', 'edit_post', 'patch') do + "<input name='post[1][comment][123][title]' type='text' id='post_1_comment_123_title' value='Hello World' />" end assert_dom_equal expected, output_buffer @@ -1289,9 +1703,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="new author" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="new author" />' end assert_dom_equal expected, output_buffer @@ -1316,9 +1730,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' end @@ -1335,9 +1749,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' end @@ -1354,9 +1768,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' end assert_dom_equal expected, output_buffer @@ -1372,9 +1786,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' end assert_dom_equal expected, output_buffer @@ -1390,9 +1804,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' end @@ -1410,10 +1824,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' end assert_dom_equal expected, output_buffer @@ -1431,11 +1845,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1458,12 +1872,12 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1485,11 +1899,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1511,12 +1925,12 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="author #321" />' + '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1534,11 +1948,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1558,12 +1972,12 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' end assert_dom_equal expected, output_buffer @@ -1581,10 +1995,10 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="new comment" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="new comment" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="new comment" />' end assert_dom_equal expected, output_buffer @@ -1602,11 +2016,11 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #321" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="new comment" />' end assert_dom_equal expected, output_buffer @@ -1620,8 +2034,8 @@ class FormHelperTest < ActionView::TestCase end end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' end assert_dom_equal expected, output_buffer @@ -1637,11 +2051,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1658,11 +2072,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1680,11 +2094,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #1" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' + + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="comment #2" />' + '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' end @@ -1703,11 +2117,11 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' + - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input name="post[title]" type="text" id="post_title" value="Hello World" />' + + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #321" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' + - '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' + '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" type="text" value="new comment" />' end assert_dom_equal expected, output_buffer @@ -1723,14 +2137,64 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" size="30" type="text" value="comment #321" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" type="text" value="comment #321" />' + '<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' end assert_dom_equal expected, output_buffer end + def test_nested_fields_for_index_method_with_existing_records_on_a_nested_attributes_collection_association + @post.comments = Array.new(2) { |id| Comment.new(id + 1) } + + form_for(@post) do |f| + expected = 0 + @post.comments.each do |comment| + f.fields_for(:comments, comment) { |cf| + assert_equal cf.index, expected + expected += 1 + } + end + end + end + + def test_nested_fields_for_index_method_with_existing_and_new_records_on_a_nested_attributes_collection_association + @post.comments = [Comment.new(321), Comment.new] + + form_for(@post) do |f| + expected = 0 + @post.comments.each do |comment| + f.fields_for(:comments, comment) { |cf| + assert_equal cf.index, expected + expected += 1 + } + end + end + end + + def test_nested_fields_for_index_method_with_existing_records_on_a_supplied_nested_attributes_collection + @post.comments = Array.new(2) { |id| Comment.new(id + 1) } + + form_for(@post) do |f| + expected = 0 + f.fields_for(:comments, @post.comments) { |cf| + assert_equal cf.index, expected + expected += 1 + } + end + end + + def test_nested_fields_for_index_method_with_child_index_option_override_on_a_nested_attributes_collection_association + @post.comments = [] + + form_for(@post) do |f| + f.fields_for(:comments, Comment.new(321), :child_index => 'abc') { |cf| + assert_equal cf.index, 'abc' + } + end + end + def test_nested_fields_uses_unique_indices_for_different_collection_associations @post.comments = [Comment.new(321)] @post.tags = [Tag.new(123), Tag.new(456)] @@ -1759,17 +2223,17 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' + - '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" type="text" value="comment #321" />' + + '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" type="text" value="commentrelevance #314" />' + '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' + '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' + - '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' + - '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' + + '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" type="text" value="tag #123" />' + + '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" type="text" value="tagrelevance #3141" />' + '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' + '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' + - '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' + - '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' + + '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" type="text" value="tag #456" />' + + '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" type="text" value="tagrelevance #31415" />' + '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' + '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' end @@ -1786,8 +2250,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="hash backed author" />' + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + '<input id="post_author_attributes_name" name="post[author_attributes][name]" type="text" value="hash backed author" />' end assert_dom_equal expected, output_buffer @@ -1801,8 +2265,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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' />" @@ -1817,8 +2281,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" + - "<textarea name='post[123][body]' id='post_123_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[123][title]' type='text' id='post_123_title' value='Hello World' />" + + "<textarea name='post[123][body]' id='post_123_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[123][secret]' type='hidden' value='0' />" + "<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />" @@ -1833,8 +2297,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[][title]' size='30' type='text' id='post__title' value='Hello World' />" + - "<textarea name='post[][body]' id='post__body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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' />" @@ -1849,8 +2313,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[abc][title]' size='30' type='text' id='post_abc_title' value='Hello World' />" + - "<textarea name='post[abc][body]' id='post_abc_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[abc][title]' type='text' id='post_abc_title' value='Hello World' />" + + "<textarea name='post[abc][body]' id='post_abc_body'>\nBack to the hill and over it again!</textarea>" + "<input name='post[abc][secret]' type='hidden' value='0' />" + "<input name='post[abc][secret]' checked='checked' type='checkbox' id='post_abc_secret' value='1' />" @@ -1865,8 +2329,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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' />" @@ -1881,8 +2345,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<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' />" @@ -1896,7 +2360,7 @@ class FormHelperTest < ActionView::TestCase end assert_dom_equal "<label for=\"author_post_title\">Title</label>" + - "<input name='author[post][title]' size='30' type='text' id='author_post_title' value='Hello World' />", + "<input name='author[post][title]' type='text' id='author_post_title' value='Hello World' />", output_buffer end @@ -1907,12 +2371,12 @@ class FormHelperTest < ActionView::TestCase end assert_dom_equal "<label for=\"author_post_1_title\">Title</label>" + - "<input name='author[post][1][title]' size='30' type='text' id='author_post_1_title' value='Hello World' />", + "<input name='author[post][1][title]' type='text' id='author_post_1_title' value='Hello World' />", output_buffer end def test_form_builder_does_not_have_form_for_method - assert ! ActionView::Helpers::FormBuilder.instance_methods.include?('form_for') + assert !ActionView::Helpers::FormBuilder.instance_methods.include?(:form_for) end def test_form_for_and_fields_for @@ -1925,9 +2389,9 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'create-post', 'edit_post', :method => 'put') do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + expected = whole_form('/posts/123', 'create-post', 'edit_post', :method => 'patch') 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='parent_post[secret]' type='hidden' value='0' />" + "<input name='parent_post[secret]' checked='checked' type='checkbox' id='parent_post_secret' value='1' />" end @@ -1945,10 +2409,10 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'create-post', 'edit_post', :method => 'put') do - "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + - "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + - "<input name='post[comment][name]' type='text' id='post_comment_name' value='new comment' size='30' />" + expected = whole_form('/posts/123', 'create-post', 'edit_post', :method => 'patch') 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[comment][name]' type='text' id='post_comment_name' value='new comment' />" end assert_dom_equal expected, output_buffer @@ -1961,8 +2425,8 @@ class FormHelperTest < ActionView::TestCase } end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'put') do - "<input name='post[category][name]' type='text' size='30' id='post_category_name' />" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', 'patch') do + "<input name='post[category][name]' type='text' id='post_category_name' />" end assert_dom_equal expected, output_buffer @@ -1985,60 +2449,46 @@ class FormHelperTest < ActionView::TestCase concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + - "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea><br/>" + "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" end assert_dom_equal expected, output_buffer end - def hidden_fields(method = nil) - txt = %{<div style="margin:0;padding:0;display:inline">} - txt << %{<input name="utf8" type="hidden" value="✓" />} - if method && !method.to_s.in?(['get', 'post']) - txt << %{<input name="_method" type="hidden" value="#{method}" />} - end - txt << %{</div>} - end - - def form_text(action = "/", id = nil, html_class = nil, remote = nil, multipart = nil, method = nil) - txt = %{<form accept-charset="UTF-8" action="#{action}"} - txt << %{ enctype="multipart/form-data"} if multipart - txt << %{ data-remote="true"} if remote - txt << %{ class="#{html_class}"} if html_class - txt << %{ id="#{id}"} if id - method = method.to_s == "get" ? "get" : "post" - txt << %{ method="#{method}">} - end + def test_default_form_builder + old_default_form_builder, ActionView::Base.default_form_builder = + ActionView::Base.default_form_builder, LabelledFormBuilder - def whole_form(action = "/", id = nil, html_class = nil, options = nil) - contents = block_given? ? yield : "" + form_for(@post) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end - if options.is_a?(Hash) - method, remote, multipart = options.values_at(:method, :remote, :multipart) - else - method = options + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea><br/>" + + "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" end - form_text(action, id, html_class, remote, multipart, method) + hidden_fields(method) + contents + "</form>" + assert_dom_equal expected, output_buffer + ensure + ActionView::Base.default_form_builder = old_default_form_builder end - def test_default_form_builder + def test_lazy_loading_default_form_builder old_default_form_builder, ActionView::Base.default_form_builder = - ActionView::Base.default_form_builder, LabelledFormBuilder + ActionView::Base.default_form_builder, "FormHelperTest::LabelledFormBuilder" form_for(@post) do |f| concat f.text_field(:title) - concat f.text_area(:body) - concat f.check_box(:secret) end - expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'put') do - "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + - "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + - "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" + expected = whole_form('/posts/123', 'edit_post_123', 'edit_post', :method => 'patch') do + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" end assert_dom_equal expected, output_buffer @@ -2054,8 +2504,8 @@ class FormHelperTest < ActionView::TestCase end expected = - "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + - "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + "<label for='title'>Title:</label> <input name='post[title]' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body'>\nBack to the hill and over it again!</textarea><br/>" + "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" assert_dom_equal expected, output_buffer @@ -2115,7 +2565,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_html_options_adds_options_to_form_tag form_for(@post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end - expected = whole_form("/posts/123", "some_form", "some_class", 'put') + expected = whole_form("/posts/123", "some_form", "some_class", 'patch') assert_dom_equal expected, output_buffer end @@ -2123,7 +2573,7 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_string_url_option form_for(@post, :url => 'http://www.otherdomain.com') do |f| end - assert_equal whole_form("http://www.otherdomain.com", 'edit_post_123', 'edit_post', 'put'), output_buffer + assert_equal whole_form("http://www.otherdomain.com", 'edit_post_123', 'edit_post', 'patch'), output_buffer end def test_form_for_with_hash_url_option @@ -2136,14 +2586,14 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_record_url_option form_for(@post, :url => @post) do |f| end - expected = whole_form("/posts/123", 'edit_post_123', 'edit_post', 'put') + expected = whole_form("/posts/123", 'edit_post_123', 'edit_post', 'patch') assert_equal expected, output_buffer end def test_form_for_with_existing_object form_for(@post) do |f| end - expected = whole_form("/posts/123", "edit_post_123", "edit_post", "put") + expected = whole_form("/posts/123", "edit_post_123", "edit_post", 'patch') assert_equal expected, output_buffer end @@ -2162,7 +2612,7 @@ class FormHelperTest < ActionView::TestCase @comment.save form_for([@post, @comment]) {} - expected = whole_form(post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") + expected = whole_form(post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", 'patch') assert_dom_equal expected, output_buffer end @@ -2177,7 +2627,7 @@ class FormHelperTest < ActionView::TestCase @comment.save form_for([:admin, @post, @comment]) {} - expected = whole_form(admin_post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put") + expected = whole_form(admin_post_comment_path(@post, @comment), "edit_comment_1", "edit_comment", 'patch') assert_dom_equal expected, output_buffer end @@ -2191,17 +2641,20 @@ class FormHelperTest < ActionView::TestCase def test_form_for_with_existing_object_and_custom_url form_for(@post, :url => "/super_posts") do |f| end - expected = whole_form("/super_posts", "edit_post_123", "edit_post", "put") + expected = whole_form("/super_posts", "edit_post_123", "edit_post", 'patch') assert_equal expected, output_buffer end def test_form_for_with_default_method_as_patch - ActionView::Base.default_method_for_update = :patch form_for(@post) {} expected = whole_form("/posts/123", "edit_post_123", "edit_post", "patch") assert_dom_equal expected, output_buffer - ensure - ActionView::Base.default_method_for_update = :put + end + + def test_form_for_with_data_attributes + form_for(@post, data: { behavior: "stuff" }, remote: true) {} + assert_match %r|data-behavior="stuff"|, output_buffer + assert_match %r|data-remote="true"|, output_buffer end def test_fields_for_returns_block_result @@ -2209,8 +2662,51 @@ class FormHelperTest < ActionView::TestCase assert_equal "fields", output end + def test_form_builder_block_argument_deprecation + builder_class = Class.new(ActionView::Helpers::FormBuilder) do + def initialize(object_name, object, template, options, block) + super + end + end + + assert_deprecated(/Giving a block to FormBuilder is deprecated and has no effect anymore/) do + builder_class.new(:foo, nil, nil, {}, proc {}) + end + end + protected + def hidden_fields(method = nil) + txt = %{<div style="margin:0;padding:0;display:inline">} + txt << %{<input name="utf8" type="hidden" value="✓" />} + if method && !%w(get post).include?(method.to_s) + txt << %{<input name="_method" type="hidden" value="#{method}" />} + end + txt << %{</div>} + end + + def form_text(action = "/", id = nil, html_class = nil, remote = nil, multipart = nil, method = nil) + txt = %{<form accept-charset="UTF-8" action="#{action}"} + txt << %{ enctype="multipart/form-data"} if multipart + txt << %{ data-remote="true"} if remote + txt << %{ class="#{html_class}"} if html_class + txt << %{ id="#{id}"} if id + method = method.to_s == "get" ? "get" : "post" + txt << %{ method="#{method}">} + end + + def whole_form(action = "/", id = nil, html_class = nil, options = nil) + contents = block_given? ? yield : "" + + if options.is_a?(Hash) + method, remote, multipart = options.values_at(:method, :remote, :multipart) + else + method = options + end + + form_text(action, id, html_class, remote, multipart, method) + hidden_fields(method) + contents + "</form>" + end + def protect_against_forgery? false end diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 6b8d62df62..54ab8b4d3a 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -1,6 +1,5 @@ require 'abstract_unit' require 'tzinfo' -require 'active_support/core_ext/object/inclusion' class Map < Hash def category @@ -83,7 +82,7 @@ class FormOptionsHelperTest < ActionView::TestCase def test_collection_options_with_proc_for_disabled assert_dom_equal( "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\" disabled=\"disabled\">Babe went home</option>\n<option value=\"Cabe\" disabled=\"disabled\">Cabe went home</option>", - options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => lambda{|p| p.author_name.in?(["Babe", "Cabe"]) }) + options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => lambda {|p| %w(Babe Cabe).include?(p.author_name)}) ) end @@ -296,10 +295,34 @@ class FormOptionsHelperTest < ActionView::TestCase ) end - def test_grouped_options_for_select_with_selected_and_prompt + def test_grouped_options_for_select_with_optional_divider assert_dom_equal( + "<optgroup label=\"----------\"><option value=\"US\">US</option>\n<option value=\"Canada\">Canada</option></optgroup><optgroup label=\"----------\"><option value=\"GB\">GB</option>\n<option value=\"Germany\">Germany</option></optgroup>", + + grouped_options_for_select([['US',"Canada"] , ["GB", "Germany"]], nil, divider: "----------") + ) + end + + def test_grouped_options_for_select_with_selected_and_prompt_deprecated + assert_deprecated 'Passing the prompt to grouped_options_for_select as an argument is deprecated. Please use an options hash like `{ prompt: "Choose a product..." }`.' do + assert_dom_equal( "<option value=\"\">Choose a product...</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", "Choose a product...") + ) + end + end + + def test_grouped_options_for_select_with_selected_and_prompt + assert_dom_equal( + "<option value=\"\">Choose a product...</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", prompt: "Choose a product...") + ) + end + + def test_grouped_options_for_select_with_selected_and_prompt_true + assert_dom_equal( + "<option value=\"\">Please select</option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option selected=\"selected\" value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", prompt: true) ) end @@ -307,10 +330,18 @@ class FormOptionsHelperTest < ActionView::TestCase assert grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]]).html_safe? end + def test_grouped_options_for_select_with_prompt_returns_html_escaped_string_deprecated + ActiveSupport::Deprecation.silence do + assert_dom_equal( + "<option value=\"\"><Choose One></option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, '<Choose One>')) + end + end + def test_grouped_options_for_select_with_prompt_returns_html_escaped_string assert_dom_equal( "<option value=\"\"><Choose One></option><optgroup label=\"Hats\"><option value=\"Baseball Cap\">Baseball Cap</option>\n<option value=\"Cowboy Hat\">Cowboy Hat</option></optgroup>", - grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, '<Choose One>')) + grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], nil, prompt: '<Choose One>')) end def test_optgroups_with_with_options_with_hash @@ -509,7 +540,7 @@ class FormOptionsHelperTest < ActionView::TestCase def test_select_under_fields_for_with_string_and_given_prompt @post = Post.new - options = "<option value=\"abe\">abe</option><option value=\"mus\">mus</option><option value=\"hest\">hest</option>" + options = "<option value=\"abe\">abe</option><option value=\"mus\">mus</option><option value=\"hest\">hest</option>".html_safe output_buffer = fields_for :post, @post do |f| concat f.select(:category, options, :prompt => 'The prompt') @@ -529,6 +560,14 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_multiple_and_without_hidden_input + output_buffer = select(:post, :category, "", {:include_hidden => false}, :multiple => true) + assert_dom_equal( + "<select multiple=\"multiple\" id=\"post_category\" name=\"post[category][]\"></select>", + output_buffer + ) + end + def test_select_with_multiple_and_disabled_to_add_disabled_hidden_input output_buffer = select(:post, :category, "", {}, :multiple => true, :disabled => true) assert_dom_equal( @@ -626,6 +665,48 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_required_select + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required"><option value=""></option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true) + ) + end + + def test_required_select_with_include_blank_prompt + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required"><option value="">Select one</option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), { include_blank: "Select one" }, required: true) + ) + end + + def test_required_select_with_prompt + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required"><option value="">Select one</option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), { prompt: "Select one" }, required: true) + ) + end + + def test_required_select_display_size_equals_to_one + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required" size="1"><option value=""></option>\n<option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true, size: 1) + ) + end + + def test_required_select_with_display_size_bigger_than_one + assert_dom_equal( + %(<select id="post_category" name="post[category]" required="required" size="2"><option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true, size: 2) + ) + end + + def test_required_select_with_multiple_option + assert_dom_equal( + %(<input name="post[category][]" type="hidden" value=""/><select id="post_category" multiple="multiple" name="post[category][]" required="required"><option value="abe">abe</option>\n<option value="mus">mus</option>\n<option value="hest">hest</option></select>), + select("post", "category", %w(abe mus hest), {}, required: true, multiple: true) + ) + end + def test_select_with_fixnum @post = Post.new @post.category = "" @@ -665,6 +746,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_escapes_options + assert_dom_equal( + '<select id="post_title" name="post[title]"><script>alert(1)</script></select>', + select('post', 'title', '<script>alert(1)</script>') + ) + end + def test_select_with_selected_nil @post = Post.new @post.category = "<mus>" @@ -1036,11 +1124,25 @@ class FormOptionsHelperTest < ActionView::TestCase def test_options_for_select_with_element_attributes assert_dom_equal( - "<option value=\"<Denmark>\" class=\"bold\"><Denmark></option>\n<option value=\"USA\" onclick=\"alert('Hello World');\">USA</option>\n<option value=\"Sweden\">Sweden</option>\n<option value=\"Germany\">Germany</option>", + "<option value=\"<Denmark>\" class=\"bold\"><Denmark></option>\n<option value=\"USA\" onclick=\"alert('Hello World');\">USA</option>\n<option value=\"Sweden\">Sweden</option>\n<option value=\"Germany\">Germany</option>", options_for_select([ [ "<Denmark>", { :class => 'bold' } ], [ "USA", { :onclick => "alert('Hello World');" } ], [ "Sweden" ], "Germany" ]) ) end + def test_options_for_select_with_data_element + assert_dom_equal( + "<option value=\"<Denmark>\" data-test=\"bold\"><Denmark></option>", + options_for_select([ [ "<Denmark>", { :data => { :test => 'bold' } } ] ]) + ) + end + + def test_options_for_select_with_data_element_with_special_characters + assert_dom_equal( + "<option value=\"<Denmark>\" data-test=\"<bold>\"><Denmark></option>", + options_for_select([ [ "<Denmark>", { :data => { :test => '<bold>' } } ] ]) + ) + end + def test_options_for_select_with_element_attributes_and_selection assert_dom_equal( "<option value=\"<Denmark>\"><Denmark></option>\n<option value=\"USA\" class=\"bold\" selected=\"selected\">USA</option>\n<option value=\"Sweden\">Sweden</option>", @@ -1055,13 +1157,21 @@ class FormOptionsHelperTest < ActionView::TestCase ) end - def test_option_html_attributes_from_without_hash - assert_equal( - {}, - option_html_attributes([ 'foo', 'bar' ]) + def test_options_for_select_with_special_characters + assert_dom_equal( + "<option value=\"<Denmark>\" onclick=\"alert("<code>")\"><Denmark></option>", + options_for_select([ [ "<Denmark>", { :onclick => %(alert("<code>")) } ] ]) ) end + def test_option_html_attributes_with_no_array_element + assert_equal({}, option_html_attributes('foo')) + end + + def test_option_html_attributes_without_hash + assert_equal({}, option_html_attributes([ 'foo', 'bar' ])) + end + def test_option_html_attributes_with_single_element_hash assert_equal( {:class => 'fancy'}, @@ -1083,11 +1193,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end - def test_option_html_attributes_with_special_characters - assert_equal( - {:onclick => "alert("<code>")"}, - option_html_attributes([ 'foo', 'bar', { :onclick => %(alert("<code>")) } ]) - ) + def test_option_html_attributes_with_multiple_hashes_does_not_modify_them + options1 = { class: 'fancy' } + options2 = { onclick: "alert('Hello World');" } + option_html_attributes([ 'foo', 'bar', options1, options2 ]) + + assert_equal({ class: 'fancy' }, options1) + assert_equal({ onclick: "alert('Hello World');" }, options2) end def test_grouped_collection_select diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb index 6ef4cf4dd2..945dff2a29 100644 --- a/actionpack/test/template/form_tag_helper_test.rb +++ b/actionpack/test/template/form_tag_helper_test.rb @@ -1,5 +1,4 @@ require 'abstract_unit' -require 'active_support/core_ext/object/inclusion' class FormTagHelperTest < ActionView::TestCase include RenderERBUtils @@ -16,7 +15,7 @@ class FormTagHelperTest < ActionView::TestCase txt = %{<div style="margin:0;padding:0;display:inline">} txt << %{<input name="utf8" type="hidden" value="✓" />} - if method && !method.to_s.in?(['get','post']) + if method && !%w(get post).include?(method.to_s) txt << %{<input name="_method" type="hidden" value="#{method}" />} end txt << %{</div>} @@ -214,27 +213,45 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal expected, actual end + def test_select_tag_escapes_prompt + actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, :prompt => "<script>alert(1337)</script>" + expected = %(<select id="places" name="places"><option value=""><script>alert(1337)</script></option><option>Home</option><option>Work</option><option>Pub</option></select>) + assert_dom_equal expected, actual + end + def test_select_tag_with_prompt_and_include_blank actual = select_tag "places", "<option>Home</option><option>Work</option><option>Pub</option>".html_safe, :prompt => "string", :include_blank => true expected = %(<select name="places" id="places"><option value="">string</option><option value=""></option><option>Home</option><option>Work</option><option>Pub</option></select>) assert_dom_equal expected, actual end + def test_select_tag_with_nil_option_tags_and_include_blank + actual = select_tag "places", nil, :include_blank => true + expected = %(<select id="places" name="places"><option value=""></option></select>) + assert_dom_equal expected, actual + end + + def test_select_tag_with_nil_option_tags_and_prompt + actual = select_tag "places", nil, :prompt => "string" + expected = %(<select id="places" name="places"><option value="">string</option></select>) + assert_dom_equal expected, actual + end + def test_text_area_tag_size_string actual = text_area_tag "body", "hello world", "size" => "20x40" - expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\nhello world</textarea>) assert_dom_equal expected, actual end def test_text_area_tag_size_symbol actual = text_area_tag "body", "hello world", :size => "20x40" - expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\nhello world</textarea>) assert_dom_equal expected, actual end def test_text_area_tag_should_disregard_size_if_its_given_as_an_integer actual = text_area_tag "body", "hello world", :size => 20 - expected = %(<textarea id="body" name="body">hello world</textarea>) + expected = %(<textarea id="body" name="body">\nhello world</textarea>) assert_dom_equal expected, actual end @@ -245,19 +262,19 @@ class FormTagHelperTest < ActionView::TestCase def test_text_area_tag_escape_content actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40" - expected = %(<textarea cols="20" id="body" name="body" rows="40"><b>hello world</b></textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\n<b>hello world</b></textarea>) assert_dom_equal expected, actual end def test_text_area_tag_unescaped_content actual = text_area_tag "body", "<b>hello world</b>", :size => "20x40", :escape => false - expected = %(<textarea cols="20" id="body" name="body" rows="40"><b>hello world</b></textarea>) + expected = %(<textarea cols="20" id="body" name="body" rows="40">\n<b>hello world</b></textarea>) assert_dom_equal expected, actual end def test_text_area_tag_unescaped_nil_content actual = text_area_tag "body", nil, :escape => false - expected = %(<textarea id="body" name="body"></textarea>) + expected = %(<textarea id="body" name="body">\n</textarea>) assert_dom_equal expected, actual end @@ -374,30 +391,32 @@ class FormTagHelperTest < ActionView::TestCase def test_submit_tag assert_dom_equal( - %(<input name='commit' data-disable-with="Saving..." onclick="alert('hello!')" type="submit" value="Save" />), - submit_tag("Save", :disable_with => "Saving...", :onclick => "alert('hello!')") + %(<input name='commit' data-disable-with="Saving..." onclick="alert('hello!')" type="submit" value="Save" />), + submit_tag("Save", :onclick => "alert('hello!')", :data => { :disable_with => "Saving..." }) ) end def test_submit_tag_with_no_onclick_options assert_dom_equal( %(<input name='commit' data-disable-with="Saving..." type="submit" value="Save" />), - submit_tag("Save", :disable_with => "Saving...") + submit_tag("Save", :data => { :disable_with => "Saving..." }) ) end def test_submit_tag_with_confirmation assert_dom_equal( %(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />), - submit_tag("Save", :confirm => "Are you sure?") + submit_tag("Save", :data => { :confirm => "Are you sure?" }) ) end - def test_submit_tag_with_confirmation_and_with_disable_with - assert_dom_equal( - %(<input name="commit" data-disable-with="Saving..." data-confirm="Are you sure?" type="submit" value="Save" />), - submit_tag("Save", :disable_with => "Saving...", :confirm => "Are you sure?") - ) + def test_submit_tag_with_deprecated_confirmation + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + %(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />), + submit_tag("Save", :confirm => "Are you sure?") + ) + end end def test_button_tag @@ -451,13 +470,44 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal('<button name="temptation" type="button"><strong>Do not press me</strong></button>', output) end + def test_button_tag_with_confirmation + assert_dom_equal( + %(<button name="button" type="submit" data-confirm="Are you sure?">Save</button>), + button_tag("Save", :type => "submit", :data => { :confirm => "Are you sure?" }) + ) + end + + def test_button_tag_with_deprecated_confirmation + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + %(<button name="button" type="submit" data-confirm="Are you sure?">Save</button>), + button_tag("Save", :type => "submit", :confirm => "Are you sure?") + ) + end + end + def test_image_submit_tag_with_confirmation assert_dom_equal( %(<input type="image" src="/images/save.gif" data-confirm="Are you sure?" />), - image_submit_tag("save.gif", :confirm => "Are you sure?") + image_submit_tag("save.gif", :data => { :confirm => "Are you sure?" }) ) end + def test_image_submit_tag_with_deprecated_confirmation + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + %(<input type="image" src="/images/save.gif" data-confirm="Are you sure?" />), + image_submit_tag("save.gif", :confirm => "Are you sure?") + ) + end + end + + + def test_color_field_tag + expected = %{<input id="car" name="car" type="color" />} + assert_dom_equal(expected, color_field_tag("car")) + end + def test_search_field_tag expected = %{<input id="query" name="query" type="search" />} assert_dom_equal(expected, search_field_tag("query")) @@ -473,6 +523,31 @@ class FormTagHelperTest < ActionView::TestCase assert_dom_equal(expected, date_field_tag("cell")) end + def test_time_field_tag + expected = %{<input id="cell" name="cell" type="time" />} + assert_dom_equal(expected, time_field_tag("cell")) + end + + def test_datetime_field_tag + expected = %{<input id="appointment" name="appointment" type="datetime" />} + assert_dom_equal(expected, datetime_field_tag("appointment")) + end + + def test_datetime_local_field_tag + expected = %{<input id="appointment" name="appointment" type="datetime-local" />} + assert_dom_equal(expected, datetime_local_field_tag("appointment")) + end + + def test_month_field_tag + expected = %{<input id="birthday" name="birthday" type="month" />} + assert_dom_equal(expected, month_field_tag("birthday")) + end + + def test_week_field_tag + expected = %{<input id="birthday" name="birthday" type="week" />} + assert_dom_equal(expected, week_field_tag("birthday")) + end + def test_url_field_tag expected = %{<input id="homepage" name="homepage" type="url" />} assert_dom_equal(expected, url_field_tag("homepage")) @@ -513,6 +588,16 @@ class FormTagHelperTest < ActionView::TestCase expected = %(<fieldset class="format">Hello world!</fieldset>) assert_dom_equal expected, output_buffer + + output_buffer = render_erb("<%= field_set_tag %>") + + expected = %(<fieldset></fieldset>) + assert_dom_equal expected, output_buffer + + output_buffer = render_erb("<%= field_set_tag('You legend!') %>") + + expected = %(<fieldset><legend>You legend!</legend></fieldset>) + assert_dom_equal expected, output_buffer end def test_text_area_tag_options_symbolize_keys_side_effects diff --git a/actionpack/test/template/html-scanner/sanitizer_test.rb b/actionpack/test/template/html-scanner/sanitizer_test.rb index 32c655c5fd..324caef224 100644 --- a/actionpack/test/template/html-scanner/sanitizer_test.rb +++ b/actionpack/test/template/html-scanner/sanitizer_test.rb @@ -125,6 +125,24 @@ class SanitizerTest < ActionController::TestCase assert_equal(text, sanitizer.sanitize(text, :attributes => ['foo'])) end + def test_should_raise_argument_error_if_tags_is_not_enumerable + sanitizer = HTML::WhiteListSanitizer.new + e = assert_raise(ArgumentError) do + sanitizer.sanitize('', :tags => 'foo') + end + + assert_equal "You should pass :tags as an Enumerable", e.message + end + + def test_should_raise_argument_error_if_attributes_is_not_enumerable + sanitizer = HTML::WhiteListSanitizer.new + e = assert_raise(ArgumentError) do + sanitizer.sanitize('', :attributes => 'foo') + end + + assert_equal "You should pass :attributes as an Enumerable", e.message + end + [%w(img src), %w(a href)].each do |(tag, attr)| define_method "test_should_strip_#{attr}_attribute_in_#{tag}_with_bad_protocols" do assert_sanitized %(<#{tag} #{attr}="javascript:bang" title="1">boo</#{tag}>), %(<#{tag} title="1">boo</#{tag}>) diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 9441bd6b38..58784c26fa 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -28,6 +28,8 @@ class JavaScriptHelperTest < ActionView::TestCase assert_equal %(backslash\\\\test), escape_javascript( %(backslash\\test) ) assert_equal %(dont <\\/close> tags), escape_javascript(%(dont </close> tags)) assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\250 newline).force_encoding('UTF-8').encode!) + assert_equal %(unicode 
 newline), escape_javascript(%(unicode \342\200\251 newline).force_encoding('UTF-8').encode!) + assert_equal %(dont <\\/close> tags), j(%(dont </close> tags)) end @@ -41,46 +43,58 @@ class JavaScriptHelperTest < ActionView::TestCase end def test_button_to_function - assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />), - button_to_function("Greeting", "alert('Hello world!')") + assert_deprecated "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do + assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />), + button_to_function("Greeting", "alert('Hello world!')") + end end def test_button_to_function_with_onclick - assert_dom_equal "<input onclick=\"alert('Goodbye World :('); alert('Hello world!');\" type=\"button\" value=\"Greeting\" />", - button_to_function("Greeting", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')") + assert_deprecated "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do + assert_dom_equal "<input onclick=\"alert('Goodbye World :('); alert('Hello world!');\" type=\"button\" value=\"Greeting\" />", + button_to_function("Greeting", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')") + end end def test_button_to_function_without_function - assert_dom_equal "<input onclick=\";\" type=\"button\" value=\"Greeting\" />", - button_to_function("Greeting") + assert_deprecated "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do + assert_dom_equal "<input onclick=\";\" type=\"button\" value=\"Greeting\" />", + button_to_function("Greeting") + end end def test_link_to_function - assert_dom_equal %(<a href="#" onclick="alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')") + assert_deprecated "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do + assert_dom_equal %(<a href="#" onclick="alert('Hello world!'); return false;">Greeting</a>), + link_to_function("Greeting", "alert('Hello world!')") + end end def test_link_to_function_with_existing_onclick - assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')") + assert_deprecated "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do + assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>), + link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')") + end end def test_function_with_href - assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>), - link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') + assert_deprecated "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do + assert_dom_equal %(<a href="http://example.com/" onclick="alert('Hello world!'); return false;">Greeting</a>), + link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/') + end end def test_javascript_tag self.output_buffer = 'foo' - assert_dom_equal "<script type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", + assert_dom_equal "<script>\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", javascript_tag("alert('hello')") assert_equal 'foo', output_buffer, 'javascript_tag without a block should not concat to output_buffer' end def test_javascript_tag_with_options - assert_dom_equal "<script id=\"the_js_tag\" type=\"text/javascript\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", + assert_dom_equal "<script id=\"the_js_tag\">\n//<![CDATA[\nalert('hello')\n//]]>\n</script>", javascript_tag("alert('hello')", :id => "the_js_tag") end diff --git a/actionpack/test/template/log_subscriber_test.rb b/actionpack/test/template/log_subscriber_test.rb index 1713ce935c..7f4c84929f 100644 --- a/actionpack/test/template/log_subscriber_test.rb +++ b/actionpack/test/template/log_subscriber_test.rb @@ -8,9 +8,10 @@ class AVLogSubscriberTest < ActiveSupport::TestCase def setup super - @controller = Object.new - @controller.stubs(:_prefixes).returns(%w(test)) - @view = ActionView::Base.new(ActionController::Base.view_paths, {}, @controller) + view_paths = ActionController::Base.view_paths + 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 end diff --git a/actionpack/test/template/lookup_context_test.rb b/actionpack/test/template/lookup_context_test.rb index 96b14a0acd..073bd14783 100644 --- a/actionpack/test/template/lookup_context_test.rb +++ b/actionpack/test/template/lookup_context_test.rb @@ -11,6 +11,17 @@ class LookupContextTest < ActiveSupport::TestCase I18n.locale = :en end + test "allows to override default_formats with ActionView::Base.default_formats" do + begin + formats = ActionView::Base.default_formats + ActionView::Base.default_formats = [:foo, :bar] + + assert_equal [:foo, :bar], ActionView::LookupContext.new([]).default_formats + ensure + ActionView::Base.default_formats = formats + end + end + test "process view paths on initialization" do assert_kind_of ActionView::PathSet, @lookup_context.view_paths end @@ -169,7 +180,7 @@ class LookupContextTest < ActiveSupport::TestCase assert_not_equal template, old_template end - + test "responds to #prefixes" do assert_equal [], @lookup_context.prefixes @lookup_context.prefixes = ["foo"] @@ -180,7 +191,7 @@ end class LookupContextWithFalseCaching < ActiveSupport::TestCase def setup @resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)]) - @resolver.stubs(:caching?).returns(false) + ActionView::Resolver.stubs(:caching?).returns(false) @lookup_context = ActionView::LookupContext.new(@resolver, {}) end @@ -247,6 +258,6 @@ class TestMissingTemplate < ActiveSupport::TestCase @lookup_context.view_paths.find("foo", "parent", true, details) end assert_match %r{Missing partial parent/foo with .* Searched in:\n \* "/Path/to/views"\n}, e.message - end - + end + end diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb deleted file mode 100644 index d6e9de9555..0000000000 --- a/actionpack/test/template/number_helper_i18n_test.rb +++ /dev/null @@ -1,122 +0,0 @@ -require 'abstract_unit' - -class NumberHelperTest < ActionView::TestCase - tests ActionView::Helpers::NumberHelper - - def setup - I18n.backend.store_translations 'ts', - :number => { - :format => { :precision => 3, :delimiter => ',', :separator => '.', :significant => false, :strip_insignificant_zeros => false }, - :currency => { :format => { :unit => '&$', :format => '%u - %n', :negative_format => '(%u - %n)', :precision => 2 } }, - :human => { - :format => { - :precision => 2, - :significant => true, - :strip_insignificant_zeros => true - }, - :storage_units => { - :format => "%n %u", - :units => { - :byte => "b", - :kb => "k" - } - }, - :decimal_units => { - :format => "%n %u", - :units => { - :deci => {:one => "Tenth", :other => "Tenths"}, - :unit => "u", - :ten => {:one => "Ten", :other => "Tens"}, - :thousand => "t", - :million => "m" , - :billion =>"b" , - :trillion =>"t" , - :quadrillion =>"q" - } - } - }, - :percentage => { :format => {:delimiter => '', :precision => 2, :strip_insignificant_zeros => true} }, - :precision => { :format => {:delimiter => '', :significant => true} } - }, - :custom_units_for_number_to_human => {:mili => "mm", :centi => "cm", :deci => "dm", :unit => "m", :ten => "dam", :hundred => "hm", :thousand => "km"} - end - - def test_number_to_i18n_currency - assert_equal("&$ - 10.00", number_to_currency(10, :locale => 'ts')) - assert_equal("(&$ - 10.00)", number_to_currency(-10, :locale => 'ts')) - assert_equal("-10.00 - &$", number_to_currency(-10, :locale => 'ts', :format => "%n - %u")) - end - - def test_number_to_currency_with_clean_i18n_settings - clean_i18n do - assert_equal("$10.00", number_to_currency(10)) - assert_equal("-$10.00", number_to_currency(-10)) - end - end - - def test_number_to_currency_without_currency_negative_format - clean_i18n do - I18n.backend.store_translations 'ts', :number => { :currency => { :format => { :unit => '@', :format => '%n %u' } } } - assert_equal("-10.00 @", number_to_currency(-10, :locale => 'ts')) - end - end - - def test_number_with_i18n_precision - #Delimiter was set to "" - assert_equal("10000", number_with_precision(10000, :locale => 'ts')) - - #Precision inherited and significant was set - assert_equal("1.00", number_with_precision(1.0, :locale => 'ts')) - - end - - def test_number_with_i18n_delimiter - #Delimiter "," and separator "." - assert_equal("1,000,000.234", number_with_delimiter(1000000.234, :locale => 'ts')) - end - - def test_number_to_i18n_percentage - # to see if strip_insignificant_zeros is true - assert_equal("1%", number_to_percentage(1, :locale => 'ts')) - # precision is 2, significant should be inherited - assert_equal("1.24%", number_to_percentage(1.2434, :locale => 'ts')) - # no delimiter - assert_equal("12434%", number_to_percentage(12434, :locale => 'ts')) - end - - def test_number_to_i18n_human_size - #b for bytes and k for kbytes - assert_equal("2 k", number_to_human_size(2048, :locale => 'ts')) - assert_equal("42 b", number_to_human_size(42, :locale => 'ts')) - end - - def test_number_to_human_with_default_translation_scope - #Using t for thousand - assert_equal "2 t", number_to_human(2000, :locale => 'ts') - #Significant was set to true with precision 2, using b for billion - assert_equal "1.2 b", number_to_human(1234567890, :locale => 'ts') - #Using pluralization (Ten/Tens and Tenth/Tenths) - assert_equal "1 Tenth", number_to_human(0.1, :locale => 'ts') - assert_equal "1.3 Tenth", number_to_human(0.134, :locale => 'ts') - assert_equal "2 Tenths", number_to_human(0.2, :locale => 'ts') - assert_equal "1 Ten", number_to_human(10, :locale => 'ts') - assert_equal "1.2 Ten", number_to_human(12, :locale => 'ts') - assert_equal "2 Tens", number_to_human(20, :locale => 'ts') - end - - def test_number_to_human_with_custom_translation_scope - #Significant was set to true with precision 2, with custom translated units - assert_equal "4.3 cm", number_to_human(0.0432, :locale => 'ts', :units => :custom_units_for_number_to_human) - end - - private - def clean_i18n - load_path = I18n.load_path.dup - I18n.load_path.clear - I18n.reload! - yield - ensure - I18n.load_path = load_path - I18n.reload! - end -end diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb index 482d953907..d8fffe75ed 100644 --- a/actionpack/test/template/number_helper_test.rb +++ b/actionpack/test/template/number_helper_test.rb @@ -33,6 +33,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal("+18005551212", number_to_phone(8005551212, :country_code => 1, :delimiter => '')) assert_equal("22-555-1212", number_to_phone(225551212)) assert_equal("+45-22-555-1212", number_to_phone(225551212, :country_code => 45)) + assert_equal '111<script></script>111<script></script>1111', number_to_phone(1111111111, :delimiter => "<script></script>") end def test_number_to_currency @@ -47,6 +48,8 @@ class NumberHelperTest < ActionView::TestCase assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50")) assert_equal("1,234,567,890.50 Kč", number_to_currency("1234567890.50", {:unit => "Kč", :format => "%n %u"})) assert_equal("1,234,567,890.50 - Kč", number_to_currency("-1234567890.50", {:unit => "Kč", :format => "%n %u", :negative_format => "%n - %u"})) + assert_equal '$1<script></script>01', number_to_currency(1.01, :separator => "<script></script>") + assert_equal '$1<script></script>000.00', number_to_currency(1000, :delimiter => "<script></script>") end def test_number_to_percentage @@ -58,6 +61,8 @@ class NumberHelperTest < ActionView::TestCase assert_equal("123.4%", number_to_percentage(123.400, :precision => 3, :strip_insignificant_zeros => true)) assert_equal("1.000,000%", number_to_percentage(1000, :delimiter => '.', :separator => ',')) assert_equal("1000.000 %", number_to_percentage(1000, :format => "%n %")) + assert_equal '1<script></script>010%', number_to_percentage(1.01, :separator => "<script></script>") + assert_equal '1<script></script>000.000%', number_to_percentage(1000, :delimiter => "<script></script>") end def test_number_with_delimiter @@ -78,6 +83,8 @@ class NumberHelperTest < ActionView::TestCase assert_equal '12,345,678-05', number_with_delimiter(12345678.05, :separator => '-') assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :separator => ',', :delimiter => '.') assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :delimiter => '.', :separator => ',') + assert_equal '1<script></script>01', number_with_delimiter(1.01, :separator => "<script></script>") + assert_equal '1<script></script>000', number_with_delimiter(1000, :delimiter => "<script></script>") end def test_number_with_precision @@ -96,11 +103,14 @@ class NumberHelperTest < ActionView::TestCase assert_equal("0.001", number_with_precision(0.00111, :precision => 3)) assert_equal("10.00", number_with_precision(9.995, :precision => 2)) assert_equal("11.00", number_with_precision(10.995, :precision => 2)) + assert_equal("0.00", number_with_precision(-0.001, :precision => 2)) end def test_number_with_precision_with_custom_delimiter_and_separator assert_equal '31,83', number_with_precision(31.825, :precision => 2, :separator => ',') assert_equal '1.231,83', number_with_precision(1231.825, :precision => 2, :separator => ',', :delimiter => '.') + assert_equal '1<script></script>010', number_with_precision(1.01, :separator => "<script></script>") + assert_equal '1<script></script>000.000', number_with_precision(1000, :delimiter => "<script></script>") end def test_number_with_precision_with_significant_digits @@ -190,6 +200,7 @@ class NumberHelperTest < ActionView::TestCase assert_equal '1.0 KB', number_to_human_size(kilobytes(1.0123), :precision => 2, :strip_insignificant_zeros => false) assert_equal '1.012 KB', number_to_human_size(kilobytes(1.0123), :precision => 3, :significant => false) assert_equal '1 KB', number_to_human_size(kilobytes(1.0123), :precision => 0, :significant => true) #ignores significant it precision is 0 + assert_equal '9<script></script>86 KB', number_to_human_size(10100, :separator => "<script></script>") end def test_number_to_human_size_with_custom_delimiter_and_separator @@ -250,6 +261,9 @@ class NumberHelperTest < ActionView::TestCase #Spaces are stripped from the resulting string assert_equal '4', number_to_human(4, :units => {:unit => "", :ten => 'tens '}) assert_equal '4.5 tens', number_to_human(45, :units => {:unit => "", :ten => ' tens '}) + + assert_equal '1<script></script>01', number_to_human(1.01, :separator => "<script></script>") + assert_equal '100<script></script>000 Quadrillion', number_to_human(10**20, :delimiter => "<script></script>") end def test_number_to_human_with_custom_format @@ -347,69 +361,39 @@ class NumberHelperTest < ActionView::TestCase end def test_number_helpers_should_raise_error_if_invalid_when_specified - assert_raise InvalidNumberError do - number_to_human("x", :raise => true) - end - begin + exception = assert_raise InvalidNumberError do number_to_human("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number end + assert_equal "x", exception.number - assert_raise InvalidNumberError do - number_to_human_size("x", :raise => true) - end - begin + exception = assert_raise InvalidNumberError do number_to_human_size("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number end + assert_equal "x", exception.number - assert_raise InvalidNumberError do + exception = assert_raise InvalidNumberError do number_with_precision("x", :raise => true) end - begin - number_with_precision("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number - end + assert_equal "x", exception.number - assert_raise InvalidNumberError do + exception = assert_raise InvalidNumberError do number_to_currency("x", :raise => true) end - begin - number_with_precision("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number - end + assert_equal "x", exception.number - assert_raise InvalidNumberError do + exception = assert_raise InvalidNumberError do number_to_percentage("x", :raise => true) end - begin - number_to_percentage("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number - end + assert_equal "x", exception.number - assert_raise InvalidNumberError do - number_with_delimiter("x", :raise => true) - end - begin + exception = assert_raise InvalidNumberError do number_with_delimiter("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number end + assert_equal "x", exception.number - assert_raise InvalidNumberError do + exception = assert_raise InvalidNumberError do number_to_phone("x", :raise => true) end - begin - number_to_phone("x", :raise => true) - rescue InvalidNumberError => e - assert_equal "x", e.number - end - + assert_equal "x", exception.number end - end diff --git a/actionpack/test/controller/record_identifier_test.rb b/actionpack/test/template/record_identifier_test.rb index eb38b81e85..22038110a5 100644 --- a/actionpack/test/controller/record_identifier_test.rb +++ b/actionpack/test/template/record_identifier_test.rb @@ -2,7 +2,7 @@ require 'abstract_unit' require 'controller/fake_models' class RecordIdentifierTest < ActiveSupport::TestCase - include ActionController::RecordIdentifier + include ActionView::RecordIdentifier def setup @klass = Comment @@ -37,4 +37,13 @@ class RecordIdentifierTest < ActiveSupport::TestCase def test_dom_class_with_prefix assert_equal "custom_prefix_#{@singular}", dom_class(@record, :custom_prefix) end + + def test_dom_id_as_singleton_method + @record.save + assert_equal "#{@singular}_1", ActionView::RecordIdentifier.dom_id(@record) + end + + def test_dom_class_as_singleton_method + assert_equal @singular, ActionView::RecordIdentifier.dom_class(@record) + end end diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb index 7347e15373..ddf5c6a1b3 100644 --- a/actionpack/test/template/render_test.rb +++ b/actionpack/test/template/render_test.rb @@ -21,9 +21,7 @@ module RenderTestCases end def test_render_without_options - @view.render() - flunk "Render did not raise ArgumentError" - rescue ArgumentError => e + e = assert_raises(ArgumentError) { @view.render() } assert_match "You invoked render but did not give any of :partial, :template, :inline, :file or :text option.", e.message end @@ -56,6 +54,16 @@ module RenderTestCases assert_equal "Hello world", @view.render(:template => "test/one", :formats => [:html]) end + def test_render_partial_implicitly_use_format_of_the_rendered_partial + @view.lookup_context.formats = [:html] + assert_equal "Third level", @view.render(:template => "test/html_template") + end + + def test_render_partial_use_last_prepended_format_for_partials_with_the_same_names + @view.lookup_context.formats = [:html] + assert_equal "\nHTML Template, but JSON partial", @view.render(:template => "test/change_priorty") + end + def test_render_template_with_a_missing_partial_of_another_format @view.lookup_context.formats = [:html] assert_raise ActionView::Template::Error, "Missing partial /missing with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder]}" do @@ -81,6 +89,22 @@ module RenderTestCases assert_equal "<h1>No Comment</h1>\n", @view.render(:template => "comments/empty", :handlers => [:builder]) end + def test_render_raw_template_with_handlers + assert_equal "<%= hello_world %>\n", @view.render(:template => "plain_text") + end + + def test_render_raw_template_with_quotes + assert_equal %q;Here are some characters: !@#$%^&*()-="'}{`; + "\n", @view.render(:template => "plain_text_with_characters") + end + + def test_render_ruby_template_with_handlers + assert_equal "Hello from Ruby code", @view.render(:template => "ruby_template") + end + + def test_render_ruby_template_inline + assert_equal '4', @view.render(:inline => "(2**2).to_s", :type => :ruby) + end + def test_render_file_with_localization_on_context_level old_locale, @view.locale = @view.locale, :da assert_equal "Hey verden", @view.render(:file => "test/hello_world") @@ -153,25 +177,33 @@ module RenderTestCases end def test_render_partial_with_invalid_name - @view.render(:partial => "test/200") - flunk "Render did not raise ArgumentError" - rescue ArgumentError => e + e = assert_raises(ArgumentError) { @view.render(:partial => "test/200") } 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 + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores.", e.message + end + + def test_render_partial_with_missing_filename + e = assert_raises(ArgumentError) { @view.render(:partial => "test/") } + assert_equal "The partial name (test/) is not a valid Ruby identifier; " + + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores.", e.message end def test_render_partial_with_incompatible_object - @view.render(:partial => nil) - flunk "Render did not raise ArgumentError" - rescue ArgumentError => e + e = assert_raises(ArgumentError) { @view.render(:partial => nil) } assert_equal "'#{nil.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.", e.message end + def test_render_partial_with_hyphen + e = assert_raises(ArgumentError) { @view.render(:partial => "test/a-in") } + assert_equal "The partial name (test/a-in) is not a valid Ruby identifier; " + + "make sure your partial name starts with a lowercase letter or underscore, " + + "and is followed by any combination of letters, numbers and underscores.", e.message + end + def test_render_partial_with_errors - @view.render(:partial => "test/raise") - flunk "Render did not raise Template::Error" - rescue ActionView::Template::Error => e + e = assert_raises(ActionView::Template::Error) { @view.render(:partial => "test/raise") } assert_match %r!method.*doesnt_exist!, e.message assert_equal "", e.sub_template_message assert_equal "1", e.line_number @@ -179,10 +211,17 @@ module RenderTestCases assert_equal File.expand_path("#{FIXTURE_LOAD_PATH}/test/_raise.html.erb"), e.file_name end + def test_render_error_indentation + e = assert_raises(ActionView::Template::Error) { @view.render(:partial => "test/raise_indentation") } + error_lines = e.annoted_source_code.split("\n") + assert_match %r!error\shere!, e.message + assert_equal "11", e.line_number + assert_equal " 9: <p>Ninth paragraph</p>", error_lines.second + assert_equal " 10: <p>Tenth paragraph</p>", error_lines.third + end + def test_render_sub_template_with_errors - @view.render(:template => "test/sub_template_raise") - flunk "Render did not raise Template::Error" - rescue ActionView::Template::Error => e + e = assert_raises(ActionView::Template::Error) { @view.render(:template => "test/sub_template_raise") } assert_match %r!method.*doesnt_exist!, e.message 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 @@ -190,9 +229,7 @@ module RenderTestCases end 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 + e = assert_raises(ActionView::Template::Error) { @view.render(:file => File.expand_path("test/_raise", FIXTURE_LOAD_PATH)) } assert_match %r!method.*doesnt_exist!, e.message assert_equal "", e.sub_template_message assert_equal "1", e.line_number @@ -239,6 +276,25 @@ module RenderTestCases assert_equal "Hello: davidHello: Anonymous", @view.render(:partial => "test/customer", :collection => [ Customer.new("david"), nil ]) end + def test_render_partial_with_layout_using_collection_and_template + assert_equal "<b>Hello: Amazon</b><b>Hello: Yahoo</b>", @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ]) + end + + def test_render_partial_with_layout_using_collection_and_template_makes_current_item_available_in_layout + assert_equal '<b class="amazon">Hello: Amazon</b><b class="yahoo">Hello: Yahoo</b>', + @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ]) + end + + def test_render_partial_with_layout_using_collection_and_template_makes_current_item_counter_available_in_layout + assert_equal '<b data-counter="0">Hello: Amazon</b><b data-counter="1">Hello: Yahoo</b>', + @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object_counter', :collection => [ Customer.new("Amazon"), Customer.new("Yahoo") ]) + end + + def test_render_partial_with_layout_using_object_and_template_makes_object_available_in_layout + assert_equal '<b class="amazon">Hello: Amazon</b>', + @view.render(:partial => "test/customer", :layout => 'test/b_layout_for_partial_with_object', :object => Customer.new("Amazon")) + end + def test_render_partial_with_empty_array_should_return_nil assert_nil @view.render(:partial => []) end @@ -270,7 +326,7 @@ module RenderTestCases # TODO: The reason for this test is unclear, improve documentation def test_render_missing_xml_partial_and_raise_missing_template @view.formats = [:xml] - assert_raise(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") } + assert_raises(ActionView::MissingTemplate) { @view.render(:partial => "test/layout_for_partial") } ensure @view.formats = nil end @@ -311,7 +367,7 @@ module RenderTestCases ActionView::Template.register_template_handler :foo, CustomHandler assert_equal 'source: "Hello, <%= name %>!"', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo) end - + def test_render_knows_about_types_registered_when_extensions_are_checked_earlier_in_initialization ActionView::Template::Handlers.extensions ActionView::Template.register_template_handler :foo, CustomHandler @@ -321,7 +377,7 @@ module RenderTestCases def test_render_ignores_templates_with_malformed_template_handlers ActiveSupport::Deprecation.silence do %w(malformed malformed.erb malformed.html.erb malformed.en.html.erb).each do |name| - assert_raise(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") } + assert_raises(ActionView::MissingTemplate) { @view.render(:file => "test/malformed/#{name}") } end end end @@ -395,6 +451,15 @@ module RenderTestCases assert_equal %(<title>David</title>), @view.render(:file => "test/layout_render_object") end + + def test_render_with_passing_couple_extensions_to_one_register_template_handler_function_call + ActionView::Template.register_template_handler :foo1, :foo2, CustomHandler + assert_equal @view.render(:inline => "Hello, World!", :type => :foo1), @view.render(:inline => "Hello, World!", :type => :foo2) + end + + def test_render_throws_exception_when_no_extensions_passed_to_register_template_handler_function_call + assert_raises(ArgumentError) { ActionView::Template.register_template_handler CustomHandler } + end end class CachedViewRenderTest < ActiveSupport::TestCase @@ -446,23 +511,15 @@ class LazyViewRenderTest < ActiveSupport::TestCase def test_render_utf8_template_with_incompatible_external_encoding with_external_encoding Encoding::SHIFT_JIS do - begin - @view.render(:file => "test/utf8", :formats => [:html], :layouts => "layouts/yield") - flunk 'Should have raised incompatible encoding error' - rescue ActionView::Template::Error => error - assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message - end + 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 end end def test_render_utf8_template_with_partial_with_incompatible_encoding with_external_encoding Encoding::SHIFT_JIS do - begin - @view.render(:file => "test/utf8_magic_with_bare_partial", :formats => [:html], :layouts => "layouts/yield") - flunk 'Should have raised incompatible encoding error' - rescue ActionView::Template::Error => error - assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message - end + 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 end end diff --git a/actionpack/test/template/sanitize_helper_test.rb b/actionpack/test/template/sanitize_helper_test.rb index 4182af590e..7626cdf386 100644 --- a/actionpack/test/template/sanitize_helper_test.rb +++ b/actionpack/test/template/sanitize_helper_test.rb @@ -40,9 +40,9 @@ class SanitizeHelperTest < ActionView::TestCase [nil, '', ' '].each do |blank| stripped = strip_tags(blank) assert_equal blank, stripped - assert stripped.html_safe? unless blank.nil? end - assert strip_tags("<script>").html_safe? + assert_equal "", strip_tags("<script>") + assert_equal "something <img onerror=alert(1337)", ERB::Util.html_escape(strip_tags("something <img onerror=alert(1337)")) end def test_sanitize_is_marked_safe diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb deleted file mode 100644 index 1c591bdcc2..0000000000 --- a/actionpack/test/template/sprockets_helper_test.rb +++ /dev/null @@ -1,348 +0,0 @@ -require 'abstract_unit' -require 'sprockets' -require 'sprockets/helpers/rails_helper' -require 'mocha' - -class SprocketsHelperTest < ActionView::TestCase - include Sprockets::Helpers::RailsHelper - - attr_accessor :assets - - class MockRequest - def protocol() 'http://' end - def ssl?() false end - def host_with_port() 'localhost' end - end - - def setup - super - - @controller = BasicController.new - @controller.request = MockRequest.new - - @assets = Sprockets::Environment.new - @assets.append_path(FIXTURES.join("sprockets/app/javascripts")) - @assets.append_path(FIXTURES.join("sprockets/app/stylesheets")) - @assets.append_path(FIXTURES.join("sprockets/app/images")) - @assets.append_path(FIXTURES.join("sprockets/app/fonts")) - - application = Struct.new(:config, :assets).new(config, @assets) - Rails.stubs(:application).returns(application) - @config = config - @config.perform_caching = true - @config.assets.digest = true - @config.assets.compile = true - end - - def url_for(*args) - "http://www.example.com" - end - - def config - @controller ? @controller.config : @config - end - - def compute_host(source, request, options = {}) - raise "Should never get here" - end - - test "asset_path" do - assert_match %r{/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - assert_match %r{/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png", :digest => true) - assert_match %r{/assets/logo.png}, - asset_path("logo.png", :digest => false) - end - - test "custom_asset_path" do - @config.assets.prefix = '/s' - assert_match %r{/s/logo-[0-9a-f]+.png}, - asset_path("logo.png") - assert_match %r{/s/logo-[0-9a-f]+.png}, - asset_path("logo.png", :digest => true) - assert_match %r{/s/logo.png}, - asset_path("logo.png", :digest => false) - end - - test "asset_path with root relative assets" do - assert_equal "/images/logo", - asset_path("/images/logo") - assert_equal "/images/logo.gif", - asset_path("/images/logo.gif") - - assert_equal "/dir/audio", - asset_path("/dir/audio") - end - - test "asset_path with absolute urls" do - assert_equal "http://www.example.com/video/play", - asset_path("http://www.example.com/video/play") - assert_equal "http://www.example.com/video/play.mp4", - asset_path("http://www.example.com/video/play.mp4") - end - - test "with a simple asset host the url should default to protocol relative" do - @controller.config.default_asset_host_protocol = :relative - @controller.config.asset_host = "assets-%d.example.com" - assert_match %r{^//assets-\d.example.com/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - end - - test "with a simple asset host the url can be changed to use the request protocol" do - @controller.config.asset_host = "assets-%d.example.com" - @controller.config.default_asset_host_protocol = :request - assert_match %r{http://assets-\d.example.com/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - end - - test "With a proc asset host that returns no protocol the url should be protocol relative" do - @controller.config.default_asset_host_protocol = :relative - @controller.config.asset_host = Proc.new do |asset| - "assets-999.example.com" - end - assert_match %r{^//assets-999.example.com/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - end - - test "with a proc asset host that returns a protocol the url use it" do - @controller.config.asset_host = Proc.new do |asset| - "http://assets-999.example.com" - end - assert_match %r{http://assets-999.example.com/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - end - - test "stylesheets served with a controller in scope can access the request" do - config.asset_host = Proc.new do |asset, request| - assert_not_nil request - "http://assets-666.example.com" - end - assert_match %r{http://assets-666.example.com/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - end - - test "stylesheets served without a controller in scope cannot access the request" do - @controller = nil - @config.asset_host = Proc.new do |asset, request| - fail "This should not have been called." - end - assert_raises ActionController::RoutingError do - asset_path("logo.png") - end - @config.asset_host = method :compute_host - assert_raises ActionController::RoutingError do - asset_path("logo.png") - end - end - - test "image_tag" do - assert_dom_equal '<img alt="Xml" src="/assets/xml.png" />', image_tag("xml.png") - end - - test "image_path" do - assert_match %r{/assets/logo-[0-9a-f]+.png}, - image_path("logo.png") - - assert_match %r{/assets/logo-[0-9a-f]+.png}, - path_to_image("logo.png") - end - - test "font_path" do - assert_match %r{/assets/font-[0-9a-f]+.ttf}, - font_path("font.ttf") - - assert_match %r{/assets/font-[0-9a-f]+.ttf}, - path_to_font("font.ttf") - end - - test "javascript_path" do - assert_match %r{/assets/application-[0-9a-f]+.js}, - javascript_path("application") - - assert_match %r{/assets/application-[0-9a-f]+.js}, - javascript_path("application.js") - - assert_match %r{/assets/application-[0-9a-f]+.js}, - path_to_javascript("application.js") - end - - test "stylesheet_path" do - assert_match %r{/assets/application-[0-9a-f]+.css}, - stylesheet_path("application") - - assert_match %r{/assets/application-[0-9a-f]+.css}, - stylesheet_path("application.css") - - assert_match %r{/assets/application-[0-9a-f]+.css}, - path_to_stylesheet("application.css") - end - - test "stylesheets served without a controller in do not use asset hosts when the default protocol is :request" do - @controller = nil - @config.asset_host = "assets-%d.example.com" - @config.default_asset_host_protocol = :request - @config.perform_caching = true - - assert_match %r{/assets/logo-[0-9a-f]+.png}, - asset_path("logo.png") - end - - test "asset path with relative url root" do - @controller.config.relative_url_root = "/collaboration/hieraki" - assert_equal "/collaboration/hieraki/images/logo.gif", - asset_path("/images/logo.gif") - end - - test "asset path with relative url root when controller isn't present but relative_url_root is" do - @controller = nil - @config.relative_url_root = "/collaboration/hieraki" - assert_equal "/collaboration/hieraki/images/logo.gif", - asset_path("/images/logo.gif") - end - - test "font path through asset_path" do - assert_match %r{/assets/font-[0-9a-f]+.ttf}, - asset_path('font.ttf') - - assert_match %r{/assets/dir/font-[0-9a-f]+.ttf}, - asset_path("dir/font.ttf") - - assert_equal "http://www.example.com/fonts/font.ttf", - asset_path("http://www.example.com/fonts/font.ttf") - end - - test "javascript path through asset_path" do - assert_match %r{/assets/application-[0-9a-f]+.js}, - asset_path(:application, :ext => "js") - - assert_match %r{/assets/xmlhr-[0-9a-f]+.js}, - asset_path("xmlhr", :ext => "js") - assert_match %r{/assets/dir/xmlhr-[0-9a-f]+.js}, - asset_path("dir/xmlhr.js", :ext => "js") - - assert_equal "/dir/xmlhr.js", - asset_path("/dir/xmlhr", :ext => "js") - - assert_equal "http://www.example.com/js/xmlhr", - asset_path("http://www.example.com/js/xmlhr", :ext => "js") - assert_equal "http://www.example.com/js/xmlhr.js", - asset_path("http://www.example.com/js/xmlhr.js", :ext => "js") - end - - test "javascript include tag" do - assert_match %r{<script src="/assets/application-[0-9a-f]+.js" type="text/javascript"></script>}, - javascript_include_tag(:application) - assert_match %r{<script src="/assets/application-[0-9a-f]+.js" type="text/javascript"></script>}, - javascript_include_tag(:application, :digest => true) - assert_match %r{<script src="/assets/application.js" type="text/javascript"></script>}, - javascript_include_tag(:application, :digest => false) - - assert_match %r{<script src="/assets/xmlhr-[0-9a-f]+.js" type="text/javascript"></script>}, - javascript_include_tag("xmlhr") - assert_match %r{<script src="/assets/xmlhr-[0-9a-f]+.js" type="text/javascript"></script>}, - javascript_include_tag("xmlhr.js") - assert_equal '<script src="http://www.example.com/xmlhr" type="text/javascript"></script>', - javascript_include_tag("http://www.example.com/xmlhr") - - assert_match %r{<script src=\"/assets/xmlhr-[0-9a-f]+.js" type=\"text/javascript\"></script>\n<script src=\"/assets/extra-[0-9a-f]+.js" type=\"text/javascript\"></script>}, - javascript_include_tag("xmlhr", "extra") - - assert_match %r{<script src="/assets/xmlhr-[0-9a-f]+.js\?body=1" type="text/javascript"></script>\n<script src="/assets/application-[0-9a-f]+.js\?body=1" type="text/javascript"></script>}, - javascript_include_tag(:application, :debug => true) - - assert_match %r{<script src="/assets/jquery.plugin.js" type="text/javascript"></script>}, - javascript_include_tag('jquery.plugin', :digest => false) - - @config.assets.compile = true - @config.assets.debug = true - assert_match %r{<script src="/javascripts/application.js" type="text/javascript"></script>}, - javascript_include_tag('/javascripts/application') - assert_match %r{<script src="/assets/xmlhr-[0-9a-f]+.js\?body=1" type="text/javascript"></script>\n<script src="/assets/application-[0-9a-f]+.js\?body=1" type="text/javascript"></script>}, - javascript_include_tag(:application) - end - - test "stylesheet path through asset_path" do - assert_match %r{/assets/application-[0-9a-f]+.css}, asset_path(:application, :ext => "css") - - assert_match %r{/assets/style-[0-9a-f]+.css}, asset_path("style", :ext => "css") - assert_match %r{/assets/dir/style-[0-9a-f]+.css}, asset_path("dir/style.css", :ext => "css") - assert_equal "/dir/style.css", asset_path("/dir/style.css", :ext => "css") - - assert_equal "http://www.example.com/css/style", - asset_path("http://www.example.com/css/style", :ext => "css") - assert_equal "http://www.example.com/css/style.css", - asset_path("http://www.example.com/css/style.css", :ext => "css") - end - - test "stylesheet link tag" do - assert_match %r{<link href="/assets/application-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application) - assert_match %r{<link href="/assets/application-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application, :digest => true) - assert_match %r{<link href="/assets/application.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application, :digest => false) - - assert_match %r{<link href="/assets/style-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag("style") - assert_match %r{<link href="/assets/style-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag("style.css") - - assert_equal '<link href="http://www.example.com/style.css" media="screen" rel="stylesheet" type="text/css" />', - stylesheet_link_tag("http://www.example.com/style.css") - assert_match %r{<link href="/assets/style-[0-9a-f]+.css" media="all" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag("style", :media => "all") - assert_match %r{<link href="/assets/style-[0-9a-f]+.css" media="print" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag("style", :media => "print") - - assert_match %r{<link href="/assets/style-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />\n<link href="/assets/extra-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag("style", "extra") - - assert_match %r{<link href="/assets/style-[0-9a-f]+.css\?body=1" media="screen" rel="stylesheet" type="text/css" />\n<link href="/assets/application-[0-9a-f]+.css\?body=1" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application, :debug => true) - - @config.assets.compile = true - @config.assets.debug = true - assert_match %r{<link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag('/stylesheets/application') - - assert_match %r{<link href="/assets/style-[0-9a-f]+.css\?body=1" media="screen" rel="stylesheet" type="text/css" />\n<link href="/assets/application-[0-9a-f]+.css\?body=1" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application) - - assert_match %r{<link href="/assets/style-[0-9a-f]+.css\?body=1" media="print" rel="stylesheet" type="text/css" />\n<link href="/assets/application-[0-9a-f]+.css\?body=1" media="print" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application, :media => "print") - end - - test "alternate asset prefix" do - stubs(:asset_prefix).returns("/themes/test") - assert_match %r{/themes/test/style-[0-9a-f]+.css}, asset_path("style", :ext => "css") - end - - test "alternate asset environment" do - assets = Sprockets::Environment.new - assets.append_path(FIXTURES.join("sprockets/alternate/stylesheets")) - stubs(:asset_environment).returns(assets) - assert_match %r{/assets/style-[0-9a-f]+.css}, asset_path("style", :ext => "css") - end - - test "alternate hash based on environment" do - assets = Sprockets::Environment.new - assets.version = 'development' - assets.append_path(FIXTURES.join("sprockets/alternate/stylesheets")) - stubs(:asset_environment).returns(assets) - dev_path = asset_path("style", :ext => "css") - - assets.version = 'production' - prod_path = asset_path("style", :ext => "css") - - assert_not_equal prod_path, dev_path - end - - test "precedence of `config.digest = false` over manifest.yml asset digests" do - Rails.application.config.assets.digests = {'logo.png' => 'logo-d1g3st.png'} - @config.assets.digest = false - - assert_equal '/assets/logo.png', - asset_path("logo.png") - end -end diff --git a/actionpack/test/template/sprockets_helper_with_routes_test.rb b/actionpack/test/template/sprockets_helper_with_routes_test.rb deleted file mode 100644 index bcbd81a7dd..0000000000 --- a/actionpack/test/template/sprockets_helper_with_routes_test.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'abstract_unit' -require 'sprockets' -require 'sprockets/helpers/rails_helper' -require 'mocha' - -class SprocketsHelperWithRoutesTest < ActionView::TestCase - include Sprockets::Helpers::RailsHelper - - # Let's bring in some named routes to test namespace conflicts with potential *_paths. - # We have to do this after we bring in the Sprockets RailsHelper so if there are conflicts, - # they'll fail in the way we expect in a real live Rails app. - routes = ActionDispatch::Routing::RouteSet.new - routes.draw do - resources :assets - end - include routes.url_helpers - - def setup - super - @controller = BasicController.new - - @assets = Sprockets::Environment.new - @assets.append_path(FIXTURES.join("sprockets/app/javascripts")) - @assets.append_path(FIXTURES.join("sprockets/app/stylesheets")) - @assets.append_path(FIXTURES.join("sprockets/app/images")) - - application = Struct.new(:config, :assets).new(config, @assets) - Rails.stubs(:application).returns(application) - @config = config - @config.perform_caching = true - @config.assets.digest = true - @config.assets.compile = true - end - - test "namespace conflicts on a named route called asset_path" do - # Testing this for sanity - asset_path is now a named route! - assert_match asset_path('test_asset'), '/assets/test_asset' - - assert_match %r{/assets/logo-[0-9a-f]+.png}, - path_to_asset("logo.png") - assert_match %r{/assets/logo-[0-9a-f]+.png}, - path_to_asset("logo.png", :digest => true) - assert_match %r{/assets/logo.png}, - path_to_asset("logo.png", :digest => false) - end - - test "javascript_include_tag with a named_route named asset_path" do - assert_match %r{<script src="/assets/application-[0-9a-f]+.js" type="text/javascript"></script>}, - javascript_include_tag(:application) - end - - test "stylesheet_link_tag with a named_route named asset_path" do - assert_match %r{<link href="/assets/application-[0-9a-f]+.css" media="screen" rel="stylesheet" type="text/css" />}, - stylesheet_link_tag(:application) - end - -end
\ No newline at end of file diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb index 6c325d5abb..f0a7ce0bc9 100644 --- a/actionpack/test/template/tag_helper_test.rb +++ b/actionpack/test/template/tag_helper_test.rb @@ -30,8 +30,8 @@ class TagHelperTest < ActionView::TestCase end def test_tag_options_converts_boolean_option - assert_equal '<p disabled="disabled" multiple="multiple" readonly="readonly" />', - tag("p", :disabled => true, :multiple => true, :readonly => true) + assert_equal '<p disabled="disabled" itemscope="itemscope" multiple="multiple" readonly="readonly" />', + tag("p", :disabled => true, :itemscope => true, :multiple => true, :readonly => true) end def test_content_tag @@ -91,6 +91,11 @@ class TagHelperTest < ActionView::TestCase assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>") end + def test_cdata_section_splitted + assert_equal "<![CDATA[hello]]]]><![CDATA[>world]]>", cdata_section("hello]]>world") + assert_equal "<![CDATA[hello]]]]><![CDATA[>world]]]]><![CDATA[>again]]>", cdata_section("hello]]>world]]>again") + end + def test_escape_once assert_equal '1 < 2 & 3', escape_once('1 < 2 & 3') end @@ -113,8 +118,8 @@ class TagHelperTest < ActionView::TestCase def test_data_attributes ['data', :data].each { |data| - assert_dom_equal '<a data-a-number="1" data-array="[1,2,3]" data-hash="{"key":"value"}" data-string="hello" data-symbol="foo" />', - tag('a', { data => { :a_number => 1, :string => 'hello', :symbol => :foo, :array => [1, 2, 3], :hash => { :key => 'value'} } }) + assert_dom_equal '<a data-a-float="3.14" data-a-big-decimal="-123.456" data-a-number="1" data-array="[1,2,3]" data-hash="{"key":"value"}" data-string="hello" data-symbol="foo" />', + tag('a', { data => { :a_float => 3.14, :a_big_decimal => BigDecimal.new("-123.456"), :a_number => 1, :string => 'hello', :symbol => :foo, :array => [1, 2, 3], :hash => { :key => 'value'} } }) } end end diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb index 8c57ada587..86ba5f3b4d 100644 --- a/actionpack/test/template/template_test.rb +++ b/actionpack/test/template/template_test.rb @@ -48,7 +48,7 @@ class TestERBTemplate < ActiveSupport::TestCase end def new_template(body = "<%= hello %>", details = {}) - ActionView::Template.new(body, "hello template", ERBHandler, {:virtual_path => "hello"}.merge!(details)) + ActionView::Template.new(body, "hello template", details.fetch(:handler) { ERBHandler }, {:virtual_path => "hello"}.merge!(details)) end def render(locals = {}) @@ -59,11 +59,23 @@ class TestERBTemplate < ActiveSupport::TestCase @context = Context.new end + def test_mime_type_is_deprecated + template = new_template + assert_deprecated 'Template#mime_type is deprecated and will be removed' do + template.mime_type + end + end + def test_basic_template @template = new_template assert_equal "Hello", render end + def test_raw_template + @template = new_template("<%= hello %>", :handler => ActionView::Template::Handlers::Raw.new) + assert_equal "<%= hello %>", render + end + def test_template_loses_its_source_after_rendering @template = new_template render @@ -79,7 +91,7 @@ class TestERBTemplate < ActiveSupport::TestCase def test_locals @template = new_template("<%= my_local %>") @template.locals = [:my_local] - assert_equal "I'm a local", render(:my_local => "I'm a local") + assert_equal "I am a local", render(:my_local => "I am a local") end def test_restores_buffer diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb index 37858c1ba2..387aafebd4 100644 --- a/actionpack/test/template/test_case_test.rb +++ b/actionpack/test/template/test_case_test.rb @@ -68,14 +68,14 @@ module ActionView assert_nil self.class.determine_default_helper_class("String") end - test "delegates notice to request.flash" do - view.request.flash.expects(:notice).with("this message") - view.notice("this message") + test "delegates notice to request.flash[:notice]" do + view.request.flash.expects(:[]).with(:notice) + view.notice end - test "delegates alert to request.flash" do - view.request.flash.expects(:alert).with("this message") - view.alert("this message") + test "delegates alert to request.flash[:alert]" do + view.request.flash.expects(:[]).with(:alert) + view.alert end test "uses controller lookup context" do @@ -222,6 +222,25 @@ module ActionView end end + test "is able to use mounted routes" do + with_routing do |set| + app = Class.new do + def self.routes + @routes ||= ActionDispatch::Routing::RouteSet.new + end + + routes.draw { get "bar", :to => lambda {} } + + def self.call(*) + end + end + + set.draw { mount app => "/foo", :as => "foo_app" } + + assert_equal '/foo/bar', foo_app.bar_path + end + end + test "named routes can be used from helper included in view" do with_routing do |set| set.draw { resources :contents } @@ -277,6 +296,12 @@ module ActionView 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") diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb index adcbf1447f..108a674d95 100644 --- a/actionpack/test/template/test_test.rb +++ b/actionpack/test/template/test_test.rb @@ -48,7 +48,7 @@ class PeopleHelperTest < ActionView::TestCase def with_test_route_set with_routing do |set| set.draw do - match 'people', :to => 'people#index', :as => :people + get 'people', :to => 'people#index', :as => :people end yield end diff --git a/actionpack/test/template/testing/fixture_resolver_test.rb b/actionpack/test/template/testing/fixture_resolver_test.rb index de83540468..9649f349cb 100644 --- a/actionpack/test/template/testing/fixture_resolver_test.rb +++ b/actionpack/test/template/testing/fixture_resolver_test.rb @@ -8,8 +8,8 @@ class FixtureResolverTest < ActiveSupport::TestCase end def test_should_return_template_for_declared_path - resolver = ActionView::FixtureResolver.new("arbitrary/path" => "this text") - templates = resolver.find_all("path", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => []}) + resolver = ActionView::FixtureResolver.new("arbitrary/path.erb" => "this text") + templates = resolver.find_all("path", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => [:erb]}) assert_equal 1, templates.size, "expected one template" assert_equal "this text", templates.first.source assert_equal "arbitrary/path", templates.first.virtual_path diff --git a/actionpack/test/template/testing/null_resolver_test.rb b/actionpack/test/template/testing/null_resolver_test.rb index e142506e6a..55ec36e753 100644 --- a/actionpack/test/template/testing/null_resolver_test.rb +++ b/actionpack/test/template/testing/null_resolver_test.rb @@ -3,10 +3,10 @@ require 'abstract_unit' class NullResolverTest < ActiveSupport::TestCase def test_should_return_template_for_any_path resolver = ActionView::NullResolver.new() - templates = resolver.find_all("path", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => []}) + templates = resolver.find_all("path.erb", "arbitrary", false, {:locale => [], :formats => [:html], :handlers => []}) assert_equal 1, templates.size, "expected one template" assert_equal "Template generated by Null Resolver", templates.first.source - assert_equal "arbitrary/path", templates.first.virtual_path + assert_equal "arbitrary/path.erb", templates.first.virtual_path.to_s assert_equal [:html], templates.first.formats end end diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb index 5865b7f23c..412d13bb2b 100644 --- a/actionpack/test/template/text_helper_test.rb +++ b/actionpack/test/template/text_helper_test.rb @@ -46,6 +46,14 @@ class TextHelperTest < ActionView::TestCase assert_equal "<p><b> test with unsafe string </b><script>code!</script></p>", simple_format("<b> test with unsafe string </b><script>code!</script>", {}, :sanitize => false) end + def test_simple_format_with_custom_wrapper + assert_equal "<div></div>", simple_format(nil, {}, :wrapper_tag => "div") + end + + def test_simple_format_with_custom_wrapper_and_multi_line_breaks + assert_equal "<div>We want to put a wrapper...</div>\n\n<div>...right there.</div>", simple_format("We want to put a wrapper...\n\n...right there.", {}, :wrapper_tag => "div") + end + def test_simple_format_should_not_change_the_text_passed text = "<b>Ok</b><script>code!</script>" text_clone = text.dup @@ -53,8 +61,18 @@ class TextHelperTest < ActionView::TestCase assert_equal text_clone, text end - def test_truncate_should_not_be_html_safe - assert !truncate("Hello World!", :length => 12).html_safe? + def test_simple_format_does_not_modify_the_html_options_hash + options = { :class => "foobar"} + passed_options = options.dup + simple_format("some text", passed_options) + assert_equal options, passed_options + end + + def test_simple_format_does_not_modify_the_options_hash + options = { :wrapper_tag => :div, :sanitize => false } + passed_options = options.dup + simple_format("some text", {}, passed_options) + assert_equal options, passed_options end def test_truncate @@ -62,10 +80,6 @@ class TextHelperTest < ActionView::TestCase assert_equal "Hello Wor...", truncate("Hello World!!", :length => 12) end - def test_truncate_should_not_escape_input - assert_equal "Hello <sc...", truncate("Hello <script>code!</script>World!!", :length => 12) - end - def test_truncate_should_use_default_length_of_30 str = "This is a string that will go longer then the default truncate length of 30" assert_equal str[0...27] + "...", truncate(str) @@ -85,6 +99,60 @@ class TextHelperTest < ActionView::TestCase truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10) end + def test_truncate_does_not_modify_the_options_hash + options = { :length => 10 } + passed_options = options.dup + truncate("some text", passed_options) + assert_equal options, passed_options + end + + def test_truncate_with_link_options + assert_equal "Here is a long test and ...<a href=\"#\">Continue</a>", + truncate("Here is a long test and I need a continue to read link", :length => 27) { link_to 'Continue', '#' } + end + + def test_truncate_should_be_html_safe + assert truncate("Hello World!", :length => 12).html_safe? + end + + def test_truncate_should_escape_the_input + assert_equal "Hello <sc...", truncate("Hello <script>code!</script>World!!", :length => 12) + end + + def test_truncate_should_not_escape_the_input_with_escape_false + assert_equal "Hello <sc...", truncate("Hello <script>code!</script>World!!", :length => 12, :escape => false) + end + + def test_truncate_with_escape_false_should_be_html_safe + truncated = truncate("Hello <script>code!</script>World!!", :length => 12, :escape => false) + assert truncated.html_safe? + end + + def test_truncate_with_block_should_be_html_safe + truncated = truncate("Here's a long test and I need a continue to read link", :length => 27) { link_to 'Continue', '#' } + assert truncated.html_safe? + end + + def test_truncate_with_block_should_escape_the_input + assert_equal "<script>code!</script>He...<a href=\"#\">Continue</a>", + truncate("<script>code!</script>Here's a long test and I need a continue to read link", :length => 27) { link_to 'Continue', '#' } + end + + def test_truncate_with_block_should_not_escape_the_input_with_escape_false + assert_equal "<script>code!</script>He...<a href=\"#\">Continue</a>", + truncate("<script>code!</script>Here's a long test and I need a continue to read link", :length => 27, :escape => false) { link_to 'Continue', '#' } + end + + def test_truncate_with_block_with_escape_false_should_be_html_safe + truncated = truncate("<script>code!</script>Here's a long test and I need a continue to read link", :length => 27, :escape => false) { link_to 'Continue', '#' } + assert truncated.html_safe? + end + + def test_truncate_with_block_should_escape_the_block + assert_equal "Here is a long test and ...<script>alert('foo');</script>", + truncate("Here is a long test and I need a continue to read link", :length => 27) { "<script>alert('foo');</script>" } + end + def test_highlight_should_be_html_safe assert highlight("This is a beautiful morning", "beautiful").html_safe? end @@ -102,7 +170,7 @@ class TextHelperTest < ActionView::TestCase assert_equal( "This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day", - highlight("This is a beautiful morning, but also a beautiful day", "beautiful", '<b>\1</b>') + highlight("This is a beautiful morning, but also a beautiful day", "beautiful", :highlighter => '<b>\1</b>') ) assert_equal( @@ -145,14 +213,7 @@ class TextHelperTest < ActionView::TestCase end def test_highlight_with_multiple_phrases_in_one_pass - assert_equal %(<em>wow</em> <em>em</em>), highlight('wow em', %w(wow em), '<em>\1</em>') - end - - def test_highlight_with_options_hash - assert_equal( - "This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day", - highlight("This is a beautiful morning, but also a beautiful day", "beautiful", :highlighter => '<b>\1</b>') - ) + assert_equal %(<em>wow</em> <em>em</em>), highlight('wow em', %w(wow em), :highlighter => '<em>\1</em>') end def test_highlight_with_html @@ -182,41 +243,47 @@ class TextHelperTest < ActionView::TestCase ) end + def test_highlight_does_not_modify_the_options_hash + options = { :highlighter => '<b>\1</b>', :sanitize => false } + passed_options = options.dup + highlight("<div>abc div</div>", "div", passed_options) + assert_equal options, passed_options + end + def test_excerpt - assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", 5)) - assert_equal("This is a...", excerpt("This is a beautiful morning", "this", 5)) - assert_equal("...iful morning", excerpt("This is a beautiful morning", "morning", 5)) + assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", :radius => 5)) + assert_equal("This is a...", excerpt("This is a beautiful morning", "this", :radius => 5)) + assert_equal("...iful morning", excerpt("This is a beautiful morning", "morning", :radius => 5)) assert_nil excerpt("This is a beautiful morning", "day") end def test_excerpt_should_not_be_html_safe - assert !excerpt('This is a beautiful! morning', 'beautiful', 5).html_safe? + assert !excerpt('This is a beautiful! morning', 'beautiful', :radius => 5).html_safe? end def test_excerpt_in_borderline_cases - assert_equal("", excerpt("", "", 0)) - assert_equal("a", excerpt("a", "a", 0)) - assert_equal("...b...", excerpt("abc", "b", 0)) - assert_equal("abc", excerpt("abc", "b", 1)) - assert_equal("abc...", excerpt("abcd", "b", 1)) - assert_equal("...abc", excerpt("zabc", "b", 1)) - assert_equal("...abc...", excerpt("zabcd", "b", 1)) - assert_equal("zabcd", excerpt("zabcd", "b", 2)) + assert_equal("", excerpt("", "", :radius => 0)) + assert_equal("a", excerpt("a", "a", :radius => 0)) + assert_equal("...b...", excerpt("abc", "b", :radius => 0)) + assert_equal("abc", excerpt("abc", "b", :radius => 1)) + assert_equal("abc...", excerpt("abcd", "b", :radius => 1)) + assert_equal("...abc", excerpt("zabc", "b", :radius => 1)) + assert_equal("...abc...", excerpt("zabcd", "b", :radius => 1)) + assert_equal("zabcd", excerpt("zabcd", "b", :radius => 2)) # excerpt strips the resulting string before ap-/prepending excerpt_string. # whether this behavior is meaningful when excerpt_string is not to be # appended is questionable. - assert_equal("zabcd", excerpt(" zabcd ", "b", 4)) - assert_equal("...abc...", excerpt("z abc d", "b", 1)) + assert_equal("zabcd", excerpt(" zabcd ", "b", :radius => 4)) + assert_equal("...abc...", excerpt("z abc d", "b", :radius => 1)) end def test_excerpt_with_regex - assert_equal('...is a beautiful! mor...', excerpt('This is a beautiful! morning', 'beautiful', 5)) - assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', 5)) + assert_equal('...is a beautiful! mor...', excerpt('This is a beautiful! morning', 'beautiful', :radius => 5)) + assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', :radius => 5)) end - def test_excerpt_with_options_hash - assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", :radius => 5)) + def test_excerpt_with_omission assert_equal("[...]is a beautiful morn[...]", excerpt("This is a beautiful morning", "beautiful", :omission => "[...]",:radius => 5)) assert_equal( "This is the ultimate supercalifragilisticexpialidoceous very looooooooooooooooooong looooooooooooong beautiful morning with amazing sunshine and awesome tempera[...]", @@ -226,19 +293,42 @@ class TextHelperTest < ActionView::TestCase end def test_excerpt_with_utf8 - assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', 8)) + assert_equal("...\357\254\203ciency could not be...".force_encoding('UTF-8'), excerpt("That's why e\357\254\203ciency could not be helped".force_encoding('UTF-8'), 'could', :radius => 8)) + end + + def test_excerpt_does_not_modify_the_options_hash + options = { :omission => "[...]",:radius => 5 } + passed_options = options.dup + excerpt("This is a beautiful morning", "beautiful", passed_options) + assert_equal options, passed_options + end + + def test_excerpt_with_separator + options = { :separator => ' ', :radius => 1 } + assert_equal('...a very beautiful...', excerpt('This is a very beautiful morning', 'very', options)) + assert_equal('This is...', excerpt('This is a very beautiful morning', 'this', options)) + assert_equal('...beautiful morning', excerpt('This is a very beautiful morning', 'morning', options)) + + options = { :separator => "\n", :radius => 0 } + assert_equal("...very long...", excerpt("my very\nvery\nvery long\nstring", 'long', options)) + + options = { :separator => "\n", :radius => 1 } + assert_equal("...very\nvery long\nstring", excerpt("my very\nvery\nvery long\nstring", 'long', options)) end def test_word_wrap - assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", 15)) + assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15)) end def test_word_wrap_with_extra_newlines - assert_equal("my very very\nvery long\nstring\n\nwith another\nline", word_wrap("my very very very long string\n\nwith another line", 15)) + assert_equal("my very very\nvery long\nstring\n\nwith another\nline", word_wrap("my very very very long string\n\nwith another line", :line_width => 15)) end - def test_word_wrap_with_options_hash - assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15)) + def test_word_wrap_does_not_modify_the_options_hash + options = { :line_width => 15 } + passed_options = options.dup + word_wrap("some text", passed_options) + assert_equal options, passed_options end def test_pluralization diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb index 397de9c2ce..d496dbb35e 100644 --- a/actionpack/test/template/translation_helper_test.rb +++ b/actionpack/test/template/translation_helper_test.rb @@ -11,7 +11,8 @@ class TranslationHelperTest < ActiveSupport::TestCase :translations => { :templates => { :found => { :foo => 'Foo' }, - :array => { :foo => { :bar => 'Foo Bar' } } + :array => { :foo => { :bar => 'Foo Bar' } }, + :default => { :foo => 'Foo' } }, :foo => 'Foo', :hello => '<a>Hello World</a>', @@ -71,6 +72,10 @@ class TranslationHelperTest < ActiveSupport::TestCase assert_equal 'Foo Bar', @view.render(:file => 'translations/templates/array').strip end + def test_default_lookup_scoped_by_partial + assert_equal 'Foo', view.render(:file => 'translations/templates/default').strip + end + def test_missing_translation_scoped_by_partial expected = '<span class="translation_missing" title="translation missing: en.translations.templates.missing.missing">Missing</span>' assert_equal expected, view.render(:file => 'translations/templates/missing').strip @@ -102,4 +107,32 @@ class TranslationHelperTest < ActiveSupport::TestCase def test_translation_returning_an_array_ignores_html_suffix assert_equal ["foo", "bar"], translate(:'translations.array_html') end + + def test_translate_with_default_named_html + translation = translate(:'translations.missing', :default => :'translations.hello_html') + assert_equal '<a>Hello World</a>', translation + assert_equal true, translation.html_safe? + end + + def test_translate_with_two_defaults_named_html + translation = translate(:'translations.missing', :default => [:'translations.missing_html', :'translations.hello_html']) + assert_equal '<a>Hello World</a>', translation + assert_equal true, translation.html_safe? + end + + def test_translate_with_last_default_named_html + translation = translate(:'translations.missing', :default => [:'translations.missing', :'translations.hello_html']) + assert_equal '<a>Hello World</a>', translation + assert_equal true, translation.html_safe? + end + + def test_translate_with_string_default + translation = translate(:'translations.missing', default: 'A Generic String') + assert_equal 'A Generic String', translation + end + + def test_translate_with_array_of_string_defaults + translation = translate(:'translations.missing', default: ['A Generic String', 'Second generic string']) + assert_equal 'A Generic String', translation + end end diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb index b482bd3251..134177d74d 100644 --- a/actionpack/test/template/url_helper_test.rb +++ b/actionpack/test/template/url_helper_test.rb @@ -15,14 +15,14 @@ class UrlHelperTest < ActiveSupport::TestCase routes = ActionDispatch::Routing::RouteSet.new routes.draw do - match "/" => "foo#bar" - match "/other" => "foo#other" - match "/article/:id" => "foo#article", :as => :article + get "/" => "foo#bar" + get "/other" => "foo#other" + get "/article/:id" => "foo#article", :as => :article end + include ActionView::Helpers::UrlHelper include routes.url_helpers - include ActionView::Helpers::UrlHelper include ActionView::Helpers::JavaScriptHelper include ActionDispatch::Assertions::DomAssertions include ActionView::Context @@ -90,17 +90,35 @@ class UrlHelperTest < ActiveSupport::TestCase def test_button_to_with_javascript_confirm assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :confirm => "Are you sure?") + button_to("Hello", "http://www.example.com", :data => { :confirm => "Are you sure?" }) ) end + def test_button_to_with_deprecated_confirm + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :confirm => "Are you sure?") + ) + end + end + def test_button_to_with_javascript_disable_with assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :disable_with => "Greeting...") + button_to("Hello", "http://www.example.com", :data => { :disable_with => "Greeting..." }) ) end + def test_button_to_with_javascript_deprecated_disable_with + assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead" do + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :disable_with => "Greeting...") + ) + end + end + def test_button_to_with_remote_and_form_options assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"custom-class\" data-remote=\"true\" data-type=\"json\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com", :remote => true, :form => { :class => "custom-class", "data-type" => "json" } ) end @@ -108,22 +126,33 @@ class UrlHelperTest < ActiveSupport::TestCase def test_button_to_with_remote_and_javascript_confirm assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :remote => true, :confirm => "Are you sure?") + button_to("Hello", "http://www.example.com", :remote => true, :data => { :confirm => "Are you sure?" }) ) end + def test_button_to_with_remote_and_javascript_with_deprecated_confirm + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :remote => true, :confirm => "Are you sure?") + ) + end + end + def test_button_to_with_remote_and_javascript_disable_with assert_dom_equal( "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :remote => true, :disable_with => "Greeting...") + button_to("Hello", "http://www.example.com", :remote => true, :data => { :disable_with => "Greeting..." }) ) end - def test_button_to_with_remote_and_javascript_confirm_and_javascript_disable_with - assert_dom_equal( - "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" data-confirm=\"Are you sure?\" type=\"submit\" value=\"Hello\" /></div></form>", - button_to("Hello", "http://www.example.com", :remote => true, :confirm => "Are you sure?", :disable_with => "Greeting...") - ) + def test_button_to_with_remote_and_javascript_deprecated_disable_with + assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead" do + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\" data-remote=\"true\"><div><input data-disable-with=\"Greeting...\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :remote => true, :disable_with => "Greeting...") + ) + end end def test_button_to_with_remote_false @@ -158,6 +187,13 @@ class UrlHelperTest < ActiveSupport::TestCase ) end + def test_button_to_with_block + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button_to\"><div><button type=\"submit\"><span>Hello</span></button></div></form>", + button_to("http://www.example.com") { content_tag(:span, 'Hello') } + ) + end + def test_link_tag_with_straight_url assert_dom_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", "http://www.example.com") end @@ -208,25 +244,46 @@ class UrlHelperTest < ActiveSupport::TestCase def test_link_tag_with_custom_onclick link = link_to("Hello", "http://www.example.com", :onclick => "alert('yay!')") - expected = %{<a href="http://www.example.com" onclick="alert('yay!')">Hello</a>} + expected = %{<a href="http://www.example.com" onclick="alert('yay!')">Hello</a>} assert_dom_equal expected, link end def test_link_tag_with_javascript_confirm assert_dom_equal( "<a href=\"http://www.example.com\" data-confirm=\"Are you sure?\">Hello</a>", - link_to("Hello", "http://www.example.com", :confirm => "Are you sure?") + link_to("Hello", "http://www.example.com", :data => { :confirm => "Are you sure?" }) ) assert_dom_equal( - "<a href=\"http://www.example.com\" data-confirm=\"You can't possibly be sure, can you?\">Hello</a>", - link_to("Hello", "http://www.example.com", :confirm => "You can't possibly be sure, can you?") + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure, can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :data => { :confirm => "You cant possibly be sure, can you?" }) ) assert_dom_equal( - "<a href=\"http://www.example.com\" data-confirm=\"You can't possibly be sure,\n can you?\">Hello</a>", - link_to("Hello", "http://www.example.com", :confirm => "You can't possibly be sure,\n can you?") + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure,\n can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :data => { :confirm => "You cant possibly be sure,\n can you?" }) ) end + def test_link_tag_with_deprecated_confirm + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<a href=\"http://www.example.com\" data-confirm=\"Are you sure?\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "Are you sure?") + ) + end + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure, can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "You cant possibly be sure, can you?") + ) + end + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<a href=\"http://www.example.com\" data-confirm=\"You cant possibly be sure,\n can you?\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "You cant possibly be sure,\n can you?") + ) + end + end + def test_link_to_with_remote assert_dom_equal( "<a href=\"http://www.example.com\" data-remote=\"true\">Hello</a>", @@ -272,18 +329,47 @@ class UrlHelperTest < ActiveSupport::TestCase def test_link_tag_using_post_javascript_and_confirm assert_dom_equal( "<a href=\"http://www.example.com\" data-method=\"post\" rel=\"nofollow\" data-confirm=\"Are you serious?\">Hello</a>", - link_to("Hello", "http://www.example.com", :method => :post, :confirm => "Are you serious?") + link_to("Hello", "http://www.example.com", :method => :post, :data => { :confirm => "Are you serious?" }) ) end + def test_link_tag_using_post_javascript_and_with_deprecated_confirm + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<a href=\"http://www.example.com\" data-method=\"post\" rel=\"nofollow\" data-confirm=\"Are you serious?\">Hello</a>", + link_to("Hello", "http://www.example.com", :method => :post, :confirm => "Are you serious?") + ) + end + end + def test_link_tag_using_delete_javascript_and_href_and_confirm assert_dom_equal( "<a href='\#' rel=\"nofollow\" data-confirm=\"Are you serious?\" data-method=\"delete\">Destroy</a>", - link_to("Destroy", "http://www.example.com", :method => :delete, :href => '#', :confirm => "Are you serious?"), + link_to("Destroy", "http://www.example.com", :method => :delete, :href => '#', :data => { :confirm => "Are you serious?" }), "When specifying url, form should be generated with it, but not this.href" ) end + def test_link_tag_using_delete_javascript_and_href_and_with_deprecated_confirm + assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do + assert_dom_equal( + "<a href='\#' rel=\"nofollow\" data-confirm=\"Are you serious?\" data-method=\"delete\">Destroy</a>", + link_to("Destroy", "http://www.example.com", :method => :delete, :href => '#', :confirm => "Are you serious?"), + "When specifying url, form should be generated with it, but not this.href" + ) + end + end + + def test_link_tag_with_block + assert_dom_equal '<a href="/"><span>Example site</span></a>', + link_to('/') { content_tag(:span, 'Example site') } + end + + def test_link_tag_with_block_and_html_options + assert_dom_equal '<a class="special" href="/"><span>Example site</span></a>', + link_to('/', :class => "special") { content_tag(:span, 'Example site') } + end + def test_link_tag_using_block_in_erb out = render_erb %{<%= link_to('/') do %>Example site<% end %>} assert_equal '<a href="/">Example site</a>', out @@ -296,6 +382,16 @@ class UrlHelperTest < ActiveSupport::TestCase ) end + def test_link_tag_escapes_content + assert_dom_equal '<a href="/">Malicious <script>content</script></a>', + link_to("Malicious <script>content</script>", "/") + end + + def test_link_tag_does_not_escape_html_safe_content + assert_dom_equal '<a href="/">Malicious <script>content</script></a>', + link_to("Malicious <script>content</script>".html_safe, "/") + end + def test_link_to_unless assert_equal "Showing", link_to_unless(true, "Showing", url_hash) @@ -408,12 +504,12 @@ class UrlHelperTest < ActiveSupport::TestCase def test_mail_to_with_javascript snippet = mail_to("me@domain.com", "My email", :encode => "javascript") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet end def test_mail_to_with_javascript_unicode snippet = mail_to("unicode@example.com", "Ășnicode", :encode => "javascript") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%75%6e%69%63%6f%64%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%5c%22%3e%c3%ba%6e%69%63%6f%64%65%3c%5c%2f%61%3e%27%29%3b'))</script>", snippet end def test_mail_with_options @@ -438,8 +534,8 @@ class UrlHelperTest < ActiveSupport::TestCase assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain.com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex", :replace_at => "(at)") assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain(dot)com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") - assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%4d%79%20%65%6d%61%69%6c%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script>eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%5c%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%5c%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%5c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") end def test_mail_to_returns_html_safe_string @@ -471,25 +567,25 @@ end class UrlHelperControllerTest < ActionController::TestCase class UrlHelperController < ActionController::Base test_routes do - match 'url_helper_controller_test/url_helper/show/:id', + get 'url_helper_controller_test/url_helper/show/:id', :to => 'url_helper_controller_test/url_helper#show', :as => :show - match 'url_helper_controller_test/url_helper/profile/:name', + get 'url_helper_controller_test/url_helper/profile/:name', :to => 'url_helper_controller_test/url_helper#show', :as => :profile - match 'url_helper_controller_test/url_helper/show_named_route', + get 'url_helper_controller_test/url_helper/show_named_route', :to => 'url_helper_controller_test/url_helper#show_named_route', :as => :show_named_route - match "/:controller(/:action(/:id))" + get "/:controller(/:action(/:id))" - match 'url_helper_controller_test/url_helper/normalize_recall_params', + get 'url_helper_controller_test/url_helper/normalize_recall_params', :to => UrlHelperController.action(:normalize_recall), :as => :normalize_recall_params - match '/url_helper_controller_test/url_helper/override_url_helper/default', + get '/url_helper_controller_test/url_helper/override_url_helper/default', :to => 'url_helper_controller_test/url_helper#override_url_helper', :as => :override_url_helper end @@ -566,7 +662,7 @@ class UrlHelperControllerTest < ActionController::TestCase def test_named_route_should_show_host_and_path_using_controller_default_url_options class << @controller - def default_url_options(options = nil) + def default_url_options {:host => 'testtwo.host'} end end diff --git a/actionpack/test/ts_isolated.rb b/actionpack/test/ts_isolated.rb index 7430de2299..c44c5d8968 100644 --- a/actionpack/test/ts_isolated.rb +++ b/actionpack/test/ts_isolated.rb @@ -1,9 +1,5 @@ -$:.unshift(File.dirname(__FILE__)) -$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') - require 'minitest/autorun' require 'rbconfig' -require 'active_support/core_ext/kernel/reporting' require 'abstract_unit' class TestIsolated < ActiveSupport::TestCase @@ -13,7 +9,7 @@ class TestIsolated < ActiveSupport::TestCase define_method("test #{file}") do command = "#{ruby} -Ilib:test #{file}" result = silence_stderr { `#{command}` } - assert_block("#{command}\n#{result}") { $?.to_i.zero? } + assert $?.to_i.zero?, "#{command}\n#{result}" end end end |