diff options
Diffstat (limited to 'actionpack')
40 files changed, 260 insertions, 119 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 0134bf7cab..2cbe09e3e7 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,40 @@ +* Fix regression where a gzip file response would have a Content-type, + even when it was a 304 status code. + + See #19271. + + *Kohei Suzuki* + +* Fix handling of empty X_FORWARDED_HOST header in raw_host_with_port + + Previously, an empty X_FORWARDED_HOST header would cause + Actiondispatch::Http:URL.raw_host_with_port to return nil, causing + Actiondispatch::Http:URL.host to raise a NoMethodError. + + *Adam Forsyth* + +* Drop request class from RouteSet constructor. + + If you would like to use a custom request class, please subclass and implement + the `request_class` method. + + *tenderlove@ruby-lang.org* + +* Fallback to `ENV['RAILS_RELATIVE_URL_ROOT']` in `url_for`. + + Fixed an issue where the `RAILS_RELATIVE_URL_ROOT` environment variable is not + prepended to the path when `url_for` is called. If `SCRIPT_NAME` (used by Rack) + is set, it takes precedence. + + Fixes #5122. + + *Yasyf Mohamedali* + +* Partitioning of routes is now done when the routes are being drawn. This + helps to decrease the time spent filtering the routes during the first request. + + *Guo Xiang Tan* + * Fix regression in functional tests. Responses should have default headers assigned. diff --git a/actionpack/Rakefile b/actionpack/Rakefile index 4b60b77759..3bd27f8d64 100644 --- a/actionpack/Rakefile +++ b/actionpack/Rakefile @@ -9,10 +9,7 @@ task :default => :test # Run the unit tests Rake::TestTask.new do |t| t.libs << 'test' - - # make sure we include the tests in alphabetical order as on some systems - # this will not happen automatically and the tests (as a whole) will error - t.test_files = test_files.sort + t.test_files = test_files t.warning = true t.verbose = true diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec index d9b23ad4a9..b6b70a027c 100644 --- a/actionpack/actionpack.gemspec +++ b/actionpack/actionpack.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |s| s.summary = 'Web-flow and rendering framework putting the VC in MVC (part of Rails).' s.description = 'Web apps on Rails. Simple, battle-tested conventions for building and testing MVC web applications. Works with any Rack-compatible server.' - s.required_ruby_version = '>= 2.2.0' + s.required_ruby_version = '>= 2.2.1' s.license = 'MIT' @@ -22,8 +22,8 @@ Gem::Specification.new do |s| s.add_dependency 'activesupport', version s.add_dependency 'rack', '~> 1.6' - s.add_dependency 'rack-test', '~> 0.6.2' - s.add_dependency 'rails-html-sanitizer', '~> 1.0', '>= 1.0.1' + s.add_dependency 'rack-test', '~> 0.6.3' + s.add_dependency 'rails-html-sanitizer', '~> 1.0', '>= 1.0.2' s.add_dependency 'rails-dom-testing', '~> 1.0', '>= 1.0.5' s.add_dependency 'actionview', version diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index 858870d8b8..47bcfdb1e9 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -15,7 +15,7 @@ module ActionController module ClassMethods # Allows you to consider additional controller-wide information when generating an ETag. # For example, if you serve pages tailored depending on who's logged in at the moment, you - # may want to add the current user id to be part of the ETag to prevent authorized displaying + # may want to add the current user id to be part of the ETag to prevent unauthorized displaying # of cached pages. # # class InvoicesController < ApplicationController diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb index 0d93e2f7aa..70f42bf565 100644 --- a/actionpack/lib/action_controller/metal/head.rb +++ b/actionpack/lib/action_controller/metal/head.rb @@ -38,6 +38,8 @@ module ActionController headers.delete('Content-Type') headers.delete('Content-Length') end + + true end private diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb index a9c3e438fb..4038101fe0 100644 --- a/actionpack/lib/action_controller/metal/helpers.rb +++ b/actionpack/lib/action_controller/metal/helpers.rb @@ -93,6 +93,10 @@ module ActionController super(args) end + # Returns a list of helper names in a given path. + # + # ActionController::Base.all_helpers_from_path 'app/helpers' + # # => ["application", "chart", "rubygems"] def all_helpers_from_path(path) helpers = Array(path).flat_map do |_path| extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/ diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb index 20afcee537..2273406948 100644 --- a/actionpack/lib/action_controller/metal/http_authentication.rb +++ b/actionpack/lib/action_controller/metal/http_authentication.rb @@ -314,7 +314,7 @@ module ActionController nonce(secret_key, t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout end - # Opaque based on random generation - but changing each request? + # Opaque based on digest of secret key def opaque(secret_key) ::Digest::MD5.hexdigest(secret_key) end diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index a7e734db42..0a04848eba 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -131,7 +131,7 @@ module ActionController private # Determine the wrapper model from the controller's name. By convention, # this could be done by trying to find the defined model that has the - # same singularize name as the controller. For example, +UsersController+ + # same singular name as the controller. For example, +UsersController+ # will try to find if the +User+ model exists. # # This method also does namespace lookup. Foo::Bar::UsersController will diff --git a/actionpack/lib/action_controller/metal/url_for.rb b/actionpack/lib/action_controller/metal/url_for.rb index 572d1770f7..fbaa90d521 100644 --- a/actionpack/lib/action_controller/metal/url_for.rb +++ b/actionpack/lib/action_controller/metal/url_for.rb @@ -4,7 +4,10 @@ module ActionController # # In addition to <tt>AbstractController::UrlFor</tt>, this module accesses the HTTP layer to define # url options like the +host+. In order to do so, this module requires the host class - # to implement +env+ and +request+, which need to be a Rack-compatible. + # to implement +env+ which needs to be Rack-compatible and +request+ + # which is either instance of +ActionDispatch::Request+ or an object + # that responds to <tt>host</tt>, <tt>optional_port</tt>, <tt>protocol</tt> and + # <tt>symbolized_path_parameter</tt> methods. # # class RootUrl # include ActionController::UrlFor diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 4782991463..33c24999f9 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -201,7 +201,7 @@ module ActionController super self.session = TestSession.new - self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => SecureRandom.hex(16)) + self.session_options = TestSession::DEFAULT_OPTIONS end def assign_parameters(routes, controller_path, action, parameters = {}) diff --git a/actionpack/lib/action_dispatch/http/filter_redirect.rb b/actionpack/lib/action_dispatch/http/filter_redirect.rb index cd603649c3..bf79963351 100644 --- a/actionpack/lib/action_dispatch/http/filter_redirect.rb +++ b/actionpack/lib/action_dispatch/http/filter_redirect.rb @@ -4,7 +4,7 @@ module ActionDispatch FILTERED = '[FILTERED]'.freeze # :nodoc: - def filtered_location + def filtered_location # :nodoc: filters = location_filter if !filters.empty? && location_filter_match?(filters) FILTERED diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 07b3814ca4..732ee67268 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -114,7 +114,7 @@ module ActionDispatch end def engine_script_name(_routes) # :nodoc: - env["ROUTES_#{_routes.object_id}_SCRIPT_NAME"] + env[_routes.env_key] end def request_method=(request_method) #:nodoc: diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 001b14ec97..f5b709ccd6 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -67,7 +67,7 @@ module ActionDispatch end def path_for(options) - path = options[:script_name].to_s.chomp("/") + path = options[:script_name].to_s.chomp("/".freeze) path << options[:path] if options.key?(:path) add_trailing_slash(path) if options[:trailing_slash] @@ -229,7 +229,7 @@ module ActionDispatch # req = Request.new 'HTTP_HOST' => 'example.com:8080' # req.raw_host_with_port # => "example.com:8080" def raw_host_with_port - if forwarded = env["HTTP_X_FORWARDED_HOST"] + if forwarded = env["HTTP_X_FORWARDED_HOST"].presence forwarded.split(/,\s?/).last else env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}" diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb index 2b036796ab..cc4bd6105d 100644 --- a/actionpack/lib/action_dispatch/journey/router.rb +++ b/actionpack/lib/action_dispatch/journey/router.rb @@ -88,7 +88,7 @@ module ActionDispatch end def custom_routes - partitioned_routes.last + routes.custom_routes end def filter_routes(path) diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb index 80e3818ccd..a6d1980db2 100644 --- a/actionpack/lib/action_dispatch/journey/routes.rb +++ b/actionpack/lib/action_dispatch/journey/routes.rb @@ -5,13 +5,14 @@ module ActionDispatch class Routes # :nodoc: include Enumerable - attr_reader :routes, :named_routes + attr_reader :routes, :named_routes, :custom_routes, :anchored_routes def initialize @routes = [] @named_routes = {} @ast = nil - @partitioned_routes = nil + @anchored_routes = [] + @custom_routes = [] @simulator = nil end @@ -30,18 +31,22 @@ module ActionDispatch def clear routes.clear + anchored_routes.clear + custom_routes.clear named_routes.clear end - def partitioned_routes - @partitioned_routes ||= routes.partition do |r| - r.path.anchored && r.ast.grep(Nodes::Symbol).all?(&:default_regexp?) + def partition_route(route) + if route.path.anchored && route.ast.grep(Nodes::Symbol).all?(&:default_regexp?) + anchored_routes << route + else + custom_routes << route end end def ast @ast ||= begin - asts = partitioned_routes.first.map(&:ast) + asts = anchored_routes.map(&:ast) Nodes::Or.new(asts) unless asts.empty? end end @@ -60,6 +65,7 @@ module ActionDispatch route.precedence = routes.length routes << route named_routes[name] = route if name && !named_routes[name] + partition_route(route) clear_cache! route end @@ -68,7 +74,6 @@ module ActionDispatch def clear_cache! @ast = nil - @partitioned_routes = nil @simulator = nil end end diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb index 040cb215b7..7cde76b30e 100644 --- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb @@ -17,10 +17,10 @@ module ActionDispatch end def call(env) - status = env["PATH_INFO"][1..-1] + status = env["PATH_INFO"][1..-1].to_i request = ActionDispatch::Request.new(env) content_type = request.formats.first - body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status.to_i, Rack::Utils::HTTP_STATUS_CODES[500]) } + body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) } render(status, content_type, body) end diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index 2e1bd45c3d..fdd1bc4e69 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -47,6 +47,9 @@ module ActionDispatch if gzip_path && gzip_encoding_accepted?(env) env['PATH_INFO'] = gzip_path status, headers, body = @file_server.call(env) + if status == 304 + return [status, headers, body] + end headers['Content-Encoding'] = 'gzip' headers['Content-Type'] = content_type(path) else diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index f2ce175cac..9934f5547a 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -247,14 +247,12 @@ module ActionDispatch args = [] model = record.to_model - name = if model.persisted? - args << model - model.model_name.singular_route_key - else - @key_strategy.call model.model_name - end - - named_route = "#{prefix}#{name}_#{suffix}" + named_route = if model.persisted? + args << model + get_method_for_string model.model_name.singular_route_key + else + get_method_for_class model + end [named_route, args] end @@ -309,11 +307,11 @@ module ActionDispatch def get_method_for_class(klass) name = @key_strategy.call klass.model_name - prefix + "#{name}_#{suffix}" + get_method_for_string name end def get_method_for_string(str) - prefix + "#{str}_#{suffix}" + "#{prefix}#{str}_#{suffix}" end [nil, 'new', 'edit'].each do |action| diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index ce04f0b08a..0f3734dd74 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -199,12 +199,9 @@ module ActionDispatch private def optimized_helper(args) - params = parameterize_args(args) - missing_keys = missing_keys(params) - - unless missing_keys.empty? - raise_generation_error(params, missing_keys) - end + params = parameterize_args(args) { |k| + raise_generation_error(args) + } @route.format params end @@ -215,16 +212,21 @@ module ActionDispatch def parameterize_args(args) params = {} - @required_parts.zip(args.map(&:to_param)) { |k,v| params[k] = v } + @arg_size.times { |i| + key = @required_parts[i] + value = args[i].to_param + yield key if value.nil? || value.empty? + params[key] = value + } params end - def missing_keys(args) - args.select{ |part, arg| arg.nil? || arg.empty? }.keys - end - - def raise_generation_error(args, missing_keys) - constraints = Hash[@route.requirements.merge(args).sort] + def raise_generation_error(args) + missing_keys = [] + params = parameterize_args(args) { |missing_key| + missing_keys << missing_key + } + constraints = Hash[@route.requirements.merge(params).sort] message = "No route matches #{constraints.inspect}" message << " missing required keys: #{missing_keys.sort.inspect}" @@ -307,7 +309,8 @@ module ActionDispatch attr_accessor :formatter, :set, :named_routes, :default_scope, :router attr_accessor :disable_clear_and_finalize, :resources_path_names - attr_accessor :default_url_options, :request_class + attr_accessor :default_url_options + attr_reader :env_key alias :routes :set @@ -315,22 +318,44 @@ module ActionDispatch { :new => 'new', :edit => 'edit' } end - def initialize(request_class = ActionDispatch::Request) + def self.new_with_config(config) + if config.respond_to? :relative_url_root + new Config.new config.relative_url_root + else + # engines apparently don't have this set + new + end + end + + Config = Struct.new :relative_url_root + + DEFAULT_CONFIG = Config.new(nil) + + def initialize(config = DEFAULT_CONFIG) self.named_routes = NamedRouteCollection.new self.resources_path_names = self.class.default_resources_path_names self.default_url_options = {} - self.request_class = request_class + @config = config @append = [] @prepend = [] @disable_clear_and_finalize = false @finalized = false + @env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze @set = Journey::Routes.new @router = Journey::Router.new @set @formatter = Journey::Formatter.new @set end + def relative_url_root + @config.relative_url_root + end + + def request_class + ActionDispatch::Request + end + def draw(&block) clear! unless @disable_clear_and_finalize eval_block(block) @@ -539,7 +564,7 @@ module ActionDispatch conditions.keep_if do |k, _| k == :action || k == :controller || k == :required_defaults || - @request_class.public_method_defined?(k) || path_values.include?(k) + request_class.public_method_defined?(k) || path_values.include?(k) end end private :build_conditions @@ -693,7 +718,7 @@ module ActionDispatch end def find_script_name(options) - options.delete(:script_name) || '' + options.delete(:script_name) || relative_url_root || '' end def path_for(options, route_name = nil) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index dca86858cc..eb554ec383 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -184,12 +184,6 @@ module ActionDispatch def _routes_context self end - - private - - def _generate_paths_by_default - true - end end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb index f325c35b57..21b3b89d22 100644 --- a/actionpack/lib/action_dispatch/testing/assertions.rb +++ b/actionpack/lib/action_dispatch/testing/assertions.rb @@ -12,7 +12,7 @@ module ActionDispatch include Rails::Dom::Testing::Assertions def html_document - @html_document ||= if @response.content_type =~ /xml$/ + @html_document ||= if @response.content_type === Mime::XML Nokogiri::XML::Document.parse(@response.body) else Nokogiri::HTML::Document.parse(@response.body) diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb index f7f898288b..9390e2937a 100644 --- a/actionpack/lib/action_dispatch/testing/integration.rb +++ b/actionpack/lib/action_dispatch/testing/integration.rb @@ -388,8 +388,16 @@ module ActionDispatch APP_SESSIONS = {} - def app - @app ||= nil + attr_reader :app + + def before_setup + @app = nil + @integration_session = nil + super + end + + def integration_session + @integration_session ||= create_session(app) end # Reset the current session. This is useful for testing multiple sessions @@ -417,8 +425,6 @@ module ActionDispatch %w(get post patch put head delete cookies assigns xml_http_request xhr get_via_redirect post_via_redirect).each do |method| define_method(method) do |*args| - reset! unless integration_session - # reset the html_document variable, except for cookies/assigns calls unless method == 'cookies' || method == 'assigns' @html_document = nil @@ -450,19 +456,16 @@ module ActionDispatch # Copy the instance variables from the current session instance into the # test instance. def copy_session_variables! #:nodoc: - return unless integration_session @controller = @integration_session.controller @response = @integration_session.response @request = @integration_session.request end def default_url_options - reset! unless integration_session integration_session.default_url_options end def default_url_options=(options) - reset! unless integration_session integration_session.default_url_options = options end @@ -472,7 +475,6 @@ module ActionDispatch # Delegate unhandled messages to the current session instance. def method_missing(sym, *args, &block) - reset! unless integration_session if integration_session.respond_to?(sym) integration_session.__send__(sym, *args, &block).tap do copy_session_variables! @@ -481,11 +483,6 @@ module ActionDispatch super end end - - private - def integration_session - @integration_session ||= nil - end end end @@ -508,8 +505,8 @@ module ActionDispatch # assert_equal 200, status # # # post the login and follow through to the home page - # post "/login", username: people(:jamis).username, - # password: people(:jamis).password + # post "/login", params: { username: people(:jamis).username, + # password: people(:jamis).password } # follow_redirect! # assert_equal 200, status # assert_equal "/home", path @@ -548,7 +545,7 @@ module ActionDispatch # end # # def speak(room, message) - # xml_http_request "/say/#{room.id}", message: message + # post "/say/#{room.id}", xhr: true, params: { message: message } # assert(...) # ... # end @@ -558,8 +555,8 @@ module ActionDispatch # open_session do |sess| # sess.extend(CustomAssertions) # who = people(who) - # sess.post "/login", username: who.username, - # password: who.password + # sess.post "/login", params: { username: who.username, + # password: who.password } # assert(...) # end # end @@ -578,7 +575,8 @@ module ActionDispatch # get "/login" # assert_response :success # - # post_via_redirect "/login", username: users(:david).username, password: users(:david).password + # post "/login", params: { username: users(:david).username, password: users(:david).password } + # follow_redirect! # assert_equal '/welcome', path # assert_equal 'Welcome david!', flash[:notice] # @@ -633,7 +631,7 @@ module ActionDispatch # sess.extend(CustomDsl) # u = users(user) # sess.https! - # sess.post "/login", username: u.username, password: u.password + # sess.post "/login", params: { username: u.username, password: u.password } # assert_equal '/welcome', sess.path # sess.https!(false) # end @@ -662,7 +660,6 @@ module ActionDispatch end def url_options - reset! unless integration_session integration_session.url_options end diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb index 918589f916..62ff1be5c9 100644 --- a/actionpack/test/abstract_unit.rb +++ b/actionpack/test/abstract_unit.rb @@ -95,7 +95,7 @@ end module ActiveSupport class TestCase include ActionDispatch::DrawOnce - if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0 + if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0 parallelize_me! end end @@ -479,12 +479,7 @@ class ForkingExecutor end end -if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0 +if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0 # Use N processes (N defaults to 4) Minitest.parallel_executor = ForkingExecutor.new(PROCESS_COUNT) end - -# FIXME: we have tests that depend on run order, we should fix that and -# remove this method call. -require 'active_support/test_case' -ActiveSupport::TestCase.test_order = :sorted diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 438c044da2..a87059bee4 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -363,6 +363,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest respond_to do |format| format.html { render :text => "OK", :status => 200 } format.js { render :text => "JS OK", :status => 200 } + format.xml { render :xml => "<root></root>", :status => 200 } end end @@ -419,6 +420,22 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest end end + def test_get_xml + with_test_route_set do + get "/get", params: {}, headers: {"HTTP_ACCEPT" => "application/xml"} + assert_equal 200, status + assert_equal "OK", status_message + assert_response 200 + assert_response :success + assert_response :ok + assert_equal({}, cookies.to_hash) + assert_equal "<root></root>", body + assert_equal "<root></root>", response.body + assert_instance_of Nokogiri::XML::Document, html_document + assert_equal 1, request_count + end + end + def test_post with_test_route_set do post '/post' @@ -1036,3 +1053,15 @@ class IntegrationRequestsWithoutSetup < ActionDispatch::IntegrationTest end end end + +# to ensure that session requirements in setup are persisted in the tests +class IntegrationRequestsWithSessionSetup < ActionDispatch::IntegrationTest + setup do + cookies['user_name'] = 'david' + end + + def test_cookies_set_in_setup_are_persisted_through_the_session + get "/foo" + assert_equal({"user_name"=>"david"}, cookies.to_hash) + end +end diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb index 7fd1276e98..0c65270ec1 100644 --- a/actionpack/test/controller/live_stream_test.rb +++ b/actionpack/test/controller/live_stream_test.rb @@ -276,6 +276,8 @@ module ActionController end def test_async_stream + rubinius_skip "https://github.com/rubinius/rubinius/issues/2934" + @controller.latch = ActiveSupport::Concurrency::Latch.new parts = ['hello', 'world'] diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index 19fef718e7..b06ce5db40 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -186,21 +186,21 @@ module RenderTemplate end end - test "rendering with layout => :true" do + test "rendering with layout => true" do get "/render_template/with_layout/with_layout" assert_body "Hello from basic.html.erb, I'm here!" assert_status 200 end - test "rendering with layout => :false" do + test "rendering with layout => false" do get "/render_template/with_layout/with_layout_false" assert_body "Hello from basic.html.erb" assert_status 200 end - test "rendering with layout => :nil" do + test "rendering with layout => nil" do get "/render_template/with_layout/with_layout_nil" assert_body "Hello from basic.html.erb" diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 103ca9c776..efd790de63 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -63,7 +63,7 @@ class RedirectController < ActionController::Base end def redirect_to_url_with_unescaped_query_string - redirect_to "http://dev.rubyonrails.org/query?status=new" + redirect_to "http://example.com/query?status=new" end def redirect_to_url_with_complex_scheme @@ -233,7 +233,7 @@ class RedirectTest < ActionController::TestCase def test_redirect_to_url_with_unescaped_query_string get :redirect_to_url_with_unescaped_query_string assert_response :redirect - assert_redirected_to "http://dev.rubyonrails.org/query?status=new" + assert_redirected_to "http://example.com/query?status=new" end def test_redirect_to_url_with_complex_scheme diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 488585c7a4..79e2104789 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -173,6 +173,11 @@ class TestController < ActionController::Base head :forbidden, :x_custom_header => "something" end + def head_and_return + head :ok and return + raise 'should not reach this line' + end + def head_with_no_content # Fill in the headers with dummy data to make # sure they get removed during the testing @@ -560,6 +565,12 @@ class HeadRenderTest < ActionController::TestCase assert_equal "something", @response.headers["X-Custom-Header"] assert_response :forbidden end + + def test_head_returns_truthy_value + assert_nothing_raised do + get :head_and_return + end + end end class HttpCacheForeverTest < ActionController::TestCase diff --git a/actionpack/test/controller/request/test_request_test.rb b/actionpack/test/controller/request/test_request_test.rb index e624f11773..77a2f68b1c 100644 --- a/actionpack/test/controller/request/test_request_test.rb +++ b/actionpack/test/controller/request/test_request_test.rb @@ -24,12 +24,4 @@ class ActionController::TestRequestTest < ActiveSupport::TestCase end end - def test_session_id_exists_by_default - assert_not_nil(@request.session_options[:id]) - end - - def test_session_id_different_on_each_call - assert_not_equal(@request.session_options[:id], ActionController::TestRequest.new.session_options[:id]) - end - end diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index fba5ebba15..786dc15444 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -75,7 +75,7 @@ module ShowExceptions get "/", headers: { 'HTTP_ACCEPT' => 'application/json' } assert_response :internal_server_error assert_equal 'application/json', response.content_type.to_s - assert_equal({ :status => '500', :error => 'Internal Server Error' }.to_json, response.body) + assert_equal({ :status => 500, :error => 'Internal Server Error' }.to_json, response.body) end def test_render_xml_exception @@ -83,7 +83,7 @@ module ShowExceptions get "/", headers: { 'HTTP_ACCEPT' => 'application/xml' } assert_response :internal_server_error assert_equal 'application/xml', response.content_type.to_s - assert_equal({ :status => '500', :error => 'Internal Server Error' }.to_xml, response.body) + assert_equal({ :status => 500, :error => 'Internal Server Error' }.to_xml, response.body) end def test_render_fallback_exception diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb index 0ffa2d2a03..31677f202d 100644 --- a/actionpack/test/controller/url_for_test.rb +++ b/actionpack/test/controller/url_for_test.rb @@ -30,8 +30,8 @@ module AbstractController assert_equal '/foo/zot', path end - def add_host! - W.default_url_options[:host] = 'www.basecamphq.com' + def add_host!(app = W) + app.default_url_options[:host] = 'www.basecamphq.com' end def add_port! @@ -255,6 +255,20 @@ module AbstractController ) end + def test_relative_url_root_is_respected_with_environment_variable + # `config.relative_url_root` is set by ENV['RAILS_RELATIVE_URL_ROOT'] + w = Class.new { + config = ActionDispatch::Routing::RouteSet::Config.new '/subdir' + r = ActionDispatch::Routing::RouteSet.new(config) + r.draw { get ':controller(/:action(/:id(.:format)))' } + include r.url_helpers + } + add_host!(w) + assert_equal('https://www.basecamphq.com/subdir/c/a/i', + w.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https') + ) + end + def test_named_routes with_routing do |set| set.draw do diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb index 7921f05688..a867aee7ec 100644 --- a/actionpack/test/dispatch/debug_exceptions_test.rb +++ b/actionpack/test/dispatch/debug_exceptions_test.rb @@ -305,7 +305,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest assert_response 500 assert_select '#Application-Trace' do - assert_select 'pre code', /\(eval\):1: syntax error, unexpected/ + assert_select 'pre code', /syntax error, unexpected/ end end @@ -332,7 +332,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest assert_response 500 assert_select '#Application-Trace' do - assert_select 'pre code', /\(eval\):1: syntax error, unexpected/ + assert_select 'pre code', /syntax error, unexpected/ end end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index ee8e915610..61cc4dcd7e 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -435,6 +435,9 @@ class RequestHost < BaseRequestTest request = stub_request 'HTTP_X_FORWARDED_HOST' => "www.firsthost.org, www.secondhost.org" assert_equal "www.secondhost.org", request.host + + request = stub_request 'HTTP_X_FORWARDED_HOST' => "", 'HTTP_HOST' => "rubyonrails.org" + assert_equal "rubyonrails.org", request.host end test "http host with default port overrides server port" do diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index f4c0b421d6..5fbd19acdf 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -172,7 +172,7 @@ class ResponseTest < ActiveSupport::TestCase original = ActionDispatch::Response.default_charset begin ActionDispatch::Response.default_charset = 'utf-16' - resp = ActionDispatch::Response.new(200, { "Content-Type" => "text/xml" }, default_headers: nil) + resp = ActionDispatch::Response.new(200, { "Content-Type" => "text/xml" }) assert_equal('utf-16', resp.charset) ensure ActionDispatch::Response.default_charset = original @@ -254,10 +254,6 @@ class ResponseTest < ActiveSupport::TestCase end class ResponseIntegrationTest < ActionDispatch::IntegrationTest - def app - @app - end - test "response cache control from railsish app" do @app = lambda { |env| ActionDispatch::Response.new.tap { |resp| diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index b4502c19d6..55fc160ac8 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -3583,7 +3583,11 @@ class TestAltApp < ActionDispatch::IntegrationTest end end - AltRoutes = ActionDispatch::Routing::RouteSet.new(AltRequest) + AltRoutes = Class.new(ActionDispatch::Routing::RouteSet) { + def request_class + AltRequest + end + }.new AltRoutes.draw do get "/" => TestAltApp::XHeader.new, :constraints => {:x_header => /HEADER/} get "/" => TestAltApp::AltApp.new diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb index 9f810cad01..22a46b0930 100644 --- a/actionpack/test/dispatch/session/cache_store_test.rb +++ b/actionpack/test/dispatch/session/cache_store_test.rb @@ -22,7 +22,7 @@ class CacheStoreTest < ActionDispatch::IntegrationTest end def get_session_id - render :text => "#{request.session_options[:id]}" + render :text => "#{request.session.id}" end def call_reset_session diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 2194efa503..e7f4235de8 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -29,7 +29,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end def get_session_id - render :text => "id: #{request.session_options[:id]}" + render :text => "id: #{request.session.id}" end def get_class_after_reset_session @@ -53,7 +53,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end def change_session_id - request.session_options[:id] = nil + request.session.options[:id] = nil get_session_id end diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index fbd82945cc..9a5d5131c0 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -23,7 +23,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest end def get_session_id - render :text => "#{request.session_options[:id]}" + render :text => "#{request.session.id}" end def call_reset_session diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index ebc9d71403..288a2084f6 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -143,6 +143,16 @@ module StaticTests assert_equal default_response.headers['Content-Type'], response.headers['Content-Type'] end + def test_serves_gzip_files_with_not_modified + file_name = "/gzip/application-a71b3024f80aea3181c09774ca17e712.js" + last_modified = File.mtime(File.join(@root, "#{file_name}.gz")) + response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'gzip', 'HTTP_IF_MODIFIED_SINCE' => last_modified.httpdate) + assert_equal 304, response.status + assert_equal nil, response.headers['Content-Type'] + assert_equal nil, response.headers['Content-Encoding'] + assert_equal nil, response.headers['Vary'] + end + # Windows doesn't allow \ / : * ? " < > | in filenames unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ def test_serves_static_file_with_colon diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb index a4efc82b8c..b54d961f66 100644 --- a/actionpack/test/journey/routes_test.rb +++ b/actionpack/test/journey/routes_test.rb @@ -3,6 +3,10 @@ require 'abstract_unit' module ActionDispatch module Journey class TestRoutes < ActiveSupport::TestCase + setup do + @routes = Routes.new + end + def test_clear routes = Routes.new exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?'] @@ -36,8 +40,24 @@ module ActionDispatch assert_not_equal sim, routes.simulator end + def test_partition_route + path = Path::Pattern.from_string '/hello' + + anchored_route = @routes.add_route nil, path, {}, {}, {} + assert_equal [anchored_route], @routes.anchored_routes + assert_equal [], @routes.custom_routes + + strexp = Router::Strexp.build( + "/hello/:who", { who: /\d/ }, ['/', '.', '?'] + ) + path = Path::Pattern.new strexp + + custom_route = @routes.add_route nil, path, {}, {}, {} + assert_equal [custom_route], @routes.custom_routes + assert_equal [anchored_route], @routes.anchored_routes + end + def test_first_name_wins - #def add_route app, path, conditions, defaults, name = nil routes = Routes.new one = Path::Pattern.from_string '/hello' |