diff options
Diffstat (limited to 'railties/test')
22 files changed, 557 insertions, 79 deletions
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 960f708bdf..b8e167b488 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -596,6 +596,30 @@ module ApplicationTests assert_equal "some_value", verifier.verify(message) end + test "application will generate secret_key_base in tmp file if blank in development" do + app_file "config/initializers/secret_token.rb", <<-RUBY + Rails.application.credentials.secret_key_base = nil + RUBY + + # For test that works even if tmp dir does not exist. + Dir.chdir(app_path) { FileUtils.remove_dir("tmp") } + + app "development" + + assert_not_nil app.secrets.secret_key_base + assert File.exist?(app_path("tmp/development_secret.txt")) + end + + test "application will not generate secret_key_base in tmp file if blank in production" do + app_file "config/initializers/secret_token.rb", <<-RUBY + Rails.application.credentials.secret_key_base = nil + RUBY + + assert_raises ArgumentError do + app "production" + end + end + test "raises when secret_key_base is blank" do app_file "config/initializers/secret_token.rb", <<-RUBY Rails.application.credentials.secret_key_base = nil @@ -619,7 +643,6 @@ module ApplicationTests test "application verifier can build different verifiers" do make_basic_app do |application| - application.credentials.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33" application.config.session_store :disabled end @@ -1157,23 +1180,34 @@ module ApplicationTests end end - test "autoloader & autoloader=" do + test "autoloaders" do app "development" config = Rails.application.config - assert_instance_of Zeitwerk::Loader, Rails.autoloader - assert_instance_of Zeitwerk::Loader, Rails.once_autoloader - assert_equal [Rails.autoloader, Rails.once_autoloader], Rails.autoloaders + assert Rails.autoloaders.zeitwerk_enabled? + assert_instance_of Zeitwerk::Loader, Rails.autoloaders.main + assert_equal "rails.main", Rails.autoloaders.main.tag + assert_instance_of Zeitwerk::Loader, Rails.autoloaders.once + assert_equal "rails.once", Rails.autoloaders.once.tag + assert_equal [Rails.autoloaders.main, Rails.autoloaders.once], Rails.autoloaders.to_a + assert_equal ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector, Rails.autoloaders.main.inflector + assert_equal ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector, Rails.autoloaders.once.inflector config.autoloader = :classic - assert_nil Rails.autoloader - assert_nil Rails.once_autoloader - assert_empty Rails.autoloaders + assert_not Rails.autoloaders.zeitwerk_enabled? + assert_nil Rails.autoloaders.main + assert_nil Rails.autoloaders.once + assert_equal 0, Rails.autoloaders.count config.autoloader = :zeitwerk - assert_instance_of Zeitwerk::Loader, Rails.autoloader - assert_instance_of Zeitwerk::Loader, Rails.once_autoloader - assert_equal [Rails.autoloader, Rails.once_autoloader], Rails.autoloaders + assert Rails.autoloaders.zeitwerk_enabled? + assert_instance_of Zeitwerk::Loader, Rails.autoloaders.main + assert_equal "rails.main", Rails.autoloaders.main.tag + assert_instance_of Zeitwerk::Loader, Rails.autoloaders.once + assert_equal "rails.once", Rails.autoloaders.once.tag + assert_equal [Rails.autoloaders.main, Rails.autoloaders.once], Rails.autoloaders.to_a + assert_equal ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector, Rails.autoloaders.main.inflector + assert_equal ActiveSupport::Dependencies::ZeitwerkIntegration::Inflector, Rails.autoloaders.once.inflector assert_raises(ArgumentError) { config.autoloader = :unknown } end @@ -1787,6 +1821,28 @@ module ApplicationTests end end + test "config_for loads nested custom configuration inside array from yaml with deprecated non-symbol access" do + app_file "config/custom.yml", <<-RUBY + development: + foo: + bar: + - baz: 1 + RUBY + + add_to_config <<-RUBY + config.my_custom_config = config_for('custom') + RUBY + + app "development" + + config = Rails.application.config.my_custom_config + assert_instance_of Rails::Application::NonSymbolAccessDeprecatedHash, config[:foo][:bar].first + + assert_deprecated do + assert_equal 1, config[:foo][:bar].first["baz"] + end + end + test "config_for makes all hash methods available" do app_file "config/custom.yml", <<-RUBY development: @@ -2420,6 +2476,22 @@ module ApplicationTests assert_includes Rails.application.config.hosts, ".localhost" end + test "disable_sandbox is false by default" do + app "development" + + assert_equal false, Rails.configuration.disable_sandbox + end + + test "disable_sandbox can be overridden" do + add_to_config <<-RUBY + config.disable_sandbox = true + RUBY + + app "development" + + assert Rails.configuration.disable_sandbox + end + private def force_lazy_load_hooks yield # Tasty clarifying sugar, homie! We only need to reference a constant to load it. diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index b6270525f0..db16f4cc56 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -123,13 +123,17 @@ class FullStackConsoleTest < ActiveSupport::TestCase assert_output "> ", @primary end - def spawn_console(options) - Process.spawn( + def spawn_console(options, wait_for_prompt: true) + pid = Process.spawn( "#{app_path}/bin/rails console #{options}", in: @replica, out: @replica, err: @replica ) - assert_output "> ", @primary, 30 + if wait_for_prompt + assert_output "> ", @primary, 30 + end + + pid end def test_sandbox @@ -148,6 +152,17 @@ class FullStackConsoleTest < ActiveSupport::TestCase @primary.puts "quit" end + def test_sandbox_when_sandbox_is_disabled + add_to_config <<-RUBY + config.disable_sandbox = true + RUBY + + output = `#{app_path}/bin/rails console --sandbox` + + assert_includes output, "sandbox mode is disabled" + assert_equal 1, $?.exitstatus + end + def test_environment_option_and_irb_option spawn_console("-e test -- --verbose") diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index bfa66770bd..9c98489590 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -34,6 +34,22 @@ class LoadingTest < ActiveSupport::TestCase assert_equal "omg", p.title end + test "constants without a matching file raise NameError" do + app_file "app/models/post.rb", <<-RUBY + class Post + NON_EXISTING_CONSTANT + end + RUBY + + boot_app + + e = assert_raise(NameError) { User } + assert_equal "uninitialized constant #{self.class}::User", e.message + + e = assert_raise(NameError) { Post } + assert_equal "uninitialized constant Post::NON_EXISTING_CONSTANT", e.message + end + test "concerns in app are autoloaded" do app_file "app/controllers/concerns/trackable.rb", <<-CONCERN module Trackable diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index 5879949b61..a1e237fa7b 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -1,11 +1,12 @@ # frozen_string_literal: true require "isolation/abstract_unit" +require "env_helpers" module ApplicationTests module RakeTests class RakeDbsTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, EnvHelpers def setup build_app @@ -52,27 +53,73 @@ module ApplicationTests test "db:create and db:drop respect environment setting" do app_file "config/database.yml", <<-YAML + <% 1 %> development: - database: db/development.sqlite3 + database: <%= Rails.application.config.database %> adapter: sqlite3 YAML app_file "config/environments/development.rb", <<-RUBY Rails.application.configure do - config.read_encrypted_secrets = true + config.database = "db/development.sqlite3" end RUBY - app_file "lib/tasks/check_env.rake", <<-RUBY - Rake::Task["db:create"].enhance do - File.write("tmp/config_value", Rails.application.config.read_encrypted_secrets) + db_create_and_drop("db/development.sqlite3", environment_loaded: false) + end + + test "db:create and db:drop don't raise errors when loading YAML with multiline ERB" do + app_file "config/database.yml", <<-YAML + development: + database: <%= + Rails.application.config.database + %> + adapter: sqlite3 + YAML + + app_file "config/environments/development.rb", <<-RUBY + Rails.application.configure do + config.database = "db/development.sqlite3" end RUBY - db_create_and_drop("db/development.sqlite3", environment_loaded: false) do - assert File.exist?("tmp/config_value") - assert_equal "true", File.read("tmp/config_value") - end + db_create_and_drop("db/development.sqlite3", environment_loaded: false) + end + + test "db:create and db:drop don't raise errors when loading YAML containing conditional statements in ERB" do + app_file "config/database.yml", <<-YAML + development: + <% if Rails.application.config.database %> + database: <%= Rails.application.config.database %> + <% else %> + database: db/default.sqlite3 + <% end %> + adapter: sqlite3 + YAML + + app_file "config/environments/development.rb", <<-RUBY + Rails.application.configure do + config.database = "db/development.sqlite3" + end + RUBY + + db_create_and_drop("db/development.sqlite3", environment_loaded: false) + end + + test "db:create and db:drop don't raise errors when loading YAML containing multiple ERB statements on the same line" do + app_file "config/database.yml", <<-YAML + development: + database: <% if Rails.application.config.database %><%= Rails.application.config.database %><% else %>db/default.sqlite3<% end %> + adapter: sqlite3 + YAML + + app_file "config/environments/development.rb", <<-RUBY + Rails.application.configure do + config.database = "db/development.sqlite3" + end + RUBY + + db_create_and_drop("db/development.sqlite3", environment_loaded: false) end def with_database_existing @@ -139,6 +186,59 @@ module ApplicationTests end end + test "db:truncate_all truncates all non-internal tables" do + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate" + require "#{app_path}/config/environment" + Book.create!(title: "Remote") + assert_equal 1, Book.count + schema_migrations = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + internal_metadata = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + + rails "db:truncate_all" + + assert_equal( + schema_migrations, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + ) + assert_equal( + internal_metadata, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + ) + assert_equal 0, Book.count + end + end + + test "db:truncate_all does not truncate any tables when environment is protected" do + with_rails_env "production" do + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate" + require "#{app_path}/config/environment" + Book.create!(title: "Remote") + assert_equal 1, Book.count + schema_migrations = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + internal_metadata = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + books = ActiveRecord::Base.connection.execute("SELECT * from \"books\"") + + output = rails("db:truncate_all", allow_failure: true) + assert_match(/ActiveRecord::ProtectedEnvironmentError/, output) + + assert_equal( + schema_migrations, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + ) + assert_equal( + internal_metadata, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + ) + assert_equal 1, Book.count + assert_equal(books, ActiveRecord::Base.connection.execute("SELECT * from \"books\"")) + end + end + end + def db_migrate_and_status(expected_database) rails "generate", "model", "book", "title:string" rails "db:migrate" @@ -179,9 +279,10 @@ module ApplicationTests def db_fixtures_load(expected_database) Dir.chdir(app_path) do rails "generate", "model", "book", "title:string" + reload rails "db:migrate", "db:fixtures:load" + assert_match expected_database, ActiveRecord::Base.connection_config[:database] - require "#{app_path}/app/models/book" assert_equal 2, Book.count end end @@ -201,8 +302,9 @@ module ApplicationTests require "#{app_path}/config/environment" rails "generate", "model", "admin::book", "title:string" + reload rails "db:migrate", "db:fixtures:load" - require "#{app_path}/app/models/admin/book" + assert_equal 2, Admin::Book.count end @@ -385,6 +487,72 @@ module ApplicationTests assert_equal "test", test_environment.call end + + test "db:seed:replant truncates all non-internal tables and loads the seeds" do + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate" + require "#{app_path}/config/environment" + Book.create!(title: "Remote") + assert_equal 1, Book.count + schema_migrations = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + internal_metadata = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + + app_file "db/seeds.rb", <<-RUBY + Book.create!(title: "Rework") + Book.create!(title: "Ruby Under a Microscope") + RUBY + + rails "db:seed:replant" + + assert_equal( + schema_migrations, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + ) + assert_equal( + internal_metadata, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + ) + assert_equal 2, Book.count + assert_not_predicate Book.where(title: "Remote"), :exists? + assert_predicate Book.where(title: "Rework"), :exists? + assert_predicate Book.where(title: "Ruby Under a Microscope"), :exists? + end + end + + test "db:seed:replant does not truncate any tables and does not load the seeds when environment is protected" do + with_rails_env "production" do + Dir.chdir(app_path) do + rails "generate", "model", "book", "title:string" + rails "db:migrate" + require "#{app_path}/config/environment" + Book.create!(title: "Remote") + assert_equal 1, Book.count + schema_migrations = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + internal_metadata = ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + books = ActiveRecord::Base.connection.execute("SELECT * from \"books\"") + + app_file "db/seeds.rb", <<-RUBY + Book.create!(title: "Rework") + RUBY + + output = rails("db:seed:replant", allow_failure: true) + assert_match(/ActiveRecord::ProtectedEnvironmentError/, output) + + assert_equal( + schema_migrations, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.schema_migrations_table_name}\"") + ) + assert_equal( + internal_metadata, + ActiveRecord::Base.connection.execute("SELECT * from \"#{ActiveRecord::Base.internal_metadata_table_name}\"") + ) + assert_equal 1, Book.count + assert_equal(books, ActiveRecord::Base.connection.execute("SELECT * from \"books\"")) + assert_not_predicate Book.where(title: "Rework"), :exists? + end + end + end end end end diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index ef99365e75..d676e7486e 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -170,6 +170,7 @@ module ApplicationTests rails "generate", "model", "book", "title:string" rails "generate", "model", "dog", "name:string" write_models_for_animals + reload end test "db:create and db:drop works on all databases for env" do diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb index 8f5f48c281..dfb9540093 100644 --- a/railties/test/application/runner_test.rb +++ b/railties/test/application/runner_test.rb @@ -105,6 +105,14 @@ module ApplicationTests assert_match "development", rails("runner", "puts Rails.env") end + def test_environment_option + assert_match "production", rails("runner", "-e", "production", "puts Rails.env") + end + + def test_environment_option_is_properly_expanded + assert_match "production", rails("runner", "-e", "prod", "puts Rails.env") + end + def test_runner_detects_syntax_errors output = rails("runner", "puts 'hello world", allow_failure: true) assert_not_predicate $?, :success? diff --git a/railties/test/application/server_test.rb b/railties/test/application/server_test.rb index 9df36b3444..5fe1b4e6e7 100644 --- a/railties/test/application/server_test.rb +++ b/railties/test/application/server_test.rb @@ -30,13 +30,13 @@ module ApplicationTests pid = nil Bundler.with_original_env do - pid = Process.spawn("bin/rails server -P tmp/dummy.pid", chdir: app_path, in: replica, out: replica, err: replica) + pid = Process.spawn("bin/rails server -b localhost -P tmp/dummy.pid", chdir: app_path, in: replica, out: replica, err: replica) assert_output("Listening", primary) rails("restart") assert_output("Restarting", primary) - assert_output("Inherited", primary) + assert_output("tcp://localhost:3000", primary) ensure kill(pid) if pid end diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index fb43bebfbe..83e63718df 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -234,7 +234,7 @@ module ApplicationTests # TODO: would be nice if we could detect the schema change automatically. # For now, the user has to synchronize the schema manually. - # This test-case serves as a reminder for this use-case. + # This test case serves as a reminder for this use case. test "manually synchronize test schema after rollback" do output = rails("generate", "model", "user", "name:string") version = output.match(/(\d+)_create_users\.rb/)[1] diff --git a/railties/test/application/url_generation_test.rb b/railties/test/application/url_generation_test.rb index 6bcc0b0acb..dc737089f6 100644 --- a/railties/test/application/url_generation_test.rb +++ b/railties/test/application/url_generation_test.rb @@ -20,6 +20,7 @@ module ApplicationTests config.active_support.deprecation = :log config.eager_load = false config.hosts << proc { true } + config.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33" end Rails.application.initialize! diff --git a/railties/test/application/zeitwerk_integration_test.rb b/railties/test/application/zeitwerk_integration_test.rb index 628a85acd8..c82b37d07d 100644 --- a/railties/test/application/zeitwerk_integration_test.rb +++ b/railties/test/application/zeitwerk_integration_test.rb @@ -30,9 +30,10 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase boot assert decorated? - assert_instance_of Zeitwerk::Loader, Rails.autoloader - assert_instance_of Zeitwerk::Loader, Rails.once_autoloader - assert_equal [Rails.autoloader, Rails.once_autoloader], Rails.autoloaders + assert Rails.autoloaders.zeitwerk_enabled? + assert_instance_of Zeitwerk::Loader, Rails.autoloaders.main + assert_instance_of Zeitwerk::Loader, Rails.autoloaders.once + assert_equal [Rails.autoloaders.main, Rails.autoloaders.once], Rails.autoloaders.to_a end test "ActiveSupport::Dependencies is not decorated in classic mode" do @@ -40,9 +41,35 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase boot assert_not decorated? - assert_nil Rails.autoloader - assert_nil Rails.once_autoloader - assert_empty Rails.autoloaders + assert_not Rails.autoloaders.zeitwerk_enabled? + assert_nil Rails.autoloaders.main + assert_nil Rails.autoloaders.once + assert_equal 0, Rails.autoloaders.count + end + + test "autoloaders inflect with Active Support" do + app_file "config/initializers/inflections.rb", <<-RUBY + ActiveSupport::Inflector.inflections(:en) do |inflect| + inflect.acronym 'RESTful' + end + RUBY + + app_file "app/controllers/restful_controller.rb", <<-RUBY + class RESTfulController < ApplicationController + end + RUBY + + boot + + basename = "restful_controller" + abspath = "#{Rails.root}/app/controllers/#{basename}.rb" + camelized = "RESTfulController" + + Rails.autoloaders.each do |autoloader| + assert_equal camelized, autoloader.inflector.camelize(basename, abspath) + end + + assert RESTfulController end test "constantize returns the value stored in the constant" do @@ -122,22 +149,27 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase assert $zeitwerk_integration_test_extras end - test "autoload paths that are below Gem.path go to the once autoloader" do - app_dir "extras" - add_to_config 'config.autoload_paths << "#{Rails.root}/extras"' - - # Mocks Gem.path to include the extras directory. - Gem.singleton_class.prepend( - Module.new do - def path - super + ["#{Rails.root}/extras"] - end - end - ) + test "autoload_paths are set as root dirs of main, and in the same order" do + boot + + existing_autoload_paths = deps.autoload_paths.select { |dir| File.directory?(dir) } + assert_equal existing_autoload_paths, Rails.autoloaders.main.dirs + end + + test "autoload_once_paths go to the once autoloader, and in the same order" do + extras = %w(e1 e2 e3) + extras.each do |extra| + app_dir extra + add_to_config %(config.autoload_once_paths << "\#{Rails.root}/#{extra}") + end + boot - assert_not_includes Rails.autoloader.dirs, "#{app_path}/extras" - assert_includes Rails.once_autoloader.dirs, "#{app_path}/extras" + extras = extras.map { |extra| "#{app_path}/#{extra}" } + extras.each do |extra| + assert_not_includes Rails.autoloaders.main.dirs, extra + end + assert_equal extras, Rails.autoloaders.once.dirs end test "clear reloads the main autoloader, and does not reload the once one" do @@ -145,13 +177,13 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase $zeitwerk_integration_reload_test = [] - autoloader = Rails.autoloader - def autoloader.reload - $zeitwerk_integration_reload_test << :autoloader + main_autoloader = Rails.autoloaders.main + def main_autoloader.reload + $zeitwerk_integration_reload_test << :main_autoloader super end - once_autoloader = Rails.once_autoloader + once_autoloader = Rails.autoloaders.once def once_autoloader.reload $zeitwerk_integration_reload_test << :once_autoloader super @@ -159,6 +191,72 @@ class ZeitwerkIntegrationTest < ActiveSupport::TestCase ActiveSupport::Dependencies.clear - assert_equal %i(autoloader), $zeitwerk_integration_reload_test + assert_equal %i(main_autoloader), $zeitwerk_integration_reload_test + end + + test "verbose = true sets the dependencies logger if present" do + boot + + logger = Logger.new(File::NULL) + ActiveSupport::Dependencies.logger = logger + ActiveSupport::Dependencies.verbose = true + + Rails.autoloaders.each do |autoloader| + assert_same logger, autoloader.logger + end + end + + test "verbose = true sets the Rails logger as fallback" do + boot + + ActiveSupport::Dependencies.verbose = true + + Rails.autoloaders.each do |autoloader| + assert_same Rails.logger, autoloader.logger + end + end + + test "verbose = false sets loggers to nil" do + boot + + ActiveSupport::Dependencies.verbose = true + Rails.autoloaders.each do |autoloader| + assert autoloader.logger + end + + ActiveSupport::Dependencies.verbose = false + Rails.autoloaders.each do |autoloader| + assert_nil autoloader.logger + end + end + + test "unhooks" do + boot + + assert_equal Module, Module.method(:const_missing).owner + assert_equal :no_op, deps.unhook! + end + + test "autoloaders.logger=" do + boot + + logger = ->(_msg) { } + Rails.autoloaders.logger = logger + + Rails.autoloaders.each do |autoloader| + assert_same logger, autoloader.logger + end + + Rails.autoloaders.logger = Rails.logger + + Rails.autoloaders.each do |autoloader| + assert_same Rails.logger, autoloader.logger + end + + Rails.autoloaders.logger = nil + + Rails.autoloaders.each do |autoloader| + assert_nil autoloader.logger + end end end diff --git a/railties/test/backtrace_cleaner_test.rb b/railties/test/backtrace_cleaner_test.rb index 90e084ddca..ec512b6b64 100644 --- a/railties/test/backtrace_cleaner_test.rb +++ b/railties/test/backtrace_cleaner_test.rb @@ -18,7 +18,7 @@ class BacktraceCleanerTest < ActiveSupport::TestCase end test "should omit ActionView template methods names" do - method_name = ActionView::Template.new(nil, "app/views/application/index.html.erb", nil, {}).send :method_name + method_name = ActionView::Template.new(nil, "app/views/application/index.html.erb", nil, locals: []).send :method_name backtrace = [ "app/views/application/index.html.erb:4:in `block in #{method_name}'"] result = @cleaner.clean(backtrace, :all) assert_equal "app/views/application/index.html.erb:4", result[0] diff --git a/railties/test/commands/console_test.rb b/railties/test/commands/console_test.rb index 1941c83d6d..f6df2b694a 100644 --- a/railties/test/commands/console_test.rb +++ b/railties/test/commands/console_test.rb @@ -129,7 +129,7 @@ class Rails::ConsoleTest < ActiveSupport::TestCase def build_app(console) mocked_console = Class.new do attr_accessor :sandbox - attr_reader :console + attr_reader :console, :disable_sandbox def initialize(console) @console = console diff --git a/railties/test/commands/credentials_test.rb b/railties/test/commands/credentials_test.rb index 10d0ba1cae..0ee36081c0 100644 --- a/railties/test/commands/credentials_test.rb +++ b/railties/test/commands/credentials_test.rb @@ -63,6 +63,14 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase end end + test "edit command properly expands environment option" do + assert_match(/access_key_id: 123/, run_edit_command(environment: "prod")) + Dir.chdir(app_path) do + assert File.exist?("config/credentials/production.key") + assert File.exist?("config/credentials/production.yml.enc") + end + end + test "edit command does not raise when an initializer tries to access non-existent credentials" do app_file "config/initializers/raise_when_loaded.rb", <<-RUBY Rails.application.credentials.missing_key! @@ -71,11 +79,20 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase assert_match(/access_key_id: 123/, run_edit_command(environment: "qa")) end + test "edit command generates template file when the file does not exist" do + FileUtils.rm("#{app_path}/config/credentials.yml.enc") + run_edit_command + + output = run_show_command + assert_match(/access_key_id: 123/, output) + assert_match(/secret_key_base/, output) + end + test "show credentials" do assert_match(/access_key_id: 123/, run_show_command) end - test "show command raise error when require_master_key is specified and key does not exist" do + test "show command raises error when require_master_key is specified and key does not exist" do remove_file "config/master.key" add_to_config "config.require_master_key = true" @@ -95,6 +112,14 @@ class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase assert_match(/access_key_id: 123/, run_show_command(environment: "production")) end + test "show command properly expands environment option" do + run_edit_command(environment: "production") + + output = run_show_command(environment: "prod") + assert_match(/access_key_id: 123/, output) + assert_no_match(/secret_key_base/, output) + end + private def run_edit_command(editor: "cat", environment: nil, **options) switch_env("EDITOR", editor) do diff --git a/railties/test/commands/initializers_test.rb b/railties/test/commands/initializers_test.rb index bdfbb3021c..793365ef3d 100644 --- a/railties/test/commands/initializers_test.rb +++ b/railties/test/commands/initializers_test.rb @@ -25,8 +25,24 @@ class Rails::Command::InitializersTest < ActiveSupport::TestCase assert final_output.include?("set_added_test_module") end + + test "prints out initializers only specified in environment option" do + add_to_config <<-RUBY + initializer(:set_added_development_module) { } if Rails.env.development? + initializer(:set_added_production_module) { } if Rails.env.production? + RUBY + + output = run_initializers_command.split("\n") + assert_includes output, "AppTemplate::Application.set_added_development_module" + assert_not_includes output, "AppTemplate::Application.set_added_production_module" + + output = run_initializers_command(["-e", "production"]).split("\n") + assert_not_includes output, "AppTemplate::Application.set_added_development_module" + assert_includes output, "AppTemplate::Application.set_added_production_module" + end + private - def run_initializers_command - rails "initializers" + def run_initializers_command(args = []) + rails "initializers", args end end diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb index 25b89ecbd8..b78370a233 100644 --- a/railties/test/commands/server_test.rb +++ b/railties/test/commands/server_test.rb @@ -22,6 +22,12 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase assert_nil options[:server] end + def test_environment_option_is_properly_expanded + args = ["-e", "prod"] + options = parse_arguments(args) + assert_equal "production", options[:environment] + end + def test_explicit_using_option args = ["-u", "thin"] options = parse_arguments(args) @@ -285,6 +291,8 @@ class Rails::Command::ServerCommandTest < ActiveSupport::TestCase end def parse_arguments(args = []) - Rails::Command::ServerCommand.new([], args).server_options + command = Rails::Command::ServerCommand.new([], args) + command.send(:extract_environment_option_from_argument) + command.server_options end end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 937b8eb427..d5a3599f67 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -617,7 +617,7 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_no_gem "capybara" assert_no_gem "selenium-webdriver" - assert_no_gem "chromedriver-helper" + assert_no_gem "webdrivers" assert_no_directory("test") end @@ -626,7 +626,7 @@ class AppGeneratorTest < Rails::Generators::TestCase run_generator [destination_root, "--skip-system-test"] assert_no_gem "capybara" assert_no_gem "selenium-webdriver" - assert_no_gem "chromedriver-helper" + assert_no_gem "webdrivers" assert_directory("test") @@ -660,15 +660,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_gem "jbuilder" end - def test_inclusion_of_zeitwerk - run_generator - if RUBY_ENGINE == "ruby" - assert_gem "zeitwerk" - else - assert_no_gem "zeitwerk" - end - end - def test_inclusion_of_a_debugger run_generator if defined?(JRUBY_VERSION) || RUBY_ENGINE == "rbx" diff --git a/railties/test/generators/db_system_change_generator_test.rb b/railties/test/generators/db_system_change_generator_test.rb index d476bfd2dc..d3d27b616a 100644 --- a/railties/test/generators/db_system_change_generator_test.rb +++ b/railties/test/generators/db_system_change_generator_test.rb @@ -40,7 +40,7 @@ module Rails assert_file("Gemfile") do |content| assert_match "# Use pg as the database for Active Record", content - assert_match "gem 'pg'", content + assert_match "gem 'pg', '>= 0.18', '< 2.0'", content end end @@ -54,7 +54,7 @@ module Rails assert_file("Gemfile") do |content| assert_match "# Use mysql2 as the database for Active Record", content - assert_match "gem 'mysql2'", content + assert_match "gem 'mysql2', '>= 0.4.4'", content end end @@ -68,7 +68,22 @@ module Rails assert_file("Gemfile") do |content| assert_match "# Use sqlite3 as the database for Active Record", content - assert_match "gem 'sqlite3'", content + assert_match "gem 'sqlite3', '~> 1.3', '>= 1.3.6'", content + end + end + + test "change from versioned gem to other versioned gem" do + run_generator ["--to", "sqlite3"] + run_generator ["--to", "mysql", "--force"] + + assert_file("config/database.yml") do |content| + assert_match "adapter: mysql2", content + assert_match "database: test_app", content + end + + assert_file("Gemfile") do |content| + assert_match "# Use mysql2 as the database for Active Record", content + assert_match "gem 'mysql2', '>= 0.4.4'", content end end end diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index 5812cbdfc9..acc5fc3b25 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -265,6 +265,17 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end end + def test_database_puts_migrations_in_configured_folder_with_aliases + with_secondary_database_configuration do + run_generator ["create_books", "--db=secondary"] + assert_migration "db/secondary_migrate/create_books.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :books/, change) + end + end + end + end + def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove_or_create migration = "delete_books" run_generator [migration, "title:string", "content:text"] diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index 134659f285..bdb430369e 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -403,6 +403,17 @@ class ModelGeneratorTest < Rails::Generators::TestCase end end + def test_database_puts_migrations_in_configured_folder_with_aliases + with_secondary_database_configuration do + run_generator ["account", "--db=secondary"] + assert_migration "db/secondary_migrate/create_accounts.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :accounts/, change) + end + end + end + end + def test_required_belongs_to_adds_required_association run_generator ["account", "supplier:references{required}"] diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index f672e301a7..715ad938f4 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -479,6 +479,14 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase end end + def test_scaffold_generator_database_with_aliases + with_secondary_database_configuration do + run_generator ["posts", "--db=secondary"] + + assert_migration "db/secondary_migrate/create_posts.rb" + end + end + def test_scaffold_generator_password_digest run_generator ["user", "name", "password:digest"] diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 47d42645c6..3fcfaa9623 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -123,6 +123,8 @@ module TestHelpers adapter: sqlite3 pool: 5 timeout: 5000 + variables: + statement_timeout: 1000 development: primary: <<: *default @@ -226,6 +228,7 @@ module TestHelpers @app.config.session_store :cookie_store, key: "_myapp_session" @app.config.active_support.deprecation = :log @app.config.log_level = :info + @app.secrets.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33" yield @app if block_given? @app.initialize! @@ -458,12 +461,19 @@ module TestHelpers end end end + + module Reload + def reload + ActiveSupport::Dependencies.clear + end + end end class ActiveSupport::TestCase include TestHelpers::Paths include TestHelpers::Rack include TestHelpers::Generation + include TestHelpers::Reload include ActiveSupport::Testing::Stream include ActiveSupport::Testing::MethodCallAssertions end @@ -481,7 +491,14 @@ Module.new do f.puts "require 'rails/all'" end + unless File.exist?("#{RAILS_FRAMEWORK_ROOT}/actionview/lib/assets/compiled/rails-ujs.js") + Dir.chdir("#{RAILS_FRAMEWORK_ROOT}/actionview") { `yarn build` } + end + assets_path = "#{RAILS_FRAMEWORK_ROOT}/railties/test/isolation/assets" + unless Dir.exist?("#{assets_path}/node_modules") + Dir.chdir(assets_path) { `yarn install` } + end FileUtils.cp("#{assets_path}/package.json", "#{app_template_path}/package.json") FileUtils.cp("#{assets_path}/config/webpacker.yml", "#{app_template_path}/config/webpacker.yml") FileUtils.cp_r("#{assets_path}/config/webpack", "#{app_template_path}/config/webpack") @@ -491,11 +508,7 @@ Module.new do # Fake 'Bundler.require' -- we run using the repo's Gemfile, not an # app-specific one: we don't want to require every gem that lists. contents = File.read("#{app_template_path}/config/application.rb") - if RUBY_ENGINE == "ruby" - contents.sub!(/^Bundler\.require.*/, "%w(turbolinks webpacker zeitwerk).each { |r| require r }") - else - contents.sub!(/^Bundler\.require.*/, "%w(turbolinks webpacker).each { |r| require r }") - end + contents.sub!(/^Bundler\.require.*/, "%w(turbolinks webpacker).each { |r| require r }") File.write("#{app_template_path}/config/application.rb", contents) require "rails" diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index 878a238f8d..185a2f9f09 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -10,6 +10,7 @@ end class InfoControllerTest < ActionController::TestCase tests Rails::InfoController + Rails.application.config.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33" def setup Rails.application.routes.draw do |