aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md18
-rw-r--r--railties/lib/minitest/rails_plugin.rb49
-rw-r--r--railties/lib/rails/application/configuration.rb8
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb1
-rw-r--r--railties/lib/rails/commands/secrets/secrets_command.rb4
-rw-r--r--railties/lib/rails/commands/test/test_command.rb30
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt8
-rw-r--r--railties/lib/rails/plugin/test.rb8
-rw-r--r--railties/lib/rails/secrets.rb9
-rw-r--r--railties/lib/rails/test_help.rb1
-rw-r--r--railties/lib/rails/test_unit/line_filtering.rb70
-rw-r--r--railties/lib/rails/test_unit/minitest_plugin.rb145
-rw-r--r--railties/lib/rails/test_unit/runner.rb140
-rw-r--r--railties/lib/rails/test_unit/test_requirer.rb31
-rw-r--r--railties/lib/rails/test_unit/testing.rake16
-rw-r--r--railties/test/application/configuration_test.rb35
-rw-r--r--railties/test/application/dbconsole_test.rb66
-rw-r--r--railties/test/application/rake_test.rb2
-rw-r--r--railties/test/application/test_runner_test.rb4
-rw-r--r--railties/test/command/base_test.rb2
-rw-r--r--railties/test/commands/secrets_test.rb13
-rw-r--r--railties/test/generators/app_generator_test.rb42
-rw-r--r--railties/test/secrets_test.rb52
-rw-r--r--railties/test/test_unit/reporter_test.rb9
25 files changed, 489 insertions, 277 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index d1ccf5d97d..761e2f4ded 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,21 @@
+* Make Rails' test runner work better with minitest plugins.
+
+ By demoting the Rails test runner to just another minitest plugin —
+ and thereby not eager loading it — we can co-exist much better with
+ other minitest plugins such as pride and minitest-focus.
+
+ *Kasper Timm Hansen*
+
+* Load environment file in `dbconsole` command.
+
+ Fixes #29717
+
+ *Yuji Yaginuma*
+
+* Add `rails secrets:show` command.
+
+ *Yuji Yaginuma*
+
* Allow mounting the same engine several times in different locations.
Fixes #20204.
diff --git a/railties/lib/minitest/rails_plugin.rb b/railties/lib/minitest/rails_plugin.rb
new file mode 100644
index 0000000000..fec9ae64d8
--- /dev/null
+++ b/railties/lib/minitest/rails_plugin.rb
@@ -0,0 +1,49 @@
+require "active_support/core_ext/module/attribute_accessors"
+require "rails/test_unit/reporter"
+
+module Minitest
+ class SuppressedSummaryReporter < SummaryReporter
+ # Disable extra failure output after a run if output is inline.
+ def aggregated_results(*)
+ super unless options[:output_inline]
+ end
+ end
+
+ def self.plugin_rails_options(opts, options)
+ opts.on("-b", "--backtrace", "Show the complete backtrace") do
+ options[:full_backtrace] = true
+ end
+
+ opts.on("-d", "--defer-output", "Output test failures and errors after the test run") do
+ options[:output_inline] = false
+ end
+
+ opts.on("-f", "--fail-fast", "Abort test run on first failure or error") do
+ options[:fail_fast] = true
+ end
+
+ opts.on("-c", "--[no-]color", "Enable color in the output") do |value|
+ options[:color] = value
+ end
+
+ options[:color] = true
+ options[:output_inline] = true
+ end
+
+ # Owes great inspiration to test runner trailblazers like RSpec,
+ # minitest-reporters, maxitest and others.
+ def self.plugin_rails_init(options)
+ unless options[:full_backtrace] || ENV["BACKTRACE"]
+ # Plugin can run without Rails loaded, check before filtering.
+ Minitest.backtrace_filter = ::Rails.backtrace_cleaner if ::Rails.respond_to?(:backtrace_cleaner)
+ end
+
+ # Replace progress reporter for colors.
+ reporter.reporters.delete_if { |reporter| reporter.kind_of?(SummaryReporter) || reporter.kind_of?(ProgressReporter) }
+ reporter << SuppressedSummaryReporter.new(options[:io], options)
+ reporter << ::Rails::TestUnitReporter.new(options[:io], options)
+ end
+
+ # Backwardscompatibility with Rails 5.0 generated plugin test scripts
+ mattr_reader :run_via, default: {}
+end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 7e1359c42b..4797223380 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -86,6 +86,10 @@ module Rails
if respond_to?(:active_record)
active_record.cache_versioning = true
+ # Remove the temporary load hook from SQLite3Adapter when this is removed
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
+ ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
+ end
end
if respond_to?(:action_dispatch)
@@ -96,6 +100,10 @@ module Rails
active_support.use_authenticated_message_encryption = true
end
+ if respond_to?(:action_controller)
+ action_controller.default_protect_from_forgery = true
+ end
+
else
raise "Unknown version #{target_version.to_s.inspect}"
end
diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
index 5db588b66a..b3df5191c6 100644
--- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
+++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
@@ -148,6 +148,7 @@ module Rails
def perform
extract_environment_option_from_argument
+ require_application_and_environment!
Rails::DBConsole.start(options)
end
end
diff --git a/railties/lib/rails/commands/secrets/secrets_command.rb b/railties/lib/rails/commands/secrets/secrets_command.rb
index 9e530f5e23..45e02fa730 100644
--- a/railties/lib/rails/commands/secrets/secrets_command.rb
+++ b/railties/lib/rails/commands/secrets/secrets_command.rb
@@ -48,6 +48,10 @@ module Rails
end
end
+ def show
+ say Rails::Secrets.read
+ end
+
private
def generator
require_relative "../../generators"
diff --git a/railties/lib/rails/commands/test/test_command.rb b/railties/lib/rails/commands/test/test_command.rb
index ca0b6c00fe..5852f51a62 100644
--- a/railties/lib/rails/commands/test/test_command.rb
+++ b/railties/lib/rails/commands/test/test_command.rb
@@ -1,21 +1,41 @@
require_relative "../../command"
-require_relative "../../test_unit/minitest_plugin"
+require_relative "../../test_unit/runner"
module Rails
module Command
class TestCommand < Base # :nodoc:
no_commands do
def help
- perform # Hand over help printing to minitest.
+ require "optparse"
+ require "minitest/rails_plugin"
+
+ opts = OptionParser.new
+ opts.banner = "Usage: #{Rails::TestUnitReporter.executable} [options] [files or directories]"
+ opts.separator ""
+ opts.separator "You can run a single test by appending a line number to a filename:"
+ opts.separator ""
+ opts.separator " #{Rails::TestUnitReporter.executable} test/models/user_test.rb:27"
+ opts.separator ""
+ opts.separator "You can run multiple files and directories at the same time:"
+ opts.separator ""
+ opts.separator " #{Rails::TestUnitReporter.executable} test/controllers test/integration/login_test.rb"
+ opts.separator ""
+ opts.separator "By default test failures and errors are reported inline during a run."
+ opts.separator ""
+
+ opts.separator "Rails options:"
+ Rails::TestUnit::Runner.options(opts)
+ Minitest.plugin_rails_options(opts, {})
+
+ say opts
end
end
def perform(*)
$LOAD_PATH << Rails::Command.root.join("test").to_s
- Minitest.run_via = :rails
-
- require "active_support/testing/autorun"
+ Rails::TestUnit::Runner.parse_options(ARGV)
+ Rails::TestUnit::Runner.run(ARGV)
end
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt
index 413354186d..185c0017f1 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt
@@ -1,5 +1,2 @@
class ApplicationController < ActionController::<%= options[:api] ? "API" : "Base" %>
-<%- unless options[:api] -%>
- protect_from_forgery with: :exception
-<%- end -%>
end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt
index 3809936f9f..f2df0d1e9f 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt
@@ -17,3 +17,11 @@
# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages
# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true.
# Rails.application.config.active_support.use_authenticated_message_encryption = true
+
+# Add default protection from forgery to ActionController::Base instead of in
+# ApplicationController.
+# Rails.application.config.action_controller.default_protect_from_forgery = true
+
+# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and
+# 'f' after migrating old data.
+# ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true
diff --git a/railties/lib/rails/plugin/test.rb b/railties/lib/rails/plugin/test.rb
index bd43cba688..40070c0eb3 100644
--- a/railties/lib/rails/plugin/test.rb
+++ b/railties/lib/rails/plugin/test.rb
@@ -1,7 +1,7 @@
-require_relative "../test_unit/minitest_plugin"
+require_relative "../test_unit/runner"
+require_relative "../test_unit/reporter"
Rails::TestUnitReporter.executable = "bin/test"
-Minitest.run_via = :rails
-
-require "active_support/testing/autorun"
+Rails::TestUnit::Runner.parse_options(ARGV)
+Rails::TestUnit::Runner.run(ARGV)
diff --git a/railties/lib/rails/secrets.rb b/railties/lib/rails/secrets.rb
index c7a8676d7b..0883857c55 100644
--- a/railties/lib/rails/secrets.rb
+++ b/railties/lib/rails/secrets.rb
@@ -100,12 +100,15 @@ module Rails
end
def writing(contents)
- tmp_path = File.join(Dir.tmpdir, File.basename(path))
- File.write(tmp_path, contents)
+ tmp_file = "#{File.basename(path)}.#{Process.pid}"
+ tmp_path = File.join(Dir.tmpdir, tmp_file)
+ IO.binwrite(tmp_path, contents)
yield tmp_path
- write(File.read(tmp_path))
+ updated_contents = IO.binread(tmp_path)
+
+ write(updated_contents) if updated_contents != contents
ensure
FileUtils.rm(tmp_path) if File.exist?(tmp_path)
end
diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb
index 05048eb2e1..33b6740cf1 100644
--- a/railties/lib/rails/test_help.rb
+++ b/railties/lib/rails/test_help.rb
@@ -2,7 +2,6 @@
# so fixtures aren't loaded into that environment
abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production?
-require_relative "test_unit/minitest_plugin"
require "active_support/test_case"
require "action_controller"
require "action_controller/test_case"
diff --git a/railties/lib/rails/test_unit/line_filtering.rb b/railties/lib/rails/test_unit/line_filtering.rb
index 32ba744701..289afae331 100644
--- a/railties/lib/rails/test_unit/line_filtering.rb
+++ b/railties/lib/rails/test_unit/line_filtering.rb
@@ -1,78 +1,12 @@
require "method_source"
+require "rails/test_unit/runner"
module Rails
module LineFiltering # :nodoc:
def run(reporter, options = {})
- if options[:patterns] && options[:patterns].any? { |p| p =~ /:\d+/ }
- options[:filter] = \
- CompositeFilter.new(self, options[:filter], options[:patterns])
- end
+ options[:filter] = Rails::TestUnit::Runner.compose_filter(self, options[:filter])
super
end
end
-
- class CompositeFilter # :nodoc:
- attr_reader :named_filter
-
- def initialize(runnable, filter, patterns)
- @runnable = runnable
- @named_filter = derive_named_filter(filter)
- @filters = [ @named_filter, *derive_line_filters(patterns) ].compact
- end
-
- # Minitest uses === to find matching filters.
- def ===(method)
- @filters.any? { |filter| filter === method }
- end
-
- private
- def derive_named_filter(filter)
- if filter.respond_to?(:named_filter)
- filter.named_filter
- elsif filter =~ %r%/(.*)/% # Regexp filtering copied from Minitest.
- Regexp.new $1
- elsif filter.is_a?(String)
- filter
- end
- end
-
- def derive_line_filters(patterns)
- patterns.flat_map do |file_and_line|
- file, *lines = file_and_line.split(":")
-
- if lines.empty?
- Filter.new(@runnable, file, nil) if file
- else
- lines.map { |line| Filter.new(@runnable, file, line) }
- end
- end
- end
- end
-
- class Filter # :nodoc:
- def initialize(runnable, file, line)
- @runnable, @file = runnable, File.expand_path(file)
- @line = line.to_i if line
- end
-
- def ===(method)
- return unless @runnable.method_defined?(method)
-
- if @line
- test_file, test_range = definition_for(@runnable.instance_method(method))
- test_file == @file && test_range.include?(@line)
- else
- @runnable.instance_method(method).source_location.first == @file
- end
- end
-
- private
- def definition_for(method)
- file, start_line = method.source_location
- end_line = method.source.count("\n") + start_line - 1
-
- return file, start_line..end_line
- end
- end
end
diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb
deleted file mode 100644
index 3571274bcd..0000000000
--- a/railties/lib/rails/test_unit/minitest_plugin.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-require "active_support/core_ext/module/attribute_accessors"
-require_relative "reporter"
-require_relative "test_requirer"
-require "shellwords"
-
-module Minitest
- class SuppressedSummaryReporter < SummaryReporter
- # Disable extra failure output after a run if output is inline.
- def aggregated_results(*)
- super unless options[:output_inline]
- end
- end
-
- def self.plugin_rails_options(opts, options)
- executable = ::Rails::TestUnitReporter.executable
- opts.separator ""
- opts.separator "Usage: #{executable} [options] [files or directories]"
- opts.separator "You can run a single test by appending a line number to a filename:"
- opts.separator ""
- opts.separator " #{executable} test/models/user_test.rb:27"
- opts.separator ""
- opts.separator "You can run multiple files and directories at the same time:"
- opts.separator ""
- opts.separator " #{executable} test/controllers test/integration/login_test.rb"
- opts.separator ""
- opts.separator "By default test failures and errors are reported inline during a run."
- opts.separator ""
-
- opts.separator "Rails options:"
- opts.on("-e", "--environment ENV",
- "Run tests in the ENV environment") do |env|
- options[:environment] = env.strip
- end
-
- opts.on("-b", "--backtrace",
- "Show the complete backtrace") do
- options[:full_backtrace] = true
- end
-
- opts.on("-d", "--defer-output",
- "Output test failures and errors after the test run") do
- options[:output_inline] = false
- end
-
- opts.on("-f", "--fail-fast",
- "Abort test run on first failure or error") do
- options[:fail_fast] = true
- end
-
- opts.on("-c", "--[no-]color",
- "Enable color in the output") do |value|
- options[:color] = value
- end
-
- opts.on("-w", "--warnings",
- "Enable ruby warnings") do
- $VERBOSE = true
- end
-
- options[:color] = true
- options[:output_inline] = true
- options[:patterns] = opts.order! unless run_via.rake?
- end
-
- def self.rake_run(patterns, exclude_patterns = []) # :nodoc:
- self.run_via = :rake unless run_via.set?
- ::Rails::TestRequirer.require_files(patterns, exclude_patterns)
- autorun
- end
-
- module RunRespectingRakeTestopts
- def run(args = [])
- if run_via.rake?
- args = Shellwords.split(ENV["TESTOPTS"] || "")
- end
-
- super
- end
- end
-
- singleton_class.prepend RunRespectingRakeTestopts
-
- # Owes great inspiration to test runner trailblazers like RSpec,
- # minitest-reporters, maxitest and others.
- def self.plugin_rails_init(options)
- ENV["RAILS_ENV"] = options[:environment] || "test"
-
- # If run via `ruby` we've been passed the files to run directly, or if run
- # via `rake` then they have already been eagerly required.
- unless run_via.ruby? || run_via.rake?
- # If there are no given patterns, we can assume that the user
- # simply runs the `bin/rails test` command without extra arguments.
- if options[:patterns].empty?
- ::Rails::TestRequirer.require_files(options[:patterns], ["test/system/**/*"])
- else
- ::Rails::TestRequirer.require_files(options[:patterns])
- end
- end
-
- unless options[:full_backtrace] || ENV["BACKTRACE"]
- # Plugin can run without Rails loaded, check before filtering.
- Minitest.backtrace_filter = ::Rails.backtrace_cleaner if ::Rails.respond_to?(:backtrace_cleaner)
- end
-
- # Replace progress reporter for colors.
- reporter.reporters.delete_if { |reporter| reporter.kind_of?(SummaryReporter) || reporter.kind_of?(ProgressReporter) }
- reporter << SuppressedSummaryReporter.new(options[:io], options)
- reporter << ::Rails::TestUnitReporter.new(options[:io], options)
- end
-
- def self.run_via=(runner)
- if run_via.set?
- raise ArgumentError, "run_via already assigned"
- else
- run_via.runner = runner
- end
- end
-
- class RunVia
- attr_accessor :runner
- alias set? runner
-
- # Backwardscompatibility with Rails 5.0 generated plugin test scripts.
- def []=(runner, *)
- @runner = runner
- end
-
- def ruby?
- runner == :ruby
- end
-
- def rake?
- runner == :rake
- end
- end
-
- mattr_reader :run_via, default: RunVia.new
-end
-
-# Put Rails as the first plugin minitest initializes so other plugins
-# can override or replace our default reporter setup.
-# Since minitest only loads plugins if its extensions are empty we have
-# to call `load_plugins` first.
-Minitest.load_plugins
-Minitest.extensions.unshift "rails"
diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb
new file mode 100644
index 0000000000..8018ef9d02
--- /dev/null
+++ b/railties/lib/rails/test_unit/runner.rb
@@ -0,0 +1,140 @@
+require "shellwords"
+require "method_source"
+require "rake/file_list"
+require "active_support/core_ext/module/attribute_accessors"
+
+module Rails
+ module TestUnit
+ class Runner
+ mattr_reader :filters, default: []
+
+ class << self
+ def options(opts)
+ opts.on("--warnings", "-w", "Run with Ruby warnings enabled") {}
+ opts.on("--environment", "-e", "Run tests in the ENV environment") {}
+ end
+
+ def parse_options(argv)
+ # Perform manual parsing and cleanup since option parser raises on unknown options.
+ env_index = argv.index("--environment") || argv.index("-e")
+ if env_index
+ argv.delete_at(env_index)
+ environment = argv.delete_at(env_index).strip
+ end
+ ENV["RAILS_ENV"] = environment || "test"
+
+ w_index = argv.index("--warnings") || argv.index("-w")
+ $VERBOSE = argv.delete_at(w_index) if w_index
+ end
+
+ def rake_run(argv = [])
+ ARGV.replace Shellwords.split(ENV["TESTOPTS"] || "")
+
+ run(argv)
+ end
+
+ def run(argv = [])
+ load_tests(argv)
+
+ require "active_support/testing/autorun"
+ end
+
+ def load_tests(argv)
+ patterns = extract_filters(argv)
+
+ tests = Rake::FileList[patterns.any? ? patterns : "test/**/*_test.rb"]
+ tests.exclude("test/system/**/*") if patterns.empty?
+
+ tests.to_a.each { |path| require File.expand_path(path) }
+ end
+
+ def compose_filter(runnable, filter)
+ if filters.any? { |_, lines| lines.any? }
+ CompositeFilter.new(runnable, filter, filters)
+ else
+ filter
+ end
+ end
+
+ private
+ def extract_filters(argv)
+ argv.select { |arg| arg =~ /^\w+\// }.map do |path|
+ case
+ when path =~ /(:\d+)+$/
+ file, *lines = path.split(":")
+ filters << [ file, lines ]
+ file
+ when Dir.exist?(path)
+ "#{path}/**/*_test.rb"
+ else
+ filters << [ path, [] ]
+ path
+ end
+ end
+ end
+ end
+ end
+
+ class CompositeFilter # :nodoc:
+ attr_reader :named_filter
+
+ def initialize(runnable, filter, patterns)
+ @runnable = runnable
+ @named_filter = derive_named_filter(filter)
+ @filters = [ @named_filter, *derive_line_filters(patterns) ].compact
+ end
+
+ # Minitest uses === to find matching filters.
+ def ===(method)
+ @filters.any? { |filter| filter === method }
+ end
+
+ private
+ def derive_named_filter(filter)
+ if filter.respond_to?(:named_filter)
+ filter.named_filter
+ elsif filter =~ %r%/(.*)/% # Regexp filtering copied from Minitest.
+ Regexp.new $1
+ elsif filter.is_a?(String)
+ filter
+ end
+ end
+
+ def derive_line_filters(patterns)
+ patterns.flat_map do |file, lines|
+ if lines.empty?
+ Filter.new(@runnable, file, nil) if file
+ else
+ lines.map { |line| Filter.new(@runnable, file, line) }
+ end
+ end
+ end
+ end
+
+ class Filter # :nodoc:
+ def initialize(runnable, file, line)
+ @runnable, @file = runnable, File.expand_path(file)
+ @line = line.to_i if line
+ end
+
+ def ===(method)
+ return unless @runnable.method_defined?(method)
+
+ if @line
+ test_file, test_range = definition_for(@runnable.instance_method(method))
+ test_file == @file && test_range.include?(@line)
+ else
+ @runnable.instance_method(method).source_location.first == @file
+ end
+ end
+
+ private
+ def definition_for(method)
+ file, start_line = method.source_location
+ end_line = method.source.count("\n") + start_line - 1
+
+ return file, start_line..end_line
+ end
+ end
+ end
+end
diff --git a/railties/lib/rails/test_unit/test_requirer.rb b/railties/lib/rails/test_unit/test_requirer.rb
deleted file mode 100644
index 92e5fcf0bc..0000000000
--- a/railties/lib/rails/test_unit/test_requirer.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require "active_support/core_ext/object/blank"
-require "rake/file_list"
-
-module Rails
- class TestRequirer # :nodoc:
- class << self
- def require_files(patterns, exclude_patterns = [])
- patterns = expand_patterns(patterns)
-
- file_list = Rake::FileList[patterns.compact.presence || "test/**/*_test.rb"]
- file_list.exclude(exclude_patterns)
-
- file_list.to_a.each do |file|
- require File.expand_path(file)
- end
- end
-
- private
- def expand_patterns(patterns)
- patterns.map do |arg|
- arg = arg.gsub(/(:\d+)+?$/, "")
- if Dir.exist?(arg)
- "#{arg}/**/*_test.rb"
- else
- arg
- end
- end
- end
- end
- end
-end
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index 486446b463..97dd5cef10 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -1,6 +1,6 @@
gem "minitest"
require "minitest"
-require_relative "minitest_plugin"
+require_relative "runner"
task default: :test
@@ -9,9 +9,9 @@ task :test do
$: << "test"
if ENV.key?("TEST")
- Minitest.rake_run([ENV["TEST"]])
+ Rails::TestUnit::Runner.rake_run([ENV["TEST"]])
else
- Minitest.rake_run(["test"], ["test/system/**/*"])
+ Rails::TestUnit::Runner.rake_run
end
end
@@ -29,28 +29,28 @@ namespace :test do
["models", "helpers", "controllers", "mailers", "integration", "jobs"].each do |name|
task name => "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/#{name}"])
+ Rails::TestUnit::Runner.rake_run(["test/#{name}"])
end
end
task generators: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/lib/generators"])
+ Rails::TestUnit::Runner.rake_run(["test/lib/generators"])
end
task units: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/models", "test/helpers", "test/unit"])
+ Rails::TestUnit::Runner.rake_run(["test/models", "test/helpers", "test/unit"])
end
task functionals: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/controllers", "test/mailers", "test/functional"])
+ Rails::TestUnit::Runner.rake_run(["test/controllers", "test/mailers", "test/functional"])
end
desc "Run system tests only"
task system: "test:prepare" do
$: << "test"
- Minitest.rake_run(["test/system"])
+ Rails::TestUnit::Runner.rake_run(["test/system"])
end
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 983ea5c3e6..b8a19379e0 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -1209,6 +1209,13 @@ module ApplicationTests
assert_equal false, ActionController::Parameters.action_on_unpermitted_parameters
end
+ test "config.action_controller.default_protect_from_forgery is true by default" do
+ app "development"
+
+ assert_equal true, ActionController::Base.default_protect_from_forgery
+ assert_includes ActionController::Base.__callbacks[:process_action].map(&:filter), :verify_authenticity_token
+ end
+
test "config.action_controller.permit_all_parameters can be configured in an initializer" do
app_file "config/initializers/permit_all_parameters.rb", <<-RUBY
Rails.application.config.action_controller.permit_all_parameters = true
@@ -1578,6 +1585,34 @@ module ApplicationTests
assert_equal({}, Rails.application.config.my_custom_config)
end
+ test "default SQLite3Adapter.represent_boolean_as_integer for 5.1 is false" do
+ remove_from_config '.*config\.load_defaults.*\n'
+ add_to_top_of_config <<-RUBY
+ config.load_defaults 5.1
+ RUBY
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app "development"
+ Post.object_id # force lazy load hooks to run
+
+ assert_not ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
+ end
+
+ test "default SQLite3Adapter.represent_boolean_as_integer for new installs is true" do
+ app_file "app/models/post.rb", <<-RUBY
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ app "development"
+ Post.object_id # force lazy load hooks to run
+
+ assert ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
+ end
+
test "config_for containing ERB tags should evaluate" do
app_file "config/custom.yml", <<-RUBY
development:
diff --git a/railties/test/application/dbconsole_test.rb b/railties/test/application/dbconsole_test.rb
new file mode 100644
index 0000000000..7e5e9ea8aa
--- /dev/null
+++ b/railties/test/application/dbconsole_test.rb
@@ -0,0 +1,66 @@
+require "isolation/abstract_unit"
+begin
+ require "pty"
+rescue LoadError
+end
+
+module ApplicationTests
+ class DBConsoleTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ def test_use_value_defined_in_environment_file_in_database_yml
+ skip "PTY unavailable" unless available_pty?
+ Dir.chdir(app_path) do
+ app_file "config/database.yml", <<-YAML
+ development:
+ database: <%= Rails.application.config.database %>
+ adapter: sqlite3
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+ timeout: 5000
+ YAML
+
+ app_file "config/environments/development.rb", <<-RUBY
+ Rails.application.configure do
+ config.database = "db/development.sqlite3"
+ end
+ RUBY
+ end
+
+ master, slave = PTY.open
+ spawn_dbconsole(slave)
+ assert_output("sqlite>", master)
+ ensure
+ master.puts ".exit"
+ end
+
+ private
+ def spawn_dbconsole(fd)
+ Process.spawn("#{app_path}/bin/rails dbconsole", in: fd, out: fd, err: fd)
+ end
+
+ def assert_output(expected, io, timeout = 5)
+ timeout = Time.now + timeout
+
+ output = ""
+ until output.include?(expected) || Time.now > timeout
+ if IO.select([io], [], [], 0.1)
+ output << io.read(1)
+ end
+ end
+
+ assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
+ end
+
+ def available_pty?
+ defined?(PTY) && PTY.respond_to?(:open)
+ end
+ end
+end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index 5ae6ea925f..134106812d 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -117,7 +117,7 @@ module ApplicationTests
end
def test_code_statistics_sanity
- assert_match "Code LOC: 26 Test LOC: 0 Code to Test Ratio: 1:0.0",
+ assert_match "Code LOC: 25 Test LOC: 0 Code to Test Ratio: 1:0.0",
Dir.chdir(app_path) { `bin/rails stats` }
end
diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb
index 8e0712fca2..c0027ab9a2 100644
--- a/railties/test/application/test_runner_test.rb
+++ b/railties/test/application/test_runner_test.rb
@@ -16,13 +16,13 @@ module ApplicationTests
end
def test_run_via_backwardscompatibility
- require "rails/test_unit/minitest_plugin"
+ require "minitest/rails_plugin"
assert_nothing_raised do
Minitest.run_via[:ruby] = true
end
- assert_predicate Minitest.run_via, :ruby?
+ assert Minitest.run_via[:ruby]
end
def test_run_single_file
diff --git a/railties/test/command/base_test.rb b/railties/test/command/base_test.rb
index ebfc4d0ba9..bac3285f48 100644
--- a/railties/test/command/base_test.rb
+++ b/railties/test/command/base_test.rb
@@ -6,6 +6,6 @@ require "rails/commands/secrets/secrets_command"
class Rails::Command::BaseTest < ActiveSupport::TestCase
test "printing commands" do
assert_equal %w(generate), Rails::Command::GenerateCommand.printing_commands
- assert_equal %w(secrets:setup secrets:edit), Rails::Command::SecretsCommand.printing_commands
+ assert_equal %w(secrets:setup secrets:edit secrets:show), Rails::Command::SecretsCommand.printing_commands
end
end
diff --git a/railties/test/commands/secrets_test.rb b/railties/test/commands/secrets_test.rb
index be610f3b47..3771919849 100644
--- a/railties/test/commands/secrets_test.rb
+++ b/railties/test/commands/secrets_test.rb
@@ -27,8 +27,21 @@ class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
end
end
+ test "show secrets" do
+ run_setup_command
+ assert_match(/external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289/, run_show_command)
+ end
+
private
def run_edit_command(editor: "cat")
Dir.chdir(app_path) { `EDITOR="#{editor}" bin/rails secrets:edit` }
end
+
+ def run_show_command
+ Dir.chdir(app_path) { `bin/rails secrets:show` }
+ end
+
+ def run_setup_command
+ Dir.chdir(app_path) { `bin/rails secrets:setup` }
+ end
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 9364f11a98..059c2692be 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -8,32 +8,70 @@ DEFAULT_APP_FILES = %w(
Gemfile
Rakefile
config.ru
+ app/assets/config/manifest.js
+ app/assets/images
app/assets/javascripts
+ app/assets/javascripts/application.js
+ app/assets/javascripts/cable.js
+ app/assets/javascripts/channels
app/assets/stylesheets
- app/assets/images
+ app/assets/stylesheets/application.css
+ app/channels/application_cable/channel.rb
+ app/channels/application_cable/connection.rb
app/controllers
+ app/controllers/application_controller.rb
app/controllers/concerns
app/helpers
+ app/helpers/application_helper.rb
app/mailers
+ app/mailers/application_mailer.rb
app/models
+ app/models/application_record.rb
app/models/concerns
app/jobs
+ app/jobs/application_job.rb
app/views/layouts
+ app/views/layouts/application.html.erb
+ app/views/layouts/mailer.html.erb
+ app/views/layouts/mailer.text.erb
bin/bundle
bin/rails
bin/rake
bin/setup
+ bin/update
+ bin/yarn
+ config/application.rb
+ config/boot.rb
+ config/cable.yml
+ config/environment.rb
config/environments
+ config/environments/development.rb
+ config/environments/production.rb
+ config/environments/test.rb
config/initializers
+ config/initializers/application_controller_renderer.rb
+ config/initializers/assets.rb
+ config/initializers/backtrace_silencers.rb
+ config/initializers/cookies_serializer.rb
+ config/initializers/filter_parameter_logging.rb
+ config/initializers/inflections.rb
+ config/initializers/mime_types.rb
+ config/initializers/wrap_parameters.rb
config/locales
- config/cable.yml
+ config/locales/en.yml
config/puma.rb
+ config/routes.rb
+ config/secrets.yml
config/spring.rb
db
+ db/seeds.rb
lib
lib/tasks
lib/assets
log
+ package.json
+ public
+ test/application_system_test_case.rb
test/test_helper.rb
test/fixtures
test/fixtures/files
diff --git a/railties/test/secrets_test.rb b/railties/test/secrets_test.rb
index 36c8ef1fd9..744d831406 100644
--- a/railties/test/secrets_test.rb
+++ b/railties/test/secrets_test.rb
@@ -111,6 +111,58 @@ class Rails::SecretsTest < ActiveSupport::TestCase
end
end
+ test "do not update secrets.yml.enc when secretes do not change" do
+ run_secrets_generator do
+ Dir.chdir(app_path) do
+ Rails::Secrets.read_for_editing do |tmp_path|
+ File.write(tmp_path, "Empty streets, empty nights. The Downtown Lights.")
+ end
+
+ FileUtils.cp("config/secrets.yml.enc", "config/secrets.yml.enc.bk")
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ File.write(tmp_path, "Empty streets, empty nights. The Downtown Lights.")
+ end
+
+ assert_equal File.read("config/secrets.yml.enc.bk"), File.read("config/secrets.yml.enc")
+ end
+ end
+ end
+
+ test "can read secrets written in binary" do
+ run_secrets_generator do
+ secrets = <<-end_of_secrets
+ production:
+ api_key: 00112233445566778899aabbccddeeff…
+ end_of_secrets
+
+ Rails::Secrets.write(secrets.force_encoding(Encoding::ASCII_8BIT))
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ assert_match(/production:\n\s*api_key: 00112233445566778899aabbccddeeff…\n/, File.read(tmp_path))
+ end
+
+ assert_equal "00112233445566778899aabbccddeeff…\n", `bin/rails runner -e production "puts Rails.application.secrets.api_key"`
+ end
+ end
+
+ test "can read secrets written in non-binary" do
+ run_secrets_generator do
+ secrets = <<-end_of_secrets
+ production:
+ api_key: 00112233445566778899aabbccddeeff…
+ end_of_secrets
+
+ Rails::Secrets.write(secrets)
+
+ Rails::Secrets.read_for_editing do |tmp_path|
+ assert_equal(secrets.force_encoding(Encoding::ASCII_8BIT), IO.binread(tmp_path))
+ end
+
+ assert_equal "00112233445566778899aabbccddeeff…\n", `bin/rails runner -e production "puts Rails.application.secrets.api_key"`
+ end
+ end
+
private
def run_secrets_generator
Dir.chdir(app_path) do
diff --git a/railties/test/test_unit/reporter_test.rb b/railties/test/test_unit/reporter_test.rb
index 98201394cd..42f973357b 100644
--- a/railties/test/test_unit/reporter_test.rb
+++ b/railties/test/test_unit/reporter_test.rb
@@ -70,7 +70,7 @@ class TestUnitReporterTest < ActiveSupport::TestCase
@reporter.record(errored_test)
@reporter.report
- expect = %r{\AE\n\nError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n No backtrace\n\nbin/rails test .*test/test_unit/reporter_test\.rb:\d+\n\n\z}
+ expect = %r{\AE\n\nError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n \n\nbin/rails test .*test/test_unit/reporter_test\.rb:\d+\n\n\z}
assert_match expect, @output.string
end
@@ -150,7 +150,7 @@ class TestUnitReporterTest < ActiveSupport::TestCase
colored = Rails::TestUnitReporter.new @output, color: true, output_inline: true
colored.record(errored_test)
- expected = %r{\e\[31mE\e\[0m\n\n\e\[31mError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n No backtrace\n\e\[0m}
+ expected = %r{\e\[31mE\e\[0m\n\n\e\[31mError:\nTestUnitReporterTest::ExampleTest#woot:\nArgumentError: wups\n \n\e\[0m}
assert_match expected, @output.string
end
end
@@ -171,8 +171,11 @@ class TestUnitReporterTest < ActiveSupport::TestCase
end
def errored_test
+ error = ArgumentError.new("wups")
+ error.set_backtrace([ "some_test.rb:4" ])
+
et = ExampleTest.new(:woot)
- et.failures << Minitest::UnexpectedError.new(ArgumentError.new("wups"))
+ et.failures << Minitest::UnexpectedError.new(error)
et
end