aboutsummaryrefslogtreecommitdiffstats
path: root/railties/test
diff options
context:
space:
mode:
Diffstat (limited to 'railties/test')
-rw-r--r--railties/test/abstract_unit.rb3
-rw-r--r--railties/test/app_loader_test.rb8
-rw-r--r--railties/test/application/asset_debugging_test.rb18
-rw-r--r--railties/test/application/assets_test.rb17
-rw-r--r--railties/test/application/bin_setup_test.rb4
-rw-r--r--railties/test/application/configuration/custom_test.rb4
-rw-r--r--railties/test/application/configuration_test.rb387
-rw-r--r--railties/test/application/console_test.rb39
-rw-r--r--railties/test/application/content_security_policy_test.rb223
-rw-r--r--railties/test/application/current_attributes_integration_test.rb4
-rw-r--r--railties/test/application/dbconsole_test.rb81
-rw-r--r--railties/test/application/generators_test.rb14
-rw-r--r--railties/test/application/help_test.rb6
-rw-r--r--railties/test/application/initializers/frameworks_test.rb20
-rw-r--r--railties/test/application/initializers/hooks_test.rb2
-rw-r--r--railties/test/application/initializers/i18n_test.rb2
-rw-r--r--railties/test/application/initializers/load_path_test.rb2
-rw-r--r--railties/test/application/initializers/notifications_test.rb3
-rw-r--r--railties/test/application/integration_test_case_test.rb17
-rw-r--r--railties/test/application/loading_test.rb32
-rw-r--r--railties/test/application/mailer_previews_test.rb80
-rw-r--r--railties/test/application/middleware/cache_test.rb16
-rw-r--r--railties/test/application/middleware/cookies_test.rb147
-rw-r--r--railties/test/application/middleware/exceptions_test.rb4
-rw-r--r--railties/test/application/middleware/remote_ip_test.rb2
-rw-r--r--railties/test/application/middleware/sendfile_test.rb8
-rw-r--r--railties/test/application/middleware/session_test.rb74
-rw-r--r--railties/test/application/middleware/static_test.rb2
-rw-r--r--railties/test/application/middleware_test.rb10
-rw-r--r--railties/test/application/multiple_applications_test.rb2
-rw-r--r--railties/test/application/paths_test.rb2
-rw-r--r--railties/test/application/per_request_digest_cache_test.rb4
-rw-r--r--railties/test/application/rack/logger_test.rb2
-rw-r--r--railties/test/application/rackup_test.rb2
-rw-r--r--railties/test/application/rake/dbs_test.rb247
-rw-r--r--railties/test/application/rake/dev_test.rb22
-rw-r--r--railties/test/application/rake/framework_test.rb2
-rw-r--r--railties/test/application/rake/log_test.rb4
-rw-r--r--railties/test/application/rake/migrations_test.rb467
-rw-r--r--railties/test/application/rake/multi_dbs_test.rb164
-rw-r--r--railties/test/application/rake/notes_test.rb7
-rw-r--r--railties/test/application/rake/restart_test.rb17
-rw-r--r--railties/test/application/rake/tmp_test.rb8
-rw-r--r--railties/test/application/rake_test.rb258
-rw-r--r--railties/test/application/rendering_test.rb4
-rw-r--r--railties/test/application/routing_test.rb8
-rw-r--r--railties/test/application/runner_test.rb49
-rw-r--r--railties/test/application/server_test.rb66
-rw-r--r--railties/test/application/test_runner_test.rb241
-rw-r--r--railties/test/application/test_test.rb25
-rw-r--r--railties/test/application/url_generation_test.rb3
-rw-r--r--railties/test/application/version_test.rb6
-rw-r--r--railties/test/backtrace_cleaner_test.rb2
-rw-r--r--railties/test/code_statistics_calculator_test.rb2
-rw-r--r--railties/test/code_statistics_test.rb2
-rw-r--r--railties/test/command/base_test.rb2
-rw-r--r--railties/test/command/spellchecker_test.rb10
-rw-r--r--railties/test/commands/console_test.rb31
-rw-r--r--railties/test/commands/credentials_test.rb86
-rw-r--r--railties/test/commands/dbconsole_test.rb32
-rw-r--r--railties/test/commands/encrypted_test.rb106
-rw-r--r--railties/test/commands/routes_test.rb175
-rw-r--r--railties/test/commands/secrets_test.rb56
-rw-r--r--railties/test/commands/server_test.rb83
-rw-r--r--railties/test/configuration/middleware_stack_proxy_test.rb2
-rw-r--r--railties/test/console_helpers.rb25
-rw-r--r--railties/test/engine/commands_test.rb26
-rw-r--r--railties/test/engine/test_test.rb31
-rw-r--r--railties/test/engine_test.rb4
-rw-r--r--railties/test/env_helpers.rb2
-rw-r--r--railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml1
-rw-r--r--railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb1
-rw-r--r--railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb1
-rw-r--r--railties/test/fixtures/lib/create_test_dummy_template.rb2
-rw-r--r--railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb2
-rw-r--r--railties/test/fixtures/lib/generators/fixjour_generator.rb2
-rw-r--r--railties/test/fixtures/lib/generators/model_generator.rb2
-rw-r--r--railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb2
-rw-r--r--railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb2
-rw-r--r--railties/test/fixtures/lib/template.rb2
-rw-r--r--railties/test/generators/actions_test.rb105
-rw-r--r--railties/test/generators/api_app_generator_test.rb82
-rw-r--r--railties/test/generators/app_generator_test.rb417
-rw-r--r--railties/test/generators/application_record_generator_test.rb16
-rw-r--r--railties/test/generators/argv_scrubber_test.rb5
-rw-r--r--railties/test/generators/assets_generator_test.rb2
-rw-r--r--railties/test/generators/channel_generator_test.rb12
-rw-r--r--railties/test/generators/controller_generator_test.rb38
-rw-r--r--railties/test/generators/create_migration_test.rb12
-rw-r--r--railties/test/generators/encrypted_secrets_generator_test.rb42
-rw-r--r--railties/test/generators/generated_attribute_test.rb14
-rw-r--r--railties/test/generators/generator_generator_test.rb2
-rw-r--r--railties/test/generators/generator_test.rb2
-rw-r--r--railties/test/generators/generators_test_helper.rb6
-rw-r--r--railties/test/generators/helper_generator_test.rb2
-rw-r--r--railties/test/generators/integration_test_generator_test.rb2
-rw-r--r--railties/test/generators/job_generator_test.rb12
-rw-r--r--railties/test/generators/mailer_generator_test.rb2
-rw-r--r--railties/test/generators/migration_generator_test.rb24
-rw-r--r--railties/test/generators/model_generator_test.rb56
-rw-r--r--railties/test/generators/named_base_test.rb41
-rw-r--r--railties/test/generators/namespaced_generators_test.rb15
-rw-r--r--railties/test/generators/orm_test.rb2
-rw-r--r--railties/test/generators/plugin_generator_test.rb154
-rw-r--r--railties/test/generators/plugin_test_helper.rb2
-rw-r--r--railties/test/generators/plugin_test_runner_test.rb10
-rw-r--r--railties/test/generators/resource_generator_test.rb2
-rw-r--r--railties/test/generators/scaffold_controller_generator_test.rb27
-rw-r--r--railties/test/generators/scaffold_generator_test.rb19
-rw-r--r--railties/test/generators/shared_generator_tests.rb264
-rw-r--r--railties/test/generators/system_test_generator_test.rb2
-rw-r--r--railties/test/generators/task_generator_test.rb2
-rw-r--r--railties/test/generators/test_runner_in_engine_test.rb2
-rw-r--r--railties/test/generators_test.rb23
-rw-r--r--railties/test/initializable_test.rb2
-rw-r--r--railties/test/isolation/abstract_unit.rb240
-rw-r--r--railties/test/json_params_parsing_test.rb2
-rw-r--r--railties/test/minitest/rails_plugin_test.rb42
-rw-r--r--railties/test/path_generation_test.rb6
-rw-r--r--railties/test/paths_test.rb30
-rw-r--r--railties/test/rack_logger_test.rb24
-rw-r--r--railties/test/rails_info_controller_test.rb2
-rw-r--r--railties/test/rails_info_test.rb17
-rw-r--r--railties/test/railties/engine_test.rb137
-rw-r--r--railties/test/railties/generators_test.rb2
-rw-r--r--railties/test/railties/mounted_engine_test.rb23
-rw-r--r--railties/test/railties/railtie_test.rb16
-rw-r--r--railties/test/secrets_test.rb60
-rw-r--r--railties/test/test_unit/reporter_test.rb10
-rw-r--r--railties/test/version_test.rb2
130 files changed, 4115 insertions, 1451 deletions
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index 2d4c7a0f0b..b42f37d6b9 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
ENV["RAILS_ENV"] ||= "test"
require "stringio"
@@ -13,7 +15,6 @@ require "rails/all"
module TestApp
class Application < Rails::Application
config.root = __dir__
- secrets.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33"
end
end
diff --git a/railties/test/app_loader_test.rb b/railties/test/app_loader_test.rb
index 85f5502b4d..c7a6bdee1b 100644
--- a/railties/test/app_loader_test.rb
+++ b/railties/test/app_loader_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "tmpdir"
require "abstract_unit"
require "rails/app_loader"
@@ -38,13 +40,13 @@ class AppLoaderTest < ActiveSupport::TestCase
test "is not in a Rails application if #{exe} is not found in the current or parent directories" do
def loader.find_executables; end
- assert !loader.exec_app
+ assert_not loader.exec_app
end
test "is not in a Rails application if #{exe} exists but is a folder" do
FileUtils.mkdir_p(exe)
- assert !loader.exec_app
+ assert_not loader.exec_app
end
["APP_PATH", "ENGINE_PATH"].each do |keyword|
@@ -59,7 +61,7 @@ class AppLoaderTest < ActiveSupport::TestCase
test "is not in a Rails application if #{exe} exists but doesn't contain #{keyword}" do
write exe
- assert !loader.exec_app
+ assert_not loader.exec_app
end
test "is in a Rails application if parent directory has #{exe} containing #{keyword} and chdirs to the root directory" do
diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb
index 3e17a1efa5..3e0f31860b 100644
--- a/railties/test/application/asset_debugging_test.rb
+++ b/railties/test/application/asset_debugging_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -7,10 +9,7 @@ module ApplicationTests
include Rack::Test::Methods
def setup
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- build_app(initializers: true)
- end
+ build_app(initializers: true)
app_file "app/assets/javascripts/application.js", "//= require_tree ."
app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }"
@@ -34,16 +33,10 @@ module ApplicationTests
teardown_app
end
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- def get(*)
- Kernel.silence_warnings { super }
- end
-
test "assets are concatenated when debug is off and compile is off either if debug_assets param is provided" do
# config.assets.debug and config.assets.compile are false for production environment
ENV["RAILS_ENV"] = "production"
- output = Dir.chdir(app_path) { `bin/rails assets:precompile --trace 2>&1` }
- assert $?.success?, output
+ rails "assets:precompile", "--trace"
# Load app env
app "production"
@@ -84,7 +77,8 @@ module ApplicationTests
stylesheet_link_tag: %r{<link rel="stylesheet" media="screen" href="/stylesheets/#{contents}.css" />},
javascript_include_tag: %r{<script src="/javascripts/#{contents}.js">},
audio_tag: %r{<audio src="/audios/#{contents}"></audio>},
- video_tag: %r{<video src="/videos/#{contents}"></video>}
+ video_tag: %r{<video src="/videos/#{contents}"></video>},
+ image_submit_tag: %r{<input type="image" src="/images/#{contents}" />}
}
cases.each do |(view_method, tag_match)|
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index f38cacd6da..9ef123c5b6 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "active_support/json"
@@ -60,10 +62,7 @@ module ApplicationTests
add_to_env_config "development", "config.assets.digest = false"
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- require "#{app_path}/config/environment"
- end
+ require "#{app_path}/config/environment"
get "/assets/demo.js"
assert_equal 'a = "/assets/rails.png";', last_response.body.strip
@@ -77,7 +76,7 @@ module ApplicationTests
# Load app env
app "production"
- assert !defined?(Uglifier)
+ assert_not defined?(Uglifier)
get "/assets/demo.js"
assert_match "alert()", last_response.body
assert defined?(Uglifier)
@@ -271,10 +270,10 @@ module ApplicationTests
app "production"
# Checking if Uglifier is defined we can know if Sprockets was reached or not
- assert !defined?(Uglifier)
+ assert_not defined?(Uglifier)
get "/assets/#{asset_path}"
assert_match "alert()", last_response.body
- assert !defined?(Uglifier)
+ assert_not defined?(Uglifier)
end
test "precompile properly refers files referenced with asset_path" do
@@ -475,9 +474,9 @@ module ApplicationTests
class ::PostsController < ActionController::Base; end
- get "/posts", {}, "HTTPS" => "off"
+ get "/posts", {}, { "HTTPS" => "off" }
assert_match('src="http://example.com/assets/application.self.js', last_response.body)
- get "/posts", {}, "HTTPS" => "on"
+ get "/posts", {}, { "HTTPS" => "on" }
assert_match('src="https://example.com/assets/application.self.js', last_response.body)
end
diff --git a/railties/test/application/bin_setup_test.rb b/railties/test/application/bin_setup_test.rb
index 0fb995900f..54934dbe24 100644
--- a/railties/test/application/bin_setup_test.rb
+++ b/railties/test/application/bin_setup_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -20,7 +22,7 @@ module ApplicationTests
end
RUBY
- list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip }
+ list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip }
File.write("log/test.log", "zomg!")
assert_equal "[]", list_tables.call
diff --git a/railties/test/application/configuration/custom_test.rb b/railties/test/application/configuration/custom_test.rb
index 8360b7bf4b..608bc2fbe3 100644
--- a/railties/test/application/configuration/custom_test.rb
+++ b/railties/test/application/configuration/custom_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -31,7 +33,7 @@ module ApplicationTests
assert_nil x.i_do_not_exist.zomg
# test that custom configuration responds to all messages
- assert_equal true, x.respond_to?(:i_do_not_exist)
+ assert_respond_to x, :i_do_not_exist
assert_kind_of Method, x.method(:i_do_not_exist)
assert_kind_of ActiveSupport::OrderedOptions, x.i_do_not_exist
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 9f62ca8eb8..84606d3b90 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "env_helpers"
@@ -38,10 +40,7 @@ module ApplicationTests
@app ||= begin
ENV["RAILS_ENV"] = env
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- require "#{app_path}/config/environment"
- end
+ require "#{app_path}/config/environment"
Rails.application
ensure
@@ -95,7 +94,7 @@ module ApplicationTests
with_rails_env "development" do
app "development"
- assert Rails.application.config.log_tags.blank?
+ assert_predicate Rails.application.config.log_tags, :blank?
end
end
@@ -238,6 +237,66 @@ module ApplicationTests
assert_instance_of Pathname, Rails.public_path
end
+ test "does not eager load controller actions in development" do
+ app_file "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ActionController::Base
+ def index;end
+ def show;end
+ end
+ RUBY
+
+ app "development"
+
+ assert_nil PostsController.instance_variable_get(:@action_methods)
+ end
+
+ test "eager loads controller actions in production" do
+ app_file "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ActionController::Base
+ def index;end
+ def show;end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ config.eager_load = true
+ config.cache_classes = true
+ RUBY
+
+ app "production"
+
+ assert_equal %w(index show).to_set, PostsController.instance_variable_get(:@action_methods)
+ end
+
+ test "does not eager load mailer actions in development" do
+ app_file "app/mailers/posts_mailer.rb", <<-RUBY
+ class PostsMailer < ActionMailer::Base
+ def noop_email;end
+ end
+ RUBY
+
+ app "development"
+
+ assert_nil PostsMailer.instance_variable_get(:@action_methods)
+ end
+
+ test "eager loads mailer actions in production" do
+ app_file "app/mailers/posts_mailer.rb", <<-RUBY
+ class PostsMailer < ActionMailer::Base
+ def noop_email;end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ config.eager_load = true
+ config.cache_classes = true
+ RUBY
+
+ app "production"
+
+ assert_equal %w(noop_email).to_set, PostsMailer.instance_variable_get(:@action_methods)
+ end
+
test "initialize an eager loaded, cache classes app" do
add_to_config <<-RUBY
config.eager_load = true
@@ -255,6 +314,7 @@ module ApplicationTests
end
test "the application can be eager loaded even when there are no frameworks" do
+ FileUtils.rm_rf("#{app_path}/app/jobs/application_job.rb")
FileUtils.rm_rf("#{app_path}/app/models/application_record.rb")
FileUtils.rm_rf("#{app_path}/app/mailers/application_mailer.rb")
FileUtils.rm_rf("#{app_path}/config/environments")
@@ -301,7 +361,7 @@ module ApplicationTests
end
RUBY
- assert !$prepared
+ assert_not $prepared
app "development"
@@ -416,47 +476,61 @@ module ApplicationTests
test "application message verifier can be used when the key_generator is ActiveSupport::LegacyKeyGenerator" do
app_file "config/initializers/secret_token.rb", <<-RUBY
+ Rails.application.credentials.secret_key_base = nil
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
- app "development"
+ app "production"
- assert_equal app.env_config["action_dispatch.key_generator"], Rails.application.key_generator
- assert_equal app.env_config["action_dispatch.key_generator"].class, ActiveSupport::LegacyKeyGenerator
+ assert_kind_of ActiveSupport::LegacyKeyGenerator, Rails.application.key_generator
message = app.message_verifier(:sensitive_value).generate("some_value")
assert_equal "some_value", Rails.application.message_verifier(:sensitive_value).verify(message)
end
- test "warns when secrets.secret_key_base is blank and config.secret_token is set" do
+ test "config.secret_token is deprecated" do
app_file "config/initializers/secret_token.rb", <<-RUBY
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
- app "development"
+ app "production"
- assert_deprecated(/You didn't set `secret_key_base`./) do
- app.env_config
+ assert_deprecated(/secret_token/) do
+ app.secrets
end
end
- test "raise when secrets.secret_key_base is not a type of string" do
+ test "secrets.secret_token is deprecated" do
app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base: 123
+ production:
+ secret_token: "b3c631c314c0bbca50c1b2843150fe33"
YAML
- app "development"
+ app "production"
+
+ assert_deprecated(/secret_token/) do
+ app.secrets
+ 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
+ RUBY
+
+ error = assert_raise(ArgumentError) do
+ app "production"
+ end
+ assert_match(/Missing `secret_key_base`./, error.message)
+ end
+
+ test "raise when secret_key_base is not a type of string" do
+ add_to_config <<-RUBY
+ Rails.application.credentials.secret_key_base = 123
+ RUBY
assert_raise(ArgumentError) do
- app.key_generator
+ app "production"
end
end
@@ -476,7 +550,7 @@ module ApplicationTests
test "application verifier can build different verifiers" do
make_basic_app do |application|
- application.secrets.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33"
+ application.credentials.secret_key_base = "b3c631c314c0bbca50c1b2843150fe33"
application.config.session_store :disabled
end
@@ -502,6 +576,7 @@ module ApplicationTests
app "development"
assert_equal "3b7cd727ee24e8444053437c36cc66c3", app.secrets.secret_key_base
+ assert_equal "3b7cd727ee24e8444053437c36cc66c3", app.secret_key_base
end
test "secret_key_base is copied from config to secrets when not set" do
@@ -594,37 +669,15 @@ module ApplicationTests
test "uses ActiveSupport::LegacyKeyGenerator as app.key_generator when secrets.secret_key_base is blank" do
app_file "config/initializers/secret_token.rb", <<-RUBY
+ Rails.application.credentials.secret_key_base = nil
Rails.application.config.secret_token = "b3c631c314c0bbca50c1b2843150fe33"
RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
- app "development"
+ app "production"
assert_equal "b3c631c314c0bbca50c1b2843150fe33", app.config.secret_token
- assert_nil app.secrets.secret_key_base
- assert_equal app.key_generator.class, ActiveSupport::LegacyKeyGenerator
- end
-
- test "uses ActiveSupport::LegacyKeyGenerator with config.secret_token as app.key_generator when secrets.secret_key_base is blank" do
- app_file "config/initializers/secret_token.rb", <<-RUBY
- Rails.application.config.secret_token = ""
- RUBY
- app_file "config/secrets.yml", <<-YAML
- development:
- secret_key_base:
- YAML
-
- app "development"
-
- assert_equal "", app.config.secret_token
- assert_nil app.secrets.secret_key_base
- e = assert_raise ArgumentError do
- app.key_generator
- end
- assert_match(/\AA secret is required/, e.message)
+ assert_nil app.credentials.secret_key_base
+ assert_kind_of ActiveSupport::LegacyKeyGenerator, app.key_generator
end
test "that nested keys are symbolized the same as parents for hashes more than one level deep" do
@@ -641,6 +694,28 @@ module ApplicationTests
assert_equal "697361616320736c6f616e2028656c6f7265737429", app.secrets.smtp_settings[:password]
end
+ test "require_master_key aborts app boot when missing key" do
+ skip "can't run without fork" unless Process.respond_to?(:fork)
+
+ remove_file "config/master.key"
+ add_to_config "config.require_master_key = true"
+
+ error = capture(:stderr) do
+ Process.wait(Process.fork { app "development" })
+ end
+
+ assert_equal 1, $?.exitstatus
+ assert_match(/Missing.*RAILS_MASTER_KEY/, error)
+ end
+
+ test "credentials does not raise error when require_master_key is false and master key does not exist" do
+ remove_file "config/master.key"
+ add_to_config "config.require_master_key = false"
+ app "development"
+
+ assert_not app.credentials.secret_key_base
+ end
+
test "protect from forgery is the default in a new app" do
make_basic_app
@@ -691,6 +766,68 @@ module ApplicationTests
assert_match(/label/, last_response.body)
end
+ test "form_with can be configured with form_with_generates_ids" do
+ app_file "config/initializers/form_builder.rb", <<-RUBY
+ Rails.configuration.action_view.form_with_generates_ids = false
+ RUBY
+
+ app_file "app/models/post.rb", <<-RUBY
+ class Post
+ include ActiveModel::Model
+ attr_accessor :name
+ end
+ RUBY
+
+ app_file "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ApplicationController
+ def index
+ render inline: "<%= begin; form_with(model: Post.new) {|f| f.text_field(:name)}; rescue => e; e.to_s; end %>"
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ routes.prepend do
+ resources :posts
+ end
+ RUBY
+
+ app "development"
+
+ get "/posts"
+
+ assert_no_match(/id=('|")post_name('|")/, last_response.body)
+ end
+
+ test "form_with outputs ids by default" do
+ app_file "app/models/post.rb", <<-RUBY
+ class Post
+ include ActiveModel::Model
+ attr_accessor :name
+ end
+ RUBY
+
+ app_file "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ApplicationController
+ def index
+ render inline: "<%= begin; form_with(model: Post.new) {|f| f.text_field(:name)}; rescue => e; e.to_s; end %>"
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ routes.prepend do
+ resources :posts
+ end
+ RUBY
+
+ app "development"
+
+ get "/posts"
+
+ assert_match(/id=('|")post_name('|")/, last_response.body)
+ end
+
test "form_with can be configured with form_with_generates_remote_forms" do
app_file "config/initializers/form_builder.rb", <<-RUBY
Rails.configuration.action_view.form_with_generates_remote_forms = false
@@ -1131,6 +1268,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters
@@ -1142,6 +1280,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal %w(controller action), ActionController::Parameters.always_permitted_parameters
end
@@ -1154,6 +1293,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal %w( controller action format ), ActionController::Parameters.always_permitted_parameters
end
@@ -1178,6 +1318,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters
@@ -1185,26 +1326,29 @@ module ApplicationTests
assert_equal 200, last_response.status
end
- test "config.action_controller.action_on_unpermitted_parameters is :log by default on development" do
+ test "config.action_controller.action_on_unpermitted_parameters is :log by default in development" do
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal :log, ActionController::Parameters.action_on_unpermitted_parameters
end
- test "config.action_controller.action_on_unpermitted_parameters is :log by default on test" do
+ test "config.action_controller.action_on_unpermitted_parameters is :log by default in test" do
app "test"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal :log, ActionController::Parameters.action_on_unpermitted_parameters
end
- test "config.action_controller.action_on_unpermitted_parameters is false by default on production" do
+ test "config.action_controller.action_on_unpermitted_parameters is false by default in production" do
app "production"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal false, ActionController::Parameters.action_on_unpermitted_parameters
end
@@ -1224,6 +1368,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal true, ActionController::Parameters.permit_all_parameters
end
@@ -1235,6 +1380,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal [], ActionController::Parameters.always_permitted_parameters
end
@@ -1246,6 +1392,7 @@ module ApplicationTests
app "development"
force_lazy_load_hooks { ActionController::Base }
+ force_lazy_load_hooks { ActionController::API }
assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters
end
@@ -1263,21 +1410,21 @@ module ApplicationTests
end
end
- get "/", {}, "HTTP_ACCEPT" => "application/xml"
+ get "/", {}, { "HTTP_ACCEPT" => "application/xml" }
assert_equal "HTML", last_response.body
- get "/", { format: :xml }, "HTTP_ACCEPT" => "application/xml"
+ get "/", { format: :xml }, { "HTTP_ACCEPT" => "application/xml" }
assert_equal "XML", last_response.body
end
- test "Rails.application#env_config exists and include some existing parameters" do
+ test "Rails.application#env_config exists and includes some existing parameters" do
make_basic_app
- assert_equal app.env_config["action_dispatch.parameter_filter"], app.config.filter_parameters
- assert_equal app.env_config["action_dispatch.show_exceptions"], app.config.action_dispatch.show_exceptions
- assert_equal app.env_config["action_dispatch.logger"], Rails.logger
- assert_equal app.env_config["action_dispatch.backtrace_cleaner"], Rails.backtrace_cleaner
- assert_equal app.env_config["action_dispatch.key_generator"], Rails.application.key_generator
+ assert_equal app.env_config["action_dispatch.parameter_filter"], app.config.filter_parameters
+ assert_equal app.env_config["action_dispatch.show_exceptions"], app.config.action_dispatch.show_exceptions
+ assert_equal app.env_config["action_dispatch.logger"], Rails.logger
+ assert_equal app.env_config["action_dispatch.backtrace_cleaner"], Rails.backtrace_cleaner
+ assert_equal app.env_config["action_dispatch.key_generator"], Rails.application.key_generator
end
test "config.colorize_logging default is true" do
@@ -1332,7 +1479,7 @@ module ApplicationTests
test "respond_to? accepts include_private" do
make_basic_app
- assert_not Rails.configuration.respond_to?(:method_missing)
+ assert_not_respond_to Rails.configuration, :method_missing
assert Rails.configuration.respond_to?(:method_missing, true)
end
@@ -1344,12 +1491,18 @@ module ApplicationTests
assert_not ActiveRecord::Base.dump_schema_after_migration
end
- test "config.active_record.dump_schema_after_migration is true by default on development" do
+ test "config.active_record.dump_schema_after_migration is true by default in development" do
app "development"
assert ActiveRecord::Base.dump_schema_after_migration
end
+ test "config.active_record.verbose_query_logs is false by default in development" do
+ app "development"
+
+ assert_not ActiveRecord::Base.verbose_query_logs
+ end
+
test "config.annotations wrapping SourceAnnotationExtractor::Annotation class" do
make_basic_app do |application|
application.config.annotations.register_extensions("coffee") do |tag|
@@ -1357,7 +1510,7 @@ module ApplicationTests
end
end
- assert_not_nil SourceAnnotationExtractor::Annotation.extensions[/\.(coffee)$/]
+ assert_not_nil Rails::SourceAnnotationExtractor::Annotation.extensions[/\.(coffee)$/]
end
test "rake_tasks block works at instance level" do
@@ -1452,8 +1605,8 @@ module ApplicationTests
test "raises with proper error message if no database configuration found" do
FileUtils.rm("#{app_path}/config/database.yml")
- app "development"
err = assert_raises RuntimeError do
+ app "development"
Rails.application.config.database_configuration
end
assert_match "config/database", err.message
@@ -1587,9 +1740,7 @@ module ApplicationTests
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
@@ -1616,7 +1767,7 @@ module ApplicationTests
test "represent_boolean_as_integer should be able to set via config.active_record.sqlite3.represent_boolean_as_integer" do
remove_from_config '.*config\.load_defaults.*\n'
- app_file "config/initializers/new_framework_defaults_5_2.rb", <<-RUBY
+ app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
RUBY
@@ -1681,7 +1832,7 @@ module ApplicationTests
test "api_only is false by default" do
app "development"
- refute Rails.application.config.api_only
+ assert_not Rails.application.config.api_only
end
test "api_only generator config is set when api_only is set" do
@@ -1738,6 +1889,96 @@ module ApplicationTests
assert_equal "https://example.org/", last_response.location
end
+ test "ActiveSupport::MessageEncryptor.use_authenticated_message_encryption is true by default for new apps" do
+ app "development"
+
+ assert_equal true, ActiveSupport::MessageEncryptor.use_authenticated_message_encryption
+ end
+
+ test "ActiveSupport::MessageEncryptor.use_authenticated_message_encryption is false by default for upgraded apps" do
+ remove_from_config '.*config\.load_defaults.*\n'
+
+ app "development"
+
+ assert_equal false, ActiveSupport::MessageEncryptor.use_authenticated_message_encryption
+ end
+
+ test "ActiveSupport::MessageEncryptor.use_authenticated_message_encryption can be configured via config.active_support.use_authenticated_message_encryption" do
+ remove_from_config '.*config\.load_defaults.*\n'
+
+ app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY
+ Rails.application.config.active_support.use_authenticated_message_encryption = true
+ RUBY
+
+ app "development"
+
+ assert_equal true, ActiveSupport::MessageEncryptor.use_authenticated_message_encryption
+ end
+
+ test "ActiveSupport::Digest.hash_digest_class is Digest::SHA1 by default for new apps" do
+ app "development"
+
+ assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class
+ end
+
+ test "ActiveSupport::Digest.hash_digest_class is Digest::MD5 by default for upgraded apps" do
+ remove_from_config '.*config\.load_defaults.*\n'
+
+ app "development"
+
+ assert_equal Digest::MD5, ActiveSupport::Digest.hash_digest_class
+ end
+
+ test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.use_sha1_digests" do
+ remove_from_config '.*config\.load_defaults.*\n'
+
+ app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY
+ Rails.application.config.active_support.use_sha1_digests = true
+ RUBY
+
+ app "development"
+
+ assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class
+ end
+
+ test "custom serializers should be able to set via config.active_job.custom_serializers in an initializer" do
+ class ::DummySerializer < ActiveJob::Serializers::ObjectSerializer; end
+
+ app_file "config/initializers/custom_serializers.rb", <<-RUBY
+ Rails.application.config.active_job.custom_serializers << DummySerializer
+ RUBY
+
+ app "development"
+
+ assert_includes ActiveJob::Serializers.serializers, DummySerializer
+ end
+
+ test "ActionView::Helpers::FormTagHelper.default_enforce_utf8 is false by default" do
+ app "development"
+ assert_equal false, ActionView::Helpers::FormTagHelper.default_enforce_utf8
+ end
+
+ test "ActionView::Helpers::FormTagHelper.default_enforce_utf8 is true in an upgraded app" do
+ remove_from_config '.*config\.load_defaults.*\n'
+ add_to_config 'config.load_defaults "5.2"'
+
+ app "development"
+
+ assert_equal true, ActionView::Helpers::FormTagHelper.default_enforce_utf8
+ end
+
+ test "ActionView::Helpers::FormTagHelper.default_enforce_utf8 can be configured via config.action_view.default_enforce_utf8" do
+ remove_from_config '.*config\.load_defaults.*\n'
+
+ app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY
+ Rails.application.config.action_view.default_enforce_utf8 = true
+ RUBY
+
+ app "development"
+
+ assert_equal true, ActionView::Helpers::FormTagHelper.default_enforce_utf8
+ 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 057d473870..4a14042cd3 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -1,4 +1,7 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "console_helpers"
class ConsoleTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
@@ -70,7 +73,7 @@ class ConsoleTest < ActiveSupport::TestCase
MODEL
load_environment
- assert User.new.respond_to?(:name)
+ assert_respond_to User.new, :name
app_file "app/models/user.rb", <<-MODEL
class User
@@ -78,9 +81,9 @@ class ConsoleTest < ActiveSupport::TestCase
end
MODEL
- assert !User.new.respond_to?(:age)
+ assert_not_respond_to User.new, :age
irb_context.reload!(false)
- assert User.new.respond_to?(:age)
+ assert_respond_to User.new, :age
end
def test_access_to_helpers
@@ -93,14 +96,11 @@ class ConsoleTest < ActiveSupport::TestCase
end
end
-begin
- require "pty"
-rescue LoadError
-end
-
class FullStackConsoleTest < ActiveSupport::TestCase
+ include ConsoleHelpers
+
def setup
- skip "PTY unavailable" unless defined?(PTY) && PTY.respond_to?(:open)
+ skip "PTY unavailable" unless available_pty?
build_app
app_file "app/models/post.rb", <<-CODE
@@ -116,24 +116,11 @@ class FullStackConsoleTest < ActiveSupport::TestCase
teardown_app
end
- def assert_output(expected, timeout = 1)
- timeout = Time.now + timeout
-
- output = ""
- until output.include?(expected) || Time.now > timeout
- if IO.select([@master], [], [], 0.1)
- output << @master.read(1)
- end
- end
-
- assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}"
- end
-
def write_prompt(command, expected_output = nil)
@master.puts command
- assert_output command
- assert_output expected_output if expected_output
- assert_output "> "
+ assert_output command, @master
+ assert_output expected_output, @master if expected_output
+ assert_output "> ", @master
end
def spawn_console(options)
@@ -142,7 +129,7 @@ class FullStackConsoleTest < ActiveSupport::TestCase
in: @slave, out: @slave, err: @slave
)
- assert_output "> ", 30
+ assert_output "> ", @master, 30
end
def test_sandbox
diff --git a/railties/test/application/content_security_policy_test.rb b/railties/test/application/content_security_policy_test.rb
new file mode 100644
index 0000000000..0d28df16f8
--- /dev/null
+++ b/railties/test/application/content_security_policy_test.rb
@@ -0,0 +1,223 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "rack/test"
+
+module ApplicationTests
+ class ContentSecurityPolicyTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+ include Rack::Test::Methods
+
+ def setup
+ build_app
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ test "default content security policy is nil" do
+ controller :pages, <<-RUBY
+ class PagesController < ApplicationController
+ def index
+ render html: "<h1>Welcome to Rails!</h1>"
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ root to: "pages#index"
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_nil last_response.headers["Content-Security-Policy"]
+ end
+
+ test "empty content security policy is generated" do
+ controller :pages, <<-RUBY
+ class PagesController < ApplicationController
+ def index
+ render html: "<h1>Welcome to Rails!</h1>"
+ end
+ end
+ RUBY
+
+ app_file "config/initializers/content_security_policy.rb", <<-RUBY
+ Rails.application.config.content_security_policy do |p|
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ root to: "pages#index"
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_policy ""
+ end
+
+ test "global content security policy in an initializer" do
+ controller :pages, <<-RUBY
+ class PagesController < ApplicationController
+ def index
+ render html: "<h1>Welcome to Rails!</h1>"
+ end
+ end
+ RUBY
+
+ app_file "config/initializers/content_security_policy.rb", <<-RUBY
+ Rails.application.config.content_security_policy do |p|
+ p.default_src :self, :https
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ root to: "pages#index"
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_policy "default-src 'self' https:"
+ end
+
+ test "global report only content security policy in an initializer" do
+ controller :pages, <<-RUBY
+ class PagesController < ApplicationController
+ def index
+ render html: "<h1>Welcome to Rails!</h1>"
+ end
+ end
+ RUBY
+
+ app_file "config/initializers/content_security_policy.rb", <<-RUBY
+ Rails.application.config.content_security_policy do |p|
+ p.default_src :self, :https
+ end
+
+ Rails.application.config.content_security_policy_report_only = true
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ root to: "pages#index"
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_policy "default-src 'self' https:", report_only: true
+ end
+
+ test "override content security policy in a controller" do
+ controller :pages, <<-RUBY
+ class PagesController < ApplicationController
+ content_security_policy do |p|
+ p.default_src "https://example.com"
+ end
+
+ def index
+ render html: "<h1>Welcome to Rails!</h1>"
+ end
+ end
+ RUBY
+
+ app_file "config/initializers/content_security_policy.rb", <<-RUBY
+ Rails.application.config.content_security_policy do |p|
+ p.default_src :self, :https
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ root to: "pages#index"
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_policy "default-src https://example.com"
+ end
+
+ test "override content security policy to report only in a controller" do
+ controller :pages, <<-RUBY
+ class PagesController < ApplicationController
+ content_security_policy_report_only
+
+ def index
+ render html: "<h1>Welcome to Rails!</h1>"
+ end
+ end
+ RUBY
+
+ app_file "config/initializers/content_security_policy.rb", <<-RUBY
+ Rails.application.config.content_security_policy do |p|
+ p.default_src :self, :https
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ root to: "pages#index"
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_policy "default-src 'self' https:", report_only: true
+ end
+
+ test "global content security policy added to rack app" do
+ app_file "config/initializers/content_security_policy.rb", <<-RUBY
+ Rails.application.config.content_security_policy do |p|
+ p.default_src :self, :https
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+
+ app = ->(env) {
+ [200, { "Content-Type" => "text/html" }, ["<p>Hello, World!</p>"]]
+ }
+
+ root to: app
+ end
+ RUBY
+
+ app("development")
+
+ get "/"
+ assert_policy "default-src 'self' https:"
+ end
+
+ private
+
+ def assert_policy(expected, report_only: false)
+ assert_equal 200, last_response.status
+
+ if report_only
+ expected_header = "Content-Security-Policy-Report-Only"
+ unexpected_header = "Content-Security-Policy"
+ else
+ expected_header = "Content-Security-Policy"
+ unexpected_header = "Content-Security-Policy-Report-Only"
+ end
+
+ assert_nil last_response.headers[unexpected_header]
+ assert_equal expected, last_response.headers[expected_header]
+ end
+ end
+end
diff --git a/railties/test/application/current_attributes_integration_test.rb b/railties/test/application/current_attributes_integration_test.rb
index 5653ec0be1..146e96facc 100644
--- a/railties/test/application/current_attributes_integration_test.rb
+++ b/railties/test/application/current_attributes_integration_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -37,6 +39,8 @@ class CurrentAttributesIntegrationTest < ActiveSupport::TestCase
app_file "app/controllers/customers_controller.rb", <<-RUBY
class CustomersController < ApplicationController
+ layout false
+
def set_current_customer
Current.customer = Customer.new("david")
render :index
diff --git a/railties/test/application/dbconsole_test.rb b/railties/test/application/dbconsole_test.rb
index 12d1cfb089..8eb293c179 100644
--- a/railties/test/application/dbconsole_test.rb
+++ b/railties/test/application/dbconsole_test.rb
@@ -1,12 +1,12 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
-begin
- require "pty"
-rescue LoadError
-end
+require "console_helpers"
module ApplicationTests
class DBConsoleTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
+ include ConsoleHelpers
def setup
skip "PTY unavailable" unless available_pty?
@@ -19,21 +19,19 @@ module ApplicationTests
end
def test_use_value_defined_in_environment_file_in_database_yml
- 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
+ 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
master, slave = PTY.open
spawn_dbconsole(slave)
@@ -43,28 +41,26 @@ module ApplicationTests
end
def test_respect_environment_option
- Dir.chdir(app_path) do
- app_file "config/database.yml", <<-YAML
- default: &default
- adapter: sqlite3
- pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
- timeout: 5000
+ app_file "config/database.yml", <<-YAML
+ default: &default
+ adapter: sqlite3
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+ timeout: 5000
- development:
- <<: *default
- database: db/development.sqlite3
+ development:
+ <<: *default
+ database: db/development.sqlite3
- production:
- <<: *default
- database: db/production.sqlite3
- YAML
- end
+ production:
+ <<: *default
+ database: db/production.sqlite3
+ YAML
master, slave = PTY.open
spawn_dbconsole(slave, "-e production")
assert_output("sqlite>", master)
- master.puts ".databases"
+ master.puts "pragma database_list;"
assert_output("production.sqlite3", master)
ensure
master.puts ".exit"
@@ -74,22 +70,5 @@ module ApplicationTests
def spawn_dbconsole(fd, options = nil)
Process.spawn("#{app_path}/bin/rails dbconsole #{options}", 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/generators_test.rb b/railties/test/application/generators_test.rb
index fe581db286..e5e557d204 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -29,7 +31,7 @@ module ApplicationTests
end
test "allow running plugin new generator inside Rails app directory" do
- FileUtils.cd(rails_root) { `ruby bin/rails plugin new vendor/plugins/bukkits` }
+ rails "plugin", "new", "vendor/plugins/bukkits"
assert File.exist?(File.join(rails_root, "vendor/plugins/bukkits/test/dummy/config/application.rb"))
end
@@ -165,13 +167,14 @@ module ApplicationTests
config.api_only = true
RUBY
- FileUtils.cd(rails_root) { `bin/rails generate mailer notifier foo` }
+ rails "generate", "mailer", "notifier", "foo"
assert File.exist?(File.join(rails_root, "app/views/notifier_mailer/foo.text.erb"))
assert File.exist?(File.join(rails_root, "app/views/notifier_mailer/foo.html.erb"))
end
test "ARGV is mutated as expected" do
require "#{app_path}/config/environment"
+ require "rails/command"
Rails::Command.const_set("APP_PATH", "rails/all")
FileUtils.cd(rails_root) do
@@ -185,12 +188,13 @@ module ApplicationTests
Rails::Command.send(:remove_const, "APP_PATH")
end
- test "help does not show hidden namespaces" do
+ test "help does not show hidden namespaces and hidden commands" do
FileUtils.cd(rails_root) do
- output = `bin/rails generate --help`
+ output = rails("generate", "--help")
assert_no_match "active_record:migration", output
+ assert_no_match "credentials", output
- output = `bin/rails destroy --help`
+ output = rails("destroy", "--help")
assert_no_match "active_record:migration", output
end
end
diff --git a/railties/test/application/help_test.rb b/railties/test/application/help_test.rb
index 0c3fe8bfa3..f728fc3b85 100644
--- a/railties/test/application/help_test.rb
+++ b/railties/test/application/help_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
class HelpTest < ActiveSupport::TestCase
@@ -12,12 +14,12 @@ class HelpTest < ActiveSupport::TestCase
end
test "command works" do
- output = Dir.chdir(app_path) { `bin/rails help` }
+ output = rails("help")
assert_match "The most common rails commands are", output
end
test "short-cut alias works" do
- output = Dir.chdir(app_path) { `bin/rails -h` }
+ output = rails("-h")
assert_match "The most common rails commands are", output
end
end
diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb
index eb2c578f91..1530ea82d6 100644
--- a/railties/test/application/initializers/frameworks_test.rb
+++ b/railties/test/application/initializers/frameworks_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -209,26 +211,22 @@ module ApplicationTests
test "database middleware doesn't initialize when activerecord is not in frameworks" do
use_frameworks []
require "#{app_path}/config/environment"
- assert_nil defined?(ActiveRecord::Base)
+ assert !defined?(ActiveRecord::Base) || ActiveRecord.autoload?(:Base)
end
test "use schema cache dump" do
- Dir.chdir(app_path) do
- `rails generate model post title:string;
- bin/rails db:migrate db:schema:cache:dump`
- end
+ rails %w(generate model post title:string)
+ rails %w(db:migrate db:schema:cache:dump)
require "#{app_path}/config/environment"
ActiveRecord::Base.connection.drop_table("posts") # force drop posts table for test.
assert ActiveRecord::Base.connection.schema_cache.data_sources("posts")
end
test "expire schema cache dump" do
- Dir.chdir(app_path) do
- `rails generate model post title:string;
- bin/rails db:migrate db:schema:cache:dump db:rollback`
- end
+ rails %w(generate model post title:string)
+ rails %w(db:migrate db:schema:cache:dump db:rollback)
require "#{app_path}/config/environment"
- assert !ActiveRecord::Base.connection.schema_cache.data_sources("posts")
+ assert_not ActiveRecord::Base.connection.schema_cache.data_sources("posts")
end
test "active record establish_connection uses Rails.env if DATABASE_URL is not set" do
@@ -268,7 +266,7 @@ module ApplicationTests
ActiveRecord::Base.connection
RUBY
require "#{app_path}/config/environment"
- assert !ActiveRecord::Base.connection_pool.active_connection?
+ assert_not_predicate ActiveRecord::Base.connection_pool, :active_connection?
end
end
end
diff --git a/railties/test/application/initializers/hooks_test.rb b/railties/test/application/initializers/hooks_test.rb
index 36926c50ff..1e130c2f9e 100644
--- a/railties/test/application/initializers/hooks_test.rb
+++ b/railties/test/application/initializers/hooks_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb
index cee198bd01..8058052771 100644
--- a/railties/test/application/initializers/i18n_test.rb
+++ b/railties/test/application/initializers/i18n_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb
index dbefb22837..78cd4776d6 100644
--- a/railties/test/application/initializers/load_path_test.rb
+++ b/railties/test/application/initializers/load_path_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/initializers/notifications_test.rb b/railties/test/application/initializers/notifications_test.rb
index b847ac6b36..c65c955734 100644
--- a/railties/test/application/initializers/notifications_test.rb
+++ b/railties/test/application/initializers/notifications_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -30,6 +32,7 @@ module ApplicationTests
logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
ActiveRecord::Base.logger = logger
+ ActiveRecord::Base.verbose_query_logs = false
# Mimic Active Record notifications
instrument "sql.active_record", name: "SQL", sql: "SHOW tables"
diff --git a/railties/test/application/integration_test_case_test.rb b/railties/test/application/integration_test_case_test.rb
index 1118e5037a..c08761092b 100644
--- a/railties/test/application/integration_test_case_test.rb
+++ b/railties/test/application/integration_test_case_test.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "env_helpers"
module ApplicationTests
class IntegrationTestCaseTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
setup do
build_app
@@ -13,7 +16,7 @@ module ApplicationTests
end
test "resets Action Mailer test deliveries" do
- script("generate mailer BaseMailer welcome")
+ rails "generate", "mailer", "BaseMailer", "welcome"
app_file "test/integration/mailer_integration_test.rb", <<-RUBY
require 'test_helper'
@@ -37,14 +40,14 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails test 2>&1` }
- assert_equal 0, $?.to_i, output
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/0 failures, 0 errors/, output)
end
end
class IntegrationTestDefaultApp < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
setup do
build_app
@@ -65,8 +68,8 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails test 2>&1` }
- assert_equal 0, $?.to_i, output
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/0 failures, 0 errors/, output)
end
end
diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb
index c75a25bc6f..889ad16fb8 100644
--- a/railties/test/application/loading_test.rb
+++ b/railties/test/application/loading_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
class LoadingTest < ActiveSupport::TestCase
@@ -115,11 +117,11 @@ class LoadingTest < ActiveSupport::TestCase
require "#{rails_root}/config/environment"
setup_ar!
- assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata], ActiveRecord::Base.descendants
+ assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort
get "/load"
- assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, Post], ActiveRecord::Base.descendants
+ assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort
get "/unload"
- assert_equal [ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata], ActiveRecord::Base.descendants
+ assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort
end
test "initialize cant be called twice" do
@@ -298,7 +300,7 @@ class LoadingTest < ActiveSupport::TestCase
end
MIGRATION
- Dir.chdir(app_path) { `rake db:migrate` }
+ rails("db:migrate")
require "#{rails_root}/config/environment"
get "/title"
@@ -312,7 +314,7 @@ class LoadingTest < ActiveSupport::TestCase
end
MIGRATION
- Dir.chdir(app_path) { `rake db:migrate` }
+ rails("db:migrate")
get "/body"
assert_equal "BODY", last_response.body
@@ -350,11 +352,23 @@ class LoadingTest < ActiveSupport::TestCase
def test_initialize_can_be_called_at_any_time
require "#{app_path}/config/application"
- assert !Rails.initialized?
- assert !Rails.application.initialized?
+ assert_not_predicate Rails, :initialized?
+ assert_not_predicate Rails.application, :initialized?
Rails.initialize!
- assert Rails.initialized?
- assert Rails.application.initialized?
+ assert_predicate Rails, :initialized?
+ assert_predicate Rails.application, :initialized?
+ end
+
+ test "frameworks aren't loaded during initialization" do
+ app_file "config/initializers/raise_when_frameworks_load.rb", <<-RUBY
+ %i(action_controller action_mailer active_job active_record).each do |framework|
+ ActiveSupport.on_load(framework) { raise "\#{framework} loaded!" }
+ end
+ RUBY
+
+ assert_nothing_raised do
+ require "#{app_path}/config/environment"
+ end
end
private
diff --git a/railties/test/application/mailer_previews_test.rb b/railties/test/application/mailer_previews_test.rb
index f5c013dab6..ba186bda44 100644
--- a/railties/test/application/mailer_previews_test.rb
+++ b/railties/test/application/mailer_previews_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "base64"
@@ -30,7 +32,7 @@ module ApplicationTests
test "/rails/mailers is accessible with correct configuration" do
add_to_config "config.action_mailer.show_previews = true"
app("production")
- get "/rails/mailers", {}, "REMOTE_ADDR" => "4.2.42.42"
+ get "/rails/mailers", {}, { "REMOTE_ADDR" => "4.2.42.42" }
assert_equal 200, last_response.status
end
@@ -294,7 +296,7 @@ module ApplicationTests
test "mailer preview not found" do
app("development")
get "/rails/mailers/notifier"
- assert last_response.not_found?
+ assert_predicate last_response, :not_found?
assert_match "Mailer preview &#39;notifier&#39; not found", last_response.body
end
@@ -324,7 +326,7 @@ module ApplicationTests
app("development")
get "/rails/mailers/notifier/bar"
- assert last_response.not_found?
+ assert_predicate last_response, :not_found?
assert_match "Email &#39;bar&#39; not found in NotifierPreview", last_response.body
end
@@ -380,7 +382,7 @@ module ApplicationTests
app("development")
get "/rails/mailers/notifier/foo?part=text%2Fhtml"
- assert last_response.not_found?
+ assert_predicate last_response, :not_found?
assert_match "Email part &#39;text/html&#39; not found in NotifierPreview#foo", last_response.body
end
@@ -448,11 +450,67 @@ module ApplicationTests
get "/rails/mailers/notifier/foo.html"
assert_equal 200, last_response.status
- assert_match '<option selected value="?part=text%2Fhtml">View as HTML email</option>', last_response.body
+ assert_match '<option selected value="part=text%2Fhtml">View as HTML email</option>', last_response.body
get "/rails/mailers/notifier/foo.txt"
assert_equal 200, last_response.status
- assert_match '<option selected value="?part=text%2Fplain">View as plain-text email</option>', last_response.body
+ assert_match '<option selected value="part=text%2Fplain">View as plain-text email</option>', last_response.body
+ end
+
+ test "locale menu selects correct option" do
+ app_file "config/initializers/available_locales.rb", <<-RUBY
+ Rails.application.configure do
+ config.i18n.available_locales = %i[en ja]
+ end
+ RUBY
+
+ mailer "notifier", <<-RUBY
+ class Notifier < ActionMailer::Base
+ default from: "from@example.com"
+
+ def foo
+ mail to: "to@example.org"
+ end
+ end
+ RUBY
+
+ html_template "notifier/foo", <<-RUBY
+ <p>Hello, World!</p>
+ RUBY
+
+ text_template "notifier/foo", <<-RUBY
+ Hello, World!
+ RUBY
+
+ mailer_preview "notifier", <<-RUBY
+ class NotifierPreview < ActionMailer::Preview
+ def foo
+ Notifier.foo
+ end
+ end
+ RUBY
+
+ app("development")
+
+ get "/rails/mailers/notifier/foo.html"
+ assert_equal 200, last_response.status
+ assert_match '<option selected value="locale=en">en', last_response.body
+ assert_match '<option value="locale=ja">ja', last_response.body
+
+ get "/rails/mailers/notifier/foo.html?locale=ja"
+ assert_equal 200, last_response.status
+ assert_match '<option value="locale=en">en', last_response.body
+ assert_match '<option selected value="locale=ja">ja', last_response.body
+
+ get "/rails/mailers/notifier/foo.txt"
+ assert_equal 200, last_response.status
+ assert_match '<option selected value="locale=en">en', last_response.body
+ assert_match '<option value="locale=ja">ja', last_response.body
+
+ get "/rails/mailers/notifier/foo.txt?locale=ja"
+ assert_equal 200, last_response.status
+ assert_match '<option value="locale=en">en', last_response.body
+ assert_match '<option selected value="locale=ja">ja', last_response.body
end
test "mailer previews create correct links when loaded on a subdirectory" do
@@ -480,7 +538,7 @@ module ApplicationTests
app("development")
- get "/rails/mailers", {}, "SCRIPT_NAME" => "/my_app"
+ get "/rails/mailers", {}, { "SCRIPT_NAME" => "/my_app" }
assert_match '<h3><a href="/my_app/rails/mailers/notifier">Notifier</a></h3>', last_response.body
assert_match '<li><a href="/my_app/rails/mailers/notifier/foo">foo</a></li>', last_response.body
end
@@ -518,8 +576,8 @@ module ApplicationTests
get "/rails/mailers/notifier/foo.txt"
assert_equal 200, last_response.status
assert_match '<iframe seamless name="messageBody" src="?part=text%2Fplain">', last_response.body
- assert_match '<option selected value="?part=text%2Fplain">', last_response.body
- assert_match '<option value="?part=text%2Fhtml">', last_response.body
+ assert_match '<option selected value="part=text%2Fplain">', last_response.body
+ assert_match '<option value="part=text%2Fhtml">', last_response.body
get "/rails/mailers/notifier/foo?part=text%2Fplain"
assert_equal 200, last_response.status
@@ -528,8 +586,8 @@ module ApplicationTests
get "/rails/mailers/notifier/foo.html?name=Ruby"
assert_equal 200, last_response.status
assert_match '<iframe seamless name="messageBody" src="?name=Ruby&amp;part=text%2Fhtml">', last_response.body
- assert_match '<option selected value="?name=Ruby&amp;part=text%2Fhtml">', last_response.body
- assert_match '<option value="?name=Ruby&amp;part=text%2Fplain">', last_response.body
+ assert_match '<option selected value="name=Ruby&amp;part=text%2Fhtml">', last_response.body
+ assert_match '<option value="name=Ruby&amp;part=text%2Fplain">', last_response.body
get "/rails/mailers/notifier/foo?name=Ruby&part=text%2Fhtml"
assert_equal 200, last_response.status
diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb
index 93b5263bf7..3768d8ce2d 100644
--- a/railties/test/application/middleware/cache_test.rb
+++ b/railties/test/application/middleware/cache_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -54,7 +56,7 @@ module ApplicationTests
simple_controller
expected = "Wed, 30 May 1984 19:43:31 GMT"
- get "/expires/keeps_if_modified_since", {}, "HTTP_IF_MODIFIED_SINCE" => expected
+ get "/expires/keeps_if_modified_since", {}, { "HTTP_IF_MODIFIED_SINCE" => expected }
assert_equal 200, last_response.status
assert_equal expected, last_response.body, "cache should have kept If-Modified-Since"
@@ -119,7 +121,7 @@ module ApplicationTests
etag = last_response.headers["ETag"]
- get "/expires/expires_etag", {}, "HTTP_IF_NONE_MATCH" => etag
+ get "/expires/expires_etag", {}, { "HTTP_IF_NONE_MATCH" => etag }
assert_equal "stale, valid, store", last_response.headers["X-Rack-Cache"]
assert_equal 304, last_response.status
assert_equal "", last_response.body
@@ -137,8 +139,8 @@ module ApplicationTests
body = last_response.body
etag = last_response.headers["ETag"]
- get "/expires/expires_etag", { private: true }, "HTTP_IF_NONE_MATCH" => etag
- assert_equal "miss", last_response.headers["X-Rack-Cache"]
+ get "/expires/expires_etag", { private: true }, { "HTTP_IF_NONE_MATCH" => etag }
+ assert_equal "miss", last_response.headers["X-Rack-Cache"]
assert_not_equal body, last_response.body
end
@@ -153,7 +155,7 @@ module ApplicationTests
last = last_response.headers["Last-Modified"]
- get "/expires/expires_last_modified", {}, "HTTP_IF_MODIFIED_SINCE" => last
+ get "/expires/expires_last_modified", {}, { "HTTP_IF_MODIFIED_SINCE" => last }
assert_equal "stale, valid, store", last_response.headers["X-Rack-Cache"]
assert_equal 304, last_response.status
assert_equal "", last_response.body
@@ -171,8 +173,8 @@ module ApplicationTests
body = last_response.body
last = last_response.headers["Last-Modified"]
- get "/expires/expires_last_modified", { private: true }, "HTTP_IF_MODIFIED_SINCE" => last
- assert_equal "miss", last_response.headers["X-Rack-Cache"]
+ get "/expires/expires_last_modified", { private: true }, { "HTTP_IF_MODIFIED_SINCE" => last }
+ assert_equal "miss", last_response.headers["X-Rack-Cache"]
assert_not_equal body, last_response.body
end
end
diff --git a/railties/test/application/middleware/cookies_test.rb b/railties/test/application/middleware/cookies_test.rb
index 1e4b5d086c..ecb4ee3446 100644
--- a/railties/test/application/middleware/cookies_test.rb
+++ b/railties/test/application/middleware/cookies_test.rb
@@ -1,8 +1,12 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "rack/test"
module ApplicationTests
class CookiesTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
+ include Rack::Test::Methods
def new_app
File.expand_path("#{app_path}/../new_app")
@@ -13,6 +17,10 @@ module ApplicationTests
FileUtils.rm_rf("#{app_path}/config/environments")
end
+ def app
+ Rails.application
+ end
+
def teardown
teardown_app
FileUtils.rm_rf(new_app) if File.directory?(new_app)
@@ -42,5 +50,144 @@ module ApplicationTests
require "#{app_path}/config/environment"
assert_equal false, ActionDispatch::Cookies::CookieJar.always_write_cookie
end
+
+ test "signed cookies with SHA512 digest and rotated out SHA256 and SHA1 digests" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get ':controller(/:action)'
+ post ':controller(/:action)'
+ end
+ RUBY
+
+ controller :foo, <<-RUBY
+ class FooController < ActionController::Base
+ protect_from_forgery with: :null_session
+
+ def write_raw_cookie_sha1
+ cookies[:signed_cookie] = TestVerifiers.sha1.generate("signed cookie")
+ head :ok
+ end
+
+ def write_raw_cookie_sha256
+ cookies[:signed_cookie] = TestVerifiers.sha256.generate("signed cookie")
+ head :ok
+ end
+
+ def read_signed
+ render plain: cookies.signed[:signed_cookie].inspect
+ end
+
+ def read_raw_cookie
+ render plain: cookies[:signed_cookie]
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ sha1_secret = Rails.application.key_generator.generate_key("sha1")
+ sha256_secret = Rails.application.key_generator.generate_key("sha256")
+
+ ::TestVerifiers = Class.new do
+ class_attribute :sha1, default: ActiveSupport::MessageVerifier.new(sha1_secret, digest: "SHA1")
+ class_attribute :sha256, default: ActiveSupport::MessageVerifier.new(sha256_secret, digest: "SHA256")
+ end
+
+ config.action_dispatch.signed_cookie_digest = "SHA512"
+ config.action_dispatch.signed_cookie_salt = "sha512 salt"
+
+ config.action_dispatch.cookies_rotations.tap do |cookies|
+ cookies.rotate :signed, sha1_secret, digest: "SHA1"
+ cookies.rotate :signed, sha256_secret, digest: "SHA256"
+ end
+ RUBY
+
+ require "#{app_path}/config/environment"
+
+ verifier_sha512 = ActiveSupport::MessageVerifier.new(app.key_generator.generate_key("sha512 salt"), digest: :SHA512)
+
+ get "/foo/write_raw_cookie_sha1"
+ get "/foo/read_signed"
+ assert_equal "signed cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "signed cookie", verifier_sha512.verify(last_response.body)
+
+ get "/foo/write_raw_cookie_sha256"
+ get "/foo/read_signed"
+ assert_equal "signed cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "signed cookie", verifier_sha512.verify(last_response.body)
+ end
+
+ test "encrypted cookies rotating multiple encryption keys" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get ':controller(/:action)'
+ post ':controller(/:action)'
+ end
+ RUBY
+
+ controller :foo, <<-RUBY
+ class FooController < ActionController::Base
+ protect_from_forgery with: :null_session
+
+ def write_raw_cookie_one
+ cookies[:encrypted_cookie] = TestEncryptors.first_gcm.encrypt_and_sign("encrypted cookie")
+ head :ok
+ end
+
+ def write_raw_cookie_two
+ cookies[:encrypted_cookie] = TestEncryptors.second_gcm.encrypt_and_sign("encrypted cookie")
+ head :ok
+ end
+
+ def read_encrypted
+ render plain: cookies.encrypted[:encrypted_cookie].inspect
+ end
+
+ def read_raw_cookie
+ render plain: cookies[:encrypted_cookie]
+ end
+ end
+ RUBY
+
+ add_to_config <<-RUBY
+ first_secret = Rails.application.key_generator.generate_key("first", 32)
+ second_secret = Rails.application.key_generator.generate_key("second", 32)
+
+ ::TestEncryptors = Class.new do
+ class_attribute :first_gcm, default: ActiveSupport::MessageEncryptor.new(first_secret, cipher: "aes-256-gcm")
+ class_attribute :second_gcm, default: ActiveSupport::MessageEncryptor.new(second_secret, cipher: "aes-256-gcm")
+ end
+
+ config.action_dispatch.use_authenticated_cookie_encryption = true
+ config.action_dispatch.encrypted_cookie_cipher = "aes-256-gcm"
+ config.action_dispatch.authenticated_encrypted_cookie_salt = "salt"
+
+ config.action_dispatch.cookies_rotations.tap do |cookies|
+ cookies.rotate :encrypted, first_secret
+ cookies.rotate :encrypted, second_secret
+ end
+ RUBY
+
+ require "#{app_path}/config/environment"
+
+ encryptor = ActiveSupport::MessageEncryptor.new(app.key_generator.generate_key("salt", 32), cipher: "aes-256-gcm")
+
+ get "/foo/write_raw_cookie_one"
+ get "/foo/read_encrypted"
+ assert_equal "encrypted cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "encrypted cookie", encryptor.decrypt_and_verify(last_response.body)
+
+ get "/foo/write_raw_cookie_sha256"
+ get "/foo/read_encrypted"
+ assert_equal "encrypted cookie".inspect, last_response.body
+
+ get "/foo/read_raw_cookie"
+ assert_equal "encrypted cookie", encryptor.decrypt_and_verify(last_response.body)
+ end
end
end
diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb
index fe07ad3cbe..2d659ade8d 100644
--- a/railties/test/application/middleware/exceptions_test.rb
+++ b/railties/test/application/middleware/exceptions_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -100,7 +102,7 @@ module ApplicationTests
end
end
- test "routing to an nonexistent controller when action_dispatch.show_exceptions and consider_all_requests_local are set shows diagnostics" do
+ test "routing to a nonexistent controller when action_dispatch.show_exceptions and consider_all_requests_local are set shows diagnostics" do
app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do
resources :articles
diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb
index c34d9d6ee7..83cf8a27f7 100644
--- a/railties/test/application/middleware/remote_ip_test.rb
+++ b/railties/test/application/middleware/remote_ip_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "ipaddr"
require "isolation/abstract_unit"
require "active_support/key_generator"
diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb
index 4938402fdc..818ad61c64 100644
--- a/railties/test/application/middleware/sendfile_test.rb
+++ b/railties/test/application/middleware/sendfile_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -13,10 +15,6 @@ module ApplicationTests
teardown_app
end
- def app
- @app ||= Rails.application
- end
-
define_method :simple_controller do
class ::OmgController < ActionController::Base
def index
@@ -31,7 +29,7 @@ module ApplicationTests
simple_controller
get "/"
- assert !last_response.headers["X-Sendfile"]
+ assert_not last_response.headers["X-Sendfile"]
assert_equal File.read(__FILE__), last_response.body
end
diff --git a/railties/test/application/middleware/session_test.rb b/railties/test/application/middleware/session_test.rb
index a14ea589ed..9182a63ab7 100644
--- a/railties/test/application/middleware/session_test.rb
+++ b/railties/test/application/middleware/session_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -29,7 +31,7 @@ module ApplicationTests
add_to_config "config.force_ssl = true"
add_to_config "config.ssl_options = { secure_cookies: false }"
require "#{app_path}/config/environment"
- assert !app.config.session_options[:secure]
+ assert_not app.config.session_options[:secure]
end
test "session is not loaded if it's not used" do
@@ -49,7 +51,7 @@ module ApplicationTests
get "/"
assert last_request.env["HTTP_COOKIE"]
- assert !last_response.headers["Set-Cookie"]
+ assert_not last_response.headers["Set-Cookie"]
end
test "session is empty and isn't saved on unverified request when using :null_session protect method" do
@@ -335,31 +337,37 @@ module ApplicationTests
add_to_config <<-RUBY
# Use a static key
- secrets.secret_key_base = "known key base"
+ Rails.application.credentials.secret_key_base = "known key base"
# Enable AEAD cookies
config.action_dispatch.use_authenticated_cookie_encryption = true
RUBY
- require "#{app_path}/config/environment"
+ begin
+ old_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "production"
- get "/foo/write_raw_session"
- get "/foo/read_session"
- assert_equal "1", last_response.body
+ require "#{app_path}/config/environment"
- get "/foo/write_session"
- get "/foo/read_session"
- assert_equal "2", last_response.body
+ get "/foo/write_raw_session"
+ get "/foo/read_session"
+ assert_equal "1", last_response.body
- get "/foo/read_encrypted_cookie"
- assert_equal "2", last_response.body
+ get "/foo/write_session"
+ get "/foo/read_session"
+ assert_equal "2", last_response.body
- cipher = "aes-256-gcm"
- secret = app.key_generator.generate_key("authenticated encrypted cookie")
- encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher)
+ get "/foo/read_encrypted_cookie"
+ assert_equal "2", last_response.body
- get "/foo/read_raw_cookie"
- assert_equal 2, encryptor.decrypt_and_verify(last_response.body)["foo"]
+ cipher = "aes-256-gcm"
+ secret = app.key_generator.generate_key("authenticated encrypted cookie")
+ encryptor = ActiveSupport::MessageEncryptor.new(secret[0, ActiveSupport::MessageEncryptor.key_len(cipher)], cipher: cipher)
+
+ get "/foo/read_raw_cookie"
+ assert_equal 2, encryptor.decrypt_and_verify(last_response.body)["foo"]
+ ensure
+ ENV["RAILS_ENV"] = old_rails_env
+ end
end
test "session upgrading legacy signed cookies to new signed cookies" do
@@ -398,26 +406,32 @@ module ApplicationTests
add_to_config <<-RUBY
secrets.secret_token = "3b7cd727ee24e8444053437c36cc66c4"
- secrets.secret_key_base = nil
+ Rails.application.credentials.secret_key_base = nil
RUBY
- require "#{app_path}/config/environment"
+ begin
+ old_rails_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "production"
- get "/foo/write_raw_session"
- get "/foo/read_session"
- assert_equal "1", last_response.body
+ require "#{app_path}/config/environment"
- get "/foo/write_session"
- get "/foo/read_session"
- assert_equal "2", last_response.body
+ get "/foo/write_raw_session"
+ get "/foo/read_session"
+ assert_equal "1", last_response.body
- get "/foo/read_signed_cookie"
- assert_equal "2", last_response.body
+ get "/foo/write_session"
+ get "/foo/read_session"
+ assert_equal "2", last_response.body
- verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token)
+ get "/foo/read_signed_cookie"
+ assert_equal "2", last_response.body
- get "/foo/read_raw_cookie"
- assert_equal 2, verifier.verify(last_response.body)["foo"]
+ verifier = ActiveSupport::MessageVerifier.new(app.secrets.secret_token)
+
+ get "/foo/read_raw_cookie"
+ assert_equal 2, verifier.verify(last_response.body)["foo"]
+ ensure
+ ENV["RAILS_ENV"] = old_rails_env
+ end
end
test "calling reset_session on request does not trigger an error for API apps" do
diff --git a/railties/test/application/middleware/static_test.rb b/railties/test/application/middleware/static_test.rb
index 5cd3e4325e..0977042cfe 100644
--- a/railties/test/application/middleware/static_test.rb
+++ b/railties/test/application/middleware/static_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 0a6e5b52e9..5efaf841d4 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -40,9 +42,11 @@ module ApplicationTests
"ActionDispatch::Cookies",
"ActionDispatch::Session::CookieStore",
"ActionDispatch::Flash",
+ "ActionDispatch::ContentSecurityPolicy::Middleware",
"Rack::Head",
"Rack::ConditionalGet",
- "Rack::ETag"
+ "Rack::ETag",
+ "Rack::TempfileReaper"
], middleware
end
@@ -246,7 +250,7 @@ module ApplicationTests
test "can't change middleware after it's built" do
boot!
- assert_raise RuntimeError do
+ assert_raise frozen_error_class do
app.config.middleware.use Rack::Config
end
end
@@ -274,7 +278,7 @@ module ApplicationTests
assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"]
assert_equal etag, last_response.headers["Etag"]
- get "/", {}, "HTTP_IF_NONE_MATCH" => etag
+ get "/", {}, { "HTTP_IF_NONE_MATCH" => etag }
assert_equal 304, last_response.status
assert_equal "", last_response.body
assert_nil last_response.headers["Content-Type"]
diff --git a/railties/test/application/multiple_applications_test.rb b/railties/test/application/multiple_applications_test.rb
index 26b810af73..d6c81c1fe2 100644
--- a/railties/test/application/multiple_applications_test.rb
+++ b/railties/test/application/multiple_applications_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb
index 515205296c..0abc5cc9aa 100644
--- a/railties/test/application/paths_test.rb
+++ b/railties/test/application/paths_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/per_request_digest_cache_test.rb b/railties/test/application/per_request_digest_cache_test.rb
index 6e6996a6ba..10d3313f6e 100644
--- a/railties/test/application/per_request_digest_cache_test.rb
+++ b/railties/test/application/per_request_digest_cache_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
require "minitest/mock"
@@ -57,7 +59,7 @@ class PerRequestDigestCacheTest < ActiveSupport::TestCase
assert_equal 200, last_response.status
values = ActionView::LookupContext::DetailsKey.digest_caches.first.values
- assert_equal [ "8ba099b7749542fe765ff34a6824d548" ], values
+ assert_equal [ "effc8928d0b33535c8a21d24ec617161" ], values
assert_equal %w(david dingus), last_response.body.split.map(&:strip)
end
diff --git a/railties/test/application/rack/logger_test.rb b/railties/test/application/rack/logger_test.rb
index e71bcbc536..d949a48366 100644
--- a/railties/test/application/rack/logger_test.rb
+++ b/railties/test/application/rack/logger_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "active_support/log_subscriber/test_helper"
require "rack/test"
diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb
index 2943e9ee5d..383f18a7da 100644
--- a/railties/test/application/rackup_test.rb
+++ b/railties/test/application/rackup_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb
index c63f23fa0a..0594236b1f 100644
--- a/railties/test/application/rake/dbs_test.rb
+++ b/railties/test/application/rake/dbs_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -24,15 +26,15 @@ module ApplicationTests
FileUtils.rm_rf("#{app_path}/config/database.yml")
end
- def db_create_and_drop(expected_database)
+ def db_create_and_drop(expected_database, environment_loaded: true)
Dir.chdir(app_path) do
- output = `bin/rails db:create`
+ output = rails("db:create")
assert_match(/Created database/, output)
assert File.exist?(expected_database)
- assert_equal expected_database, ActiveRecord::Base.connection_config[:database]
- output = `bin/rails db:drop`
+ assert_equal expected_database, ActiveRecord::Base.connection_config[:database] if environment_loaded
+ output = rails("db:drop")
assert_match(/Dropped database/, output)
- assert !File.exist?(expected_database)
+ assert_not File.exist?(expected_database)
end
end
@@ -47,20 +49,35 @@ module ApplicationTests
db_create_and_drop database_url_db_name
end
+ test "db:create and db:drop respect environment setting" 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
+ end
+
def with_database_existing
Dir.chdir(app_path) do
set_database_url
- `bin/rails db:create`
+ rails "db:create"
yield
- `bin/rails db:drop`
+ rails "db:drop"
end
end
test "db:create failure because database exists" do
with_database_existing do
- output = `bin/rails db:create 2>&1`
+ output = rails("db:create")
assert_match(/already exists/, output)
- assert_equal 0, $?.exitstatus
end
end
@@ -75,24 +92,35 @@ module ApplicationTests
test "db:create failure because bad permissions" do
with_bad_permissions do
- output = `bin/rails db:create 2>&1`
+ output = rails("db:create", allow_failure: true)
assert_match(/Couldn't create database/, output)
assert_equal 1, $?.exitstatus
end
end
- test "db:drop failure because database does not exist" do
- Dir.chdir(app_path) do
- output = `bin/rails db:drop:_unsafe --trace 2>&1`
- assert_match(/does not exist/, output)
+ test "db:create works when schema cache exists and database does not exist" do
+ use_postgresql
+
+ begin
+ rails %w(db:create db:migrate db:schema:cache:dump)
+
+ rails "db:drop"
+ rails "db:create"
assert_equal 0, $?.exitstatus
+ ensure
+ rails "db:drop" rescue nil
end
end
+ test "db:drop failure because database does not exist" do
+ output = rails("db:drop:_unsafe", "--trace")
+ assert_match(/does not exist/, output)
+ end
+
test "db:drop failure because bad permissions" do
with_database_existing do
with_bad_permissions do
- output = `bin/rails db:drop 2>&1`
+ output = rails("db:drop", allow_failure: true)
assert_match(/Couldn't drop/, output)
assert_equal 1, $?.exitstatus
end
@@ -100,13 +128,11 @@ module ApplicationTests
end
def db_migrate_and_status(expected_database)
- Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate`
- output = `bin/rails db:migrate:status`
- assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output)
- assert_match(/up\s+\d{14}\s+Create books/, output)
- end
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate"
+ output = rails("db:migrate:status")
+ assert_match(%r{database:\s+\S*#{Regexp.escape(expected_database)}}, output)
+ assert_match(/up\s+\d{14}\s+Create books/, output)
end
test "db:migrate and db:migrate:status without database_url" do
@@ -122,8 +148,8 @@ module ApplicationTests
def db_schema_dump
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:schema:dump`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:schema:dump"
schema_dump = File.read("db/schema.rb")
assert_match(/create_table \"books\"/, schema_dump)
end
@@ -140,8 +166,8 @@ module ApplicationTests
def db_fixtures_load(expected_database)
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:fixtures:load`
+ rails "generate", "model", "book", "title:string"
+ 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
@@ -161,24 +187,23 @@ module ApplicationTests
test "db:fixtures:load with namespaced fixture" do
require "#{app_path}/config/environment"
- Dir.chdir(app_path) do
- `bin/rails generate model admin::book title:string;
- bin/rails db:migrate db:fixtures:load`
- require "#{app_path}/app/models/admin/book"
- assert_equal 2, Admin::Book.count
- end
+
+ rails "generate", "model", "admin::book", "title:string"
+ rails "db:migrate", "db:fixtures:load"
+ require "#{app_path}/app/models/admin/book"
+ assert_equal 2, Admin::Book.count
end
def db_structure_dump_and_load(expected_database)
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:structure:dump`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:structure:dump"
structure_dump = File.read("db/structure.sql")
assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"books\"/, structure_dump)
- `bin/rails environment db:drop db:structure:load`
+ rails "environment", "db:drop", "db:structure:load"
assert_match expected_database, ActiveRecord::Base.connection_config[:database]
require "#{app_path}/app/models/book"
- #if structure is not loaded correctly, exception would be raised
+ # if structure is not loaded correctly, exception would be raised
assert_equal 0, Book.count
end
end
@@ -194,79 +219,86 @@ module ApplicationTests
db_structure_dump_and_load database_url_db_name
end
+ test "db:structure:dump and db:structure:load set ar_internal_metadata" do
+ require "#{app_path}/config/environment"
+ db_structure_dump_and_load ActiveRecord::Base.configurations[Rails.env]["database"]
+
+ assert_equal "test", rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip
+ assert_equal "development", rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip
+ end
+
test "db:structure:dump does not dump schema information when no migrations are used" do
- Dir.chdir(app_path) do
- # create table without migrations
- `bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'`
+ # create table without migrations
+ rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }"
- stderr_output = capture(:stderr) { `bin/rails db:structure:dump` }
- assert_empty stderr_output
- structure_dump = File.read("db/structure.sql")
- assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump)
- end
+ stderr_output = capture(:stderr) { rails("db:structure:dump", stderr: true, allow_failure: true) }
+ assert_empty stderr_output
+ structure_dump = File.read("#{app_path}/db/structure.sql")
+ assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"posts\"/, structure_dump)
end
test "db:schema:load and db:structure:load do not purge the existing database" do
- Dir.chdir(app_path) do
- `bin/rails runner 'ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }'`
+ rails "runner", "ActiveRecord::Base.connection.create_table(:posts) {|t| t.string :title }"
- app_file "db/schema.rb", <<-RUBY
- ActiveRecord::Schema.define(version: 20140423102712) do
- create_table(:comments) {}
- end
- RUBY
+ app_file "db/schema.rb", <<-RUBY
+ ActiveRecord::Schema.define(version: 20140423102712) do
+ create_table(:comments) {}
+ end
+ RUBY
- list_tables = lambda { `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip }
+ list_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip }
- assert_equal '["posts"]', list_tables[]
- `bin/rails db:schema:load`
- assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[]
+ assert_equal '["posts"]', list_tables[]
+ rails "db:schema:load"
+ assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata"]', list_tables[]
- app_file "db/structure.sql", <<-SQL
- CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
- SQL
+ app_file "db/structure.sql", <<-SQL
+ CREATE TABLE "users" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255));
+ SQL
- `bin/rails db:structure:load`
- assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[]
- end
+ rails "db:structure:load"
+ assert_equal '["posts", "comments", "schema_migrations", "ar_internal_metadata", "users"]', list_tables[]
end
test "db:schema:load with inflections" do
- Dir.chdir(app_path) do
- app_file "config/initializers/inflection.rb", <<-RUBY
- ActiveSupport::Inflector.inflections do |inflect|
- inflect.irregular 'goose', 'geese'
- end
- RUBY
- app_file "config/initializers/primary_key_table_name.rb", <<-RUBY
- ActiveRecord::Base.primary_key_prefix_type = :table_name
- RUBY
- app_file "db/schema.rb", <<-RUBY
- ActiveRecord::Schema.define(version: 20140423102712) do
- create_table("goose".pluralize) do |t|
- t.string :name
- end
+ app_file "config/initializers/inflection.rb", <<-RUBY
+ ActiveSupport::Inflector.inflections do |inflect|
+ inflect.irregular 'goose', 'geese'
+ end
+ RUBY
+ app_file "config/initializers/primary_key_table_name.rb", <<-RUBY
+ ActiveRecord::Base.primary_key_prefix_type = :table_name
+ RUBY
+ app_file "db/schema.rb", <<-RUBY
+ ActiveRecord::Schema.define(version: 20140423102712) do
+ create_table("goose".pluralize) do |t|
+ t.string :name
end
- RUBY
+ end
+ RUBY
- `bin/rails db:schema:load`
+ rails "db:schema:load"
- tables = `bin/rails runner 'p ActiveRecord::Base.connection.tables'`.strip
- assert_match(/"geese"/, tables)
+ tables = rails("runner", "p ActiveRecord::Base.connection.tables").strip
+ assert_match(/"geese"/, tables)
- columns = `bin/rails runner 'p ActiveRecord::Base.connection.columns("geese").map(&:name)'`.strip
- assert_equal columns, '["gooseid", "name"]'
- end
+ columns = rails("runner", "p ActiveRecord::Base.connection.columns('geese').map(&:name)").strip
+ assert_equal columns, '["gooseid", "name"]'
+ end
+
+ test "db:schema:load fails if schema.rb doesn't exist yet" do
+ stderr_output = capture(:stderr) { rails("db:schema:load", stderr: true, allow_failure: true) }
+ assert_match(/Run `rails db:migrate` to create it/, stderr_output)
end
def db_test_load_structure
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate db:structure:dump db:test:load_structure`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate", "db:structure:dump", "db:test:load_structure"
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
ActiveRecord::Base.establish_connection :test
require "#{app_path}/app/models/book"
- #if structure is not loaded correctly, exception would be raised
+ # if structure is not loaded correctly, exception would be raised
assert_equal 0, Book.count
assert_match ActiveRecord::Base.configurations["test"]["database"],
ActiveRecord::Base.connection_config[:database]
@@ -297,15 +329,52 @@ module ApplicationTests
puts ActiveRecord::Base.connection_config[:database]
RUBY
- Dir.chdir(app_path) do
- database_path = `bin/rails db:setup`
- assert_equal "development.sqlite3", File.basename(database_path.strip)
- end
+ database_path = rails("db:setup")
+ assert_equal "development.sqlite3", File.basename(database_path.strip)
ensure
ENV["RAILS_ENV"] = @old_rails_env
ENV["RACK_ENV"] = @old_rack_env
end
end
+
+ test "db:setup sets ar_internal_metadata" do
+ app_file "db/schema.rb", ""
+ rails "db:setup"
+
+ test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip }
+ development_environment = lambda { rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip }
+
+ assert_equal "test", test_environment.call
+ assert_equal "development", development_environment.call
+
+ app_file "db/structure.sql", ""
+ app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY
+ Rails.application.config.active_record.schema_format = :sql
+ RUBY
+
+ rails "db:setup"
+
+ assert_equal "test", test_environment.call
+ assert_equal "development", development_environment.call
+ end
+
+ test "db:test:prepare sets test ar_internal_metadata" do
+ app_file "db/schema.rb", ""
+ rails "db:test:prepare"
+
+ test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip }
+
+ assert_equal "test", test_environment.call
+
+ app_file "db/structure.sql", ""
+ app_file "config/initializers/enable_sql_schema_format.rb", <<-RUBY
+ Rails.application.config.active_record.schema_format = :sql
+ RUBY
+
+ rails "db:test:prepare"
+
+ assert_equal "test", test_environment.call
+ end
end
end
end
diff --git a/railties/test/application/rake/dev_test.rb b/railties/test/application/rake/dev_test.rb
index 4f992d9c8d..66e1ac9d99 100644
--- a/railties/test/application/rake/dev_test.rb
+++ b/railties/test/application/rake/dev_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -15,7 +17,7 @@ module ApplicationTests
test "dev:cache creates file and outputs message" do
Dir.chdir(app_path) do
- output = `rails dev:cache`
+ output = rails("dev:cache")
assert File.exist?("tmp/caching-dev.txt")
assert_match(/Development mode is now being cached/, output)
end
@@ -23,19 +25,23 @@ module ApplicationTests
test "dev:cache deletes file and outputs message" do
Dir.chdir(app_path) do
- `rails dev:cache` # Create caching file.
- output = `rails dev:cache` # Delete caching file.
+ rails "dev:cache" # Create caching file.
+ output = rails("dev:cache") # Delete caching file.
assert_not File.exist?("tmp/caching-dev.txt")
assert_match(/Development mode is no longer being cached/, output)
end
end
- test "dev:cache removes server.pid also" do
+ test "dev:cache touches tmp/restart.txt" do
Dir.chdir(app_path) do
- FileUtils.mkdir_p("tmp/pids")
- FileUtils.touch("tmp/pids/server.pid")
- `rails dev:cache`
- assert_not File.exist?("tmp/pids/server.pid")
+ rails "dev:cache"
+ assert File.exist?("tmp/restart.txt")
+
+ prev_mtime = File.mtime("tmp/restart.txt")
+ sleep(1)
+ rails "dev:cache"
+ curr_mtime = File.mtime("tmp/restart.txt")
+ assert_not_equal prev_mtime, curr_mtime
end
end
end
diff --git a/railties/test/application/rake/framework_test.rb b/railties/test/application/rake/framework_test.rb
index 40488a6aab..644b1924b5 100644
--- a/railties/test/application/rake/framework_test.rb
+++ b/railties/test/application/rake/framework_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
diff --git a/railties/test/application/rake/log_test.rb b/railties/test/application/rake/log_test.rb
index fdd3c71fe8..678f26db26 100644
--- a/railties/test/application/rake/log_test.rb
+++ b/railties/test/application/rake/log_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -21,7 +23,7 @@ module ApplicationTests
File.write("log/test.log", "test")
File.write("log/dummy.log", "dummy")
- `rails log:clear`
+ rails "log:clear"
assert_equal 0, File.size("log/test.log")
assert_equal 0, File.size("log/staging.log")
diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb
index 51dfe2ef98..bf5b07afbd 100644
--- a/railties/test/application/rake/migrations_test.rb
+++ b/railties/test/application/rake/migrations_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -13,263 +15,416 @@ module ApplicationTests
end
test "running migrations with given scope" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string`
+ rails "generate", "model", "user", "username:string", "password:string"
- app_file "db/migrate/01_a_migration.bukkits.rb", <<-MIGRATION
- class AMigration < ActiveRecord::Migration::Current
- end
- MIGRATION
+ app_file "db/migrate/01_a_migration.bukkits.rb", <<-MIGRATION
+ class AMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- output = `bin/rails db:migrate SCOPE=bukkits`
- assert_no_match(/create_table\(:users\)/, output)
- assert_no_match(/CreateUsers/, output)
- assert_no_match(/add_column\(:users, :email, :string\)/, output)
+ output = rails("db:migrate", "SCOPE=bukkits")
+ assert_no_match(/create_table\(:users\)/, output)
+ assert_no_match(/CreateUsers/, output)
+ assert_no_match(/add_column\(:users, :email, :string\)/, output)
- assert_match(/AMigration: migrated/, output)
+ assert_match(/AMigration: migrated/, output)
- output = `bin/rails db:migrate SCOPE=bukkits VERSION=0`
- assert_no_match(/drop_table\(:users\)/, output)
- assert_no_match(/CreateUsers/, output)
- assert_no_match(/remove_column\(:users, :email\)/, output)
+ # run all the migrations to test scope for down
+ output = rails("db:migrate")
+ assert_match(/CreateUsers: migrated/, output)
- assert_match(/AMigration: reverted/, output)
- end
+ output = rails("db:migrate", "SCOPE=bukkits", "VERSION=0")
+ assert_no_match(/drop_table\(:users\)/, output)
+ assert_no_match(/CreateUsers/, output)
+ assert_no_match(/remove_column\(:users, :email\)/, output)
+
+ assert_match(/AMigration: reverted/, output)
+
+ output = rails("db:migrate", "VERSION=0")
+
+ assert_match(/CreateUsers: reverted/, output)
+ end
+
+ test "version outputs current version" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:version")
+ assert_match(/Current version: 1/, output)
+ end
+
+ test "migrate with specified VERSION in different formats" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/03_three_migration.rb", <<-MIGRATION
+ class ThreeMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ assert_match(/up\s+003\s+Three migration/, output)
+
+ rails "db:migrate", "VERSION=01_one_migration.rb"
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/down\s+002\s+Two migration/, output)
+ assert_match(/down\s+003\s+Three migration/, output)
+
+ rails "db:migrate", "VERSION=3"
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ assert_match(/up\s+003\s+Three migration/, output)
+
+ rails "db:migrate", "VERSION=001"
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/down\s+002\s+Two migration/, output)
+ assert_match(/down\s+003\s+Three migration/, output)
end
test "migration with empty version" do
- Dir.chdir(app_path) do
- output = `bin/rails db:migrate VERSION= 2>&1`
- assert_match(/Empty VERSION provided/, output)
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- output = `bin/rails db:migrate:redo VERSION= 2>&1`
- assert_match(/Empty VERSION provided/, output)
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- output = `bin/rails db:migrate:up VERSION= 2>&1`
- assert_match(/VERSION is required/, output)
+ rails("db:migrate", "VERSION=")
- output = `bin/rails db:migrate:up 2>&1`
- assert_match(/VERSION is required/, output)
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
- output = `bin/rails db:migrate:down VERSION= 2>&1`
- assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
+ output = rails("db:migrate:redo", "VERSION=", allow_failure: true)
+ assert_match(/Empty VERSION provided/, output)
- output = `bin/rails db:migrate:down 2>&1`
- assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
- end
+ output = rails("db:migrate:up", "VERSION=", allow_failure: true)
+ assert_match(/VERSION is required/, output)
+
+ output = rails("db:migrate:up", allow_failure: true)
+ assert_match(/VERSION is required/, output)
+
+ output = rails("db:migrate:down", "VERSION=", allow_failure: true)
+ assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
+
+ output = rails("db:migrate:down", allow_failure: true)
+ assert_match(/VERSION is required - To go down one migration, use db:rollback/, output)
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ end
+
+ test "migration with 0 version" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+
+ rails "db:migrate", "VERSION=0"
+
+ output = rails("db:migrate:status")
+ assert_match(/down\s+001\s+One migration/, output)
+ assert_match(/down\s+002\s+Two migration/, output)
end
test "model and migration generator with change syntax" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string`
-
- output = `bin/rails db:migrate`
- assert_match(/create_table\(:users\)/, output)
- assert_match(/CreateUsers: migrated/, output)
- assert_match(/add_column\(:users, :email, :string\)/, output)
- assert_match(/AddEmailToUsers: migrated/, output)
-
- output = `bin/rails db:rollback STEP=2`
- assert_match(/drop_table\(:users\)/, output)
- assert_match(/CreateUsers: reverted/, output)
- assert_match(/remove_column\(:users, :email, :string\)/, output)
- assert_match(/AddEmailToUsers: reverted/, output)
- end
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+
+ output = rails("db:migrate")
+ assert_match(/create_table\(:users\)/, output)
+ assert_match(/CreateUsers: migrated/, output)
+ assert_match(/add_column\(:users, :email, :string\)/, output)
+ assert_match(/AddEmailToUsers: migrated/, output)
+
+ output = rails("db:rollback", "STEP=2")
+ assert_match(/drop_table\(:users\)/, output)
+ assert_match(/CreateUsers: reverted/, output)
+ assert_match(/remove_column\(:users, :email, :string\)/, output)
+ assert_match(/AddEmailToUsers: reverted/, output)
end
test "migration status when schema migrations table is not present" do
- output = Dir.chdir(app_path) { `bin/rails db:migrate:status 2>&1` }
+ output = rails("db:migrate:status", allow_failure: true)
assert_equal "Schema migrations table does not exist yet.\n", output
end
test "migration status" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=1`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=1"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/down\s+\d{14}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/down\s+\d{14}\s+Add email to users/, output)
end
test "migration status without timestamps" do
add_to_config("config.active_record.timestamped_migrations = false")
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/up\s+\d{3,}\s+Add email to users/, output)
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/up\s+\d{3,}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=1`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=1"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/down\s+\d{3,}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/down\s+\d{3,}\s+Add email to users/, output)
end
test "migration status after rollback and redo" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/down\s+\d{14}\s+Create users/, output)
- assert_match(/down\s+\d{14}\s+Add email to users/, output)
+ assert_match(/down\s+\d{14}\s+Create users/, output)
+ assert_match(/down\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:migrate:redo`
- output = `bin/rails db:migrate:status`
+ rails "db:migrate:redo"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
end
test "migration status after rollback and forward" do
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/down\s+\d{14}\s+Create users/, output)
- assert_match(/down\s+\d{14}\s+Add email to users/, output)
+ assert_match(/down\s+\d{14}\s+Create users/, output)
+ assert_match(/down\s+\d{14}\s+Add email to users/, output)
- `bin/rails db:forward STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:forward", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{14}\s+Create users/, output)
- assert_match(/up\s+\d{14}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{14}\s+Create users/, output)
+ assert_match(/up\s+\d{14}\s+Add email to users/, output)
end
test "raise error on any move when current migration does not exist" do
Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate
- rm db/migrate/*email*.rb`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
+ `rm db/migrate/*email*.rb`
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
- output = `bin/rails db:rollback 2>&1`
+ output = rails("db:rollback", allow_failure: true)
assert_match(/rails aborted!/, output)
assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output)
assert_match(/No migration with version number\s\d{14}\./, output)
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
- output = `bin/rails db:forward 2>&1`
+ output = rails("db:forward", allow_failure: true)
assert_match(/rails aborted!/, output)
assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output)
assert_match(/No migration with version number\s\d{14}\./, output)
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
end
end
+ test "raise error on any move when target migration does not exist" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+
+ output = rails("db:migrate", "VERSION=3", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/ActiveRecord::UnknownMigrationVersionError:/, output)
+ assert_match(/No migration with version number 3/, output)
+
+ output = rails("db:migrate:status")
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
+ end
+
+ test "raise error on any move when VERSION has invalid format" do
+ output = rails("db:migrate", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=0.1.11", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1.1.11", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION='0 '", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1.", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1_", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate", "VERSION=1_name", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate:redo", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate:up", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+
+ output = rails("db:migrate:down", "VERSION=unknown", allow_failure: true)
+ assert_match(/rails aborted!/, output)
+ assert_match(/Invalid format of target version/, output)
+ end
+
test "migration status after rollback and redo without timestamps" do
add_to_config("config.active_record.timestamped_migrations = false")
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/up\s+\d{3,}\s+Add email to users/, output)
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/up\s+\d{3,}\s+Add email to users/, output)
- `bin/rails db:rollback STEP=2`
- output = `bin/rails db:migrate:status`
+ rails "db:rollback", "STEP=2"
+ output = rails("db:migrate:status")
- assert_match(/down\s+\d{3,}\s+Create users/, output)
- assert_match(/down\s+\d{3,}\s+Add email to users/, output)
+ assert_match(/down\s+\d{3,}\s+Create users/, output)
+ assert_match(/down\s+\d{3,}\s+Add email to users/, output)
- `bin/rails db:migrate:redo`
- output = `bin/rails db:migrate:status`
+ rails "db:migrate:redo"
+ output = rails("db:migrate:status")
- assert_match(/up\s+\d{3,}\s+Create users/, output)
- assert_match(/up\s+\d{3,}\s+Add email to users/, output)
- end
+ assert_match(/up\s+\d{3,}\s+Create users/, output)
+ assert_match(/up\s+\d{3,}\s+Add email to users/, output)
end
test "running migrations with not timestamp head migration files" do
- Dir.chdir(app_path) do
+ app_file "db/migrate/1_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- app_file "db/migrate/1_one_migration.rb", <<-MIGRATION
- class OneMigration < ActiveRecord::Migration::Current
- end
- MIGRATION
+ app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
+ class TwoMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
- app_file "db/migrate/02_two_migration.rb", <<-MIGRATION
- class TwoMigration < ActiveRecord::Migration::Current
- end
- MIGRATION
+ rails "db:migrate"
- `bin/rails db:migrate`
+ output = rails("db:migrate:status")
- output = `bin/rails db:migrate:status`
-
- assert_match(/up\s+001\s+One migration/, output)
- assert_match(/up\s+002\s+Two migration/, output)
- end
+ assert_match(/up\s+001\s+One migration/, output)
+ assert_match(/up\s+002\s+Two migration/, output)
end
test "schema generation when dump_schema_after_migration is set" do
add_to_config("config.active_record.dump_schema_after_migration = false")
Dir.chdir(app_path) do
- `bin/rails generate model book title:string`
- output = `bin/rails generate model author name:string`
+ rails "generate", "model", "book", "title:string"
+ output = rails("generate", "model", "author", "name:string")
version = output =~ %r{[^/]+db/migrate/(\d+)_create_authors\.rb} && $1
- `bin/rails db:migrate db:rollback db:forward db:migrate:up db:migrate:down VERSION=#{version}`
+ rails "db:migrate", "db:rollback", "db:forward", "db:migrate:up", "db:migrate:down", "VERSION=#{version}"
assert !File.exist?("db/schema.rb"), "should not dump schema when configured not to"
end
add_to_config("config.active_record.dump_schema_after_migration = true")
Dir.chdir(app_path) do
- `bin/rails generate model reviews book_id:integer`
- `bin/rails db:migrate`
+ rails "generate", "model", "reviews", "book_id:integer"
+ rails "db:migrate"
structure_dump = File.read("db/schema.rb")
assert_match(/create_table "reviews"/, structure_dump)
@@ -278,8 +433,8 @@ module ApplicationTests
test "default schema generation after migration" do
Dir.chdir(app_path) do
- `bin/rails generate model book title:string;
- bin/rails db:migrate`
+ rails "generate", "model", "book", "title:string"
+ rails "db:migrate"
structure_dump = File.read("db/schema.rb")
assert_match(/create_table "books"/, structure_dump)
@@ -288,12 +443,12 @@ module ApplicationTests
test "migration status migrated file is deleted" do
Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate migration add_email_to_users email:string;
- bin/rails db:migrate
- rm db/migrate/*email*.rb`
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "migration", "add_email_to_users", "email:string"
+ rails "db:migrate"
+ `rm db/migrate/*email*.rb`
- output = `bin/rails db:migrate:status`
+ output = rails("db:migrate:status")
assert_match(/up\s+\d{14}\s+Create users/, output)
assert_match(/up\s+\d{14}\s+\** NO FILE \**/, output)
diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb
new file mode 100644
index 0000000000..07d96fcb56
--- /dev/null
+++ b/railties/test/application/rake/multi_dbs_test.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+
+module ApplicationTests
+ module RakeTests
+ class RakeMultiDbsTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app(multi_db: true)
+ FileUtils.rm_rf("#{app_path}/config/environments")
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ def db_create_and_drop(namespace, expected_database, environment_loaded: true)
+ Dir.chdir(app_path) do
+ output = rails("db:create")
+ assert_match(/Created database/, output)
+ assert_match_namespace(namespace, output)
+ assert File.exist?(expected_database)
+
+ output = rails("db:drop")
+ assert_match(/Dropped database/, output)
+ assert_match_namespace(namespace, output)
+ assert_not File.exist?(expected_database)
+ end
+ end
+
+ def db_create_and_drop_namespace(namespace, expected_database, environment_loaded: true)
+ Dir.chdir(app_path) do
+ output = rails("db:create:#{namespace}")
+ assert_match(/Created database/, output)
+ assert_match_namespace(namespace, output)
+ assert File.exist?(expected_database)
+
+ output = rails("db:drop:#{namespace}")
+ assert_match(/Dropped database/, output)
+ assert_match_namespace(namespace, output)
+ assert_not File.exist?(expected_database)
+ end
+ end
+
+ def assert_match_namespace(namespace, output)
+ if namespace == "primary"
+ assert_match(/#{Rails.env}.sqlite3/, output)
+ else
+ assert_match(/#{Rails.env}_#{namespace}.sqlite3/, output)
+ end
+ end
+
+ def db_migrate_and_schema_dump_and_load(namespace, expected_database, format)
+ Dir.chdir(app_path) do
+ rails "generate", "model", "book", "title:string"
+ rails "generate", "model", "dog", "name:string"
+ write_models_for_animals
+ rails "db:migrate", "db:#{format}:dump"
+
+ if format == "schema"
+ schema_dump = File.read("db/#{format}.rb")
+ schema_dump_animals = File.read("db/animals_#{format}.rb")
+ assert_match(/create_table \"books\"/, schema_dump)
+ assert_match(/create_table \"dogs\"/, schema_dump_animals)
+ else
+ schema_dump = File.read("db/#{format}.sql")
+ schema_dump_animals = File.read("db/animals_#{format}.sql")
+ assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"books\"/, schema_dump)
+ assert_match(/CREATE TABLE (?:IF NOT EXISTS )?\"dogs\"/, schema_dump_animals)
+ end
+
+ rails "db:#{format}:load"
+
+ ar_tables = lambda { rails("runner", "p ActiveRecord::Base.connection.tables").strip }
+ animals_tables = lambda { rails("runner", "p AnimalsBase.connection.tables").strip }
+
+ assert_equal '["schema_migrations", "ar_internal_metadata", "books"]', ar_tables[]
+ assert_equal '["schema_migrations", "ar_internal_metadata", "dogs"]', animals_tables[]
+ end
+ end
+
+ def db_migrate_namespaced(namespace, expected_database)
+ Dir.chdir(app_path) do
+ rails "generate", "model", "book", "title:string"
+ rails "generate", "model", "dog", "name:string"
+ write_models_for_animals
+ output = rails("db:migrate:#{namespace}")
+ if namespace == "primary"
+ assert_match(/CreateBooks: migrated/, output)
+ else
+ assert_match(/CreateDogs: migrated/, output)
+ end
+ end
+ end
+
+ def write_models_for_animals
+ # make a directory for the animals migration
+ FileUtils.mkdir_p("#{app_path}/db/animals_migrate")
+ # move the dogs migration if it unless it already lives there
+ FileUtils.mv(Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first, "db/animals_migrate/") unless Dir.glob("#{app_path}/db/animals_migrate/**/*dogs.rb").first
+ # delete the dogs migration if it's still present in the
+ # migrate folder. This is necessary because sometimes
+ # the code isn't fast enough and an extra migration gets made
+ FileUtils.rm(Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first) if Dir.glob("#{app_path}/db/migrate/**/*dogs.rb").first
+
+ # change the base of the dog model
+ app_path("/app/models/dog.rb") do |file_name|
+ file = File.read("#{app_path}/app/models/dog.rb")
+ file.sub!(/ApplicationRecord/, "AnimalsBase")
+ File.write(file_name, file)
+ end
+
+ # create the base model for dog to inherit from
+ File.open("#{app_path}/app/models/animals_base.rb", "w") do |file|
+ file.write(<<-EOS
+class AnimalsBase < ActiveRecord::Base
+ self.abstract_class = true
+
+ establish_connection :animals
+end
+EOS
+)
+ end
+ end
+
+ test "db:create and db:drop works on all databases for env" do
+ require "#{app_path}/config/environment"
+ ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
+ db_create_and_drop namespace, config["database"]
+ end
+ end
+
+ test "db:create:namespace and db:drop:namespace works on specified databases" do
+ require "#{app_path}/config/environment"
+ ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
+ db_create_and_drop_namespace namespace, config["database"]
+ end
+ end
+
+ test "db:migrate and db:schema:dump and db:schema:load works on all databases" do
+ require "#{app_path}/config/environment"
+ ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
+ db_migrate_and_schema_dump_and_load namespace, config["database"], "schema"
+ end
+ end
+
+ test "db:migrate and db:structure:dump and db:structure:load works on all databases" do
+ require "#{app_path}/config/environment"
+ ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
+ db_migrate_and_schema_dump_and_load namespace, config["database"], "structure"
+ end
+ end
+
+ test "db:migrate:namespace works" do
+ require "#{app_path}/config/environment"
+ ActiveRecord::Base.configurations[Rails.env].each do |namespace, config|
+ db_migrate_namespaced namespace, config["database"]
+ end
+ end
+ end
+ end
+end
diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb
index e7ffea2e71..d73e5cdfa3 100644
--- a/railties/test/application/rake/notes_test.rb
+++ b/railties/test/application/rake/notes_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rails/source_annotation_extractor"
@@ -90,7 +92,8 @@ module ApplicationTests
test "custom rake task finds specific notes in specific directories" do
app_file "app/controllers/some_controller.rb", "# TODO: note in app directory"
- app_file "lib/some_file.rb", "# OPTIMIZE: note in lib directory\n" << "# FIXME: note in lib directory"
+ app_file "lib/some_file.rb", "# OPTIMIZE: note in lib directory\n" \
+ "# FIXME: note in lib directory"
app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory"
app_file "lib/tasks/notes_custom.rake", <<-EOS
@@ -98,7 +101,7 @@ module ApplicationTests
task :notes_custom do
tags = 'TODO|FIXME'
opts = { dirs: %w(lib test), tag: true }
- SourceAnnotationExtractor.enumerate(tags, opts)
+ Rails::SourceAnnotationExtractor.enumerate(tags, opts)
end
EOS
diff --git a/railties/test/application/rake/restart_test.rb b/railties/test/application/rake/restart_test.rb
index 6ebd2d5461..8614560bf2 100644
--- a/railties/test/application/rake/restart_test.rb
+++ b/railties/test/application/rake/restart_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -15,12 +17,12 @@ module ApplicationTests
test "rails restart touches tmp/restart.txt" do
Dir.chdir(app_path) do
- `bin/rails restart`
+ rails "restart"
assert File.exist?("tmp/restart.txt")
prev_mtime = File.mtime("tmp/restart.txt")
sleep(1)
- `bin/rails restart`
+ rails "restart"
curr_mtime = File.mtime("tmp/restart.txt")
assert_not_equal prev_mtime, curr_mtime
end
@@ -29,19 +31,10 @@ module ApplicationTests
test "rails restart should work even if tmp folder does not exist" do
Dir.chdir(app_path) do
FileUtils.remove_dir("tmp")
- `bin/rails restart`
+ rails "restart"
assert File.exist?("tmp/restart.txt")
end
end
-
- test "rails restart removes server.pid also" do
- Dir.chdir(app_path) do
- FileUtils.mkdir_p("tmp/pids")
- FileUtils.touch("tmp/pids/server.pid")
- `bin/rails restart`
- assert_not File.exist?("tmp/pids/server.pid")
- end
- end
end
end
end
diff --git a/railties/test/application/rake/tmp_test.rb b/railties/test/application/rake/tmp_test.rb
index 8423a98f84..048fd7adcc 100644
--- a/railties/test/application/rake/tmp_test.rb
+++ b/railties/test/application/rake/tmp_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -24,7 +26,7 @@ module ApplicationTests
FileUtils.mkdir_p("tmp/screenshots")
FileUtils.touch("tmp/screenshots/fail.png")
- `rails tmp:clear`
+ rails "tmp:clear"
assert_not File.exist?("tmp/cache/cache_file")
assert_not File.exist?("tmp/sockets/socket_file")
@@ -34,9 +36,7 @@ module ApplicationTests
test "tmp:clear should work if folder missing" do
FileUtils.remove_dir("#{app_path}/tmp")
- errormsg = Dir.chdir(app_path) { `bin/rails tmp:clear` }
- assert_predicate $?, :success?
- assert_empty errormsg
+ rails "tmp:clear"
end
end
end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index 134106812d..1522a2bbc5 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
-require "active_support/core_ext/string/strip"
+require "env_helpers"
module ApplicationTests
class RakeTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
def setup
build_app
@@ -24,22 +26,22 @@ module ApplicationTests
end
test "task is protected when previous migration was production" do
- Dir.chdir(app_path) do
- output = `bin/rails generate model product name:string;
- env RAILS_ENV=production bin/rails db:create db:migrate;
- env RAILS_ENV=production bin/rails db:test:prepare test 2>&1`
+ with_rails_env "production" do
+ rails "generate", "model", "product", "name:string"
+ rails "db:create", "db:migrate"
+ output = rails("db:test:prepare", allow_failure: true)
assert_match(/ActiveRecord::ProtectedEnvironmentError/, output)
end
end
def test_not_protected_when_previous_migration_was_not_production
- Dir.chdir(app_path) do
- output = `bin/rails generate model product name:string;
- env RAILS_ENV=test bin/rails db:create db:migrate;
- env RAILS_ENV=test bin/rails db:test:prepare test 2>&1`
+ with_rails_env "test" do
+ rails "generate", "model", "product", "name:string"
+ rails "db:create", "db:migrate"
+ output = rails("db:test:prepare", "test")
- refute_match(/ActiveRecord::ProtectedEnvironmentError/, output)
+ assert_no_match(/ActiveRecord::ProtectedEnvironmentError/, output)
end
end
@@ -54,7 +56,7 @@ module ApplicationTests
Rails.application.initialize!
RUBY
- assert_match("SuperMiddleware", Dir.chdir(app_path) { `bin/rails middleware` })
+ assert_match("SuperMiddleware", rails("middleware"))
end
def test_initializers_are_executed_in_rake_tasks
@@ -69,7 +71,7 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails do_nothing` }
+ output = rails("do_nothing")
assert_match "Doing something...", output
end
@@ -90,7 +92,7 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails do_nothing` }
+ output = rails("do_nothing")
assert_match "Hello world", output
end
@@ -98,6 +100,7 @@ module ApplicationTests
add_to_config <<-RUBY
rake_tasks do
task do_nothing: :environment do
+ puts 'There is nothing'
end
end
RUBY
@@ -110,134 +113,13 @@ module ApplicationTests
raise 'should not be pre-required for rake even eager_load=true'
RUBY
- Dir.chdir(app_path) do
- assert system("bin/rails do_nothing RAILS_ENV=production"),
- "should not be pre-required for rake even eager_load=true"
- end
+ output = rails("do_nothing", "RAILS_ENV=production")
+ assert_match "There is nothing", output
end
def test_code_statistics_sanity
assert_match "Code LOC: 25 Test LOC: 0 Code to Test Ratio: 1:0.0",
- Dir.chdir(app_path) { `bin/rails stats` }
- end
-
- def test_rails_routes_calls_the_route_inspector
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- get '/cart', to: 'cart#show'
- end
- RUBY
-
- output = Dir.chdir(app_path) { `bin/rails routes` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
- end
-
- def test_singular_resource_output_in_rake_routes
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- resource :post
- end
- RUBY
-
- expected_output = [" Prefix Verb URI Pattern Controller#Action",
- " new_post GET /post/new(.:format) posts#new",
- "edit_post GET /post/edit(.:format) posts#edit",
- " post GET /post(.:format) posts#show",
- " PATCH /post(.:format) posts#update",
- " PUT /post(.:format) posts#update",
- " DELETE /post(.:format) posts#destroy",
- " POST /post(.:format) posts#create\n"].join("\n")
-
- output = Dir.chdir(app_path) { `bin/rails routes -c PostController` }
- assert_equal expected_output, output
- end
-
- def test_rails_routes_with_global_search_key
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- get '/cart', to: 'cart#show'
- post '/cart', to: 'cart#create'
- get '/basketballs', to: 'basketball#index'
- end
- RUBY
-
- output = Dir.chdir(app_path) { `bin/rails routes -g show` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
-
- output = Dir.chdir(app_path) { `bin/rails routes -g POST` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n POST /cart(.:format) cart#create\n", output
-
- output = Dir.chdir(app_path) { `bin/rails routes -g basketballs` }
- assert_equal " Prefix Verb URI Pattern Controller#Action\n" \
- "basketballs GET /basketballs(.:format) basketball#index\n", output
- end
-
- def test_rails_routes_with_controller_search_key
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- get '/cart', to: 'cart#show'
- get '/basketball', to: 'basketball#index'
- end
- RUBY
-
- output = Dir.chdir(app_path) { `bin/rails routes -c cart` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
-
- output = Dir.chdir(app_path) { `bin/rails routes -c Cart` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
-
- output = Dir.chdir(app_path) { `bin/rails routes -c CartController` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
- end
-
- def test_rails_routes_with_namespaced_controller_search_key
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- namespace :admin do
- resource :post
- end
- end
- RUBY
- expected_output = [" Prefix Verb URI Pattern Controller#Action",
- " new_admin_post GET /admin/post/new(.:format) admin/posts#new",
- "edit_admin_post GET /admin/post/edit(.:format) admin/posts#edit",
- " admin_post GET /admin/post(.:format) admin/posts#show",
- " PATCH /admin/post(.:format) admin/posts#update",
- " PUT /admin/post(.:format) admin/posts#update",
- " DELETE /admin/post(.:format) admin/posts#destroy",
- " POST /admin/post(.:format) admin/posts#create\n"].join("\n")
-
- output = Dir.chdir(app_path) { `bin/rails routes -c Admin::PostController` }
- assert_equal expected_output, output
-
- output = Dir.chdir(app_path) { `bin/rails routes -c PostController` }
- assert_equal expected_output, output
- end
-
- def test_rails_routes_displays_message_when_no_routes_are_defined
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- end
- RUBY
-
- assert_equal <<-MESSAGE.strip_heredoc, Dir.chdir(app_path) { `bin/rails routes` }
- You don't have any routes defined!
-
- Please add some routes in config/routes.rb.
-
- For more information about routes, see the Rails guide: http://guides.rubyonrails.org/routing.html.
- MESSAGE
- end
-
- def test_rake_routes_with_rake_options
- app_file "config/routes.rb", <<-RUBY
- Rails.application.routes.draw do
- get '/cart', to: 'cart#show'
- end
- RUBY
-
- output = Dir.chdir(app_path) { `bin/rake --rakefile Rakefile routes` }
- assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+ rails("stats")
end
def test_logger_is_flushed_when_exiting_production_rake_tasks
@@ -249,44 +131,37 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) { `bin/rails log_something RAILS_ENV=production && cat log/production.log` }
- assert_match "Sample log message", output
+ rails "log_something", "RAILS_ENV=production"
+ assert_match "Sample log message", File.read("#{app_path}/log/production.log")
end
def test_loading_specific_fixtures
- Dir.chdir(app_path) do
- `bin/rails generate model user username:string password:string;
- bin/rails generate model product name:string;
- bin/rails db:migrate`
- end
+ rails "generate", "model", "user", "username:string", "password:string"
+ rails "generate", "model", "product", "name:string"
+ rails "db:migrate"
require "#{rails_root}/config/environment"
# loading a specific fixture
- errormsg = Dir.chdir(app_path) { `bin/rails db:fixtures:load FIXTURES=products` }
- assert $?.success?, errormsg
+ rails "db:fixtures:load", "FIXTURES=products"
assert_equal 2, ::AppTemplate::Application::Product.count
assert_equal 0, ::AppTemplate::Application::User.count
end
def test_loading_only_yml_fixtures
- Dir.chdir(app_path) do
- `bin/rails db:migrate`
- end
+ rails "db:migrate"
app_file "test/fixtures/products.csv", ""
require "#{rails_root}/config/environment"
- errormsg = Dir.chdir(app_path) { `bin/rails db:fixtures:load` }
- assert $?.success?, errormsg
+ rails "db:fixtures:load"
end
def test_scaffold_tests_pass_by_default
- output = Dir.chdir(app_path) do
- `bin/rails generate scaffold user username:string password:string;
- RAILS_ENV=test bin/rails db:migrate test`
- end
+ rails "generate", "scaffold", "user", "username:string", "password:string"
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output)
assert_no_match(/Errors running/, output)
@@ -302,22 +177,20 @@ module ApplicationTests
end
RUBY
- output = Dir.chdir(app_path) do
- `bin/rails generate scaffold user username:string password:string;
- RAILS_ENV=test bin/rails db:migrate test`
- end
+ rails "generate", "scaffold", "user", "username:string", "password:string"
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/5 runs, 7 assertions, 0 failures, 0 errors/, output)
assert_no_match(/Errors running/, output)
end
def test_scaffold_with_references_columns_tests_pass_by_default
- output = Dir.chdir(app_path) do
- `bin/rails generate model Product;
- bin/rails generate model Cart;
- bin/rails generate scaffold LineItems product:references cart:belongs_to;
- RAILS_ENV=test bin/rails db:migrate test`
- end
+ rails "generate", "model", "Product"
+ rails "generate", "model", "Cart"
+ rails "generate", "scaffold", "LineItems", "product:references", "cart:belongs_to"
+ with_rails_env("test") { rails("db:migrate") }
+ output = rails("test")
assert_match(/7 runs, 9 assertions, 0 failures, 0 errors/, output)
assert_no_match(/Errors running/, output)
@@ -325,59 +198,47 @@ module ApplicationTests
def test_db_test_prepare_when_using_sql_format
add_to_config "config.active_record.schema_format = :sql"
- output = Dir.chdir(app_path) do
- `bin/rails generate scaffold user username:string;
- bin/rails db:migrate;
- bin/rails db:test:prepare 2>&1 --trace`
- end
+ rails "generate", "scaffold", "user", "username:string"
+ rails "db:migrate"
+ output = rails("db:test:prepare", "--trace")
assert_match(/Execute db:test:load_structure/, output)
end
def test_rake_dump_structure_should_respect_db_structure_env_variable
- Dir.chdir(app_path) do
- # ensure we have a schema_migrations table to dump
- `bin/rails db:migrate db:structure:dump SCHEMA=db/my_structure.sql`
- end
+ # ensure we have a schema_migrations table to dump
+ rails "db:migrate", "db:structure:dump", "SCHEMA=db/my_structure.sql"
assert File.exist?(File.join(app_path, "db", "my_structure.sql"))
end
def test_rake_dump_structure_should_be_called_twice_when_migrate_redo
add_to_config "config.active_record.schema_format = :sql"
- output = Dir.chdir(app_path) do
- `bin/rails g model post title:string;
- bin/rails db:migrate:redo 2>&1 --trace;`
- end
+ rails "g", "model", "post", "title:string"
+ output = rails("db:migrate:redo", "--trace")
# expect only Invoke db:structure:dump (first_time)
assert_no_match(/^\*\* Invoke db:structure:dump\s+$/, output)
end
def test_rake_dump_schema_cache
- Dir.chdir(app_path) do
- `bin/rails generate model post title:string;
- bin/rails generate model product name:string;
- bin/rails db:migrate db:schema:cache:dump`
- end
+ rails "generate", "model", "post", "title:string"
+ rails "generate", "model", "product", "name:string"
+ rails "db:migrate", "db:schema:cache:dump"
assert File.exist?(File.join(app_path, "db", "schema_cache.yml"))
end
def test_rake_clear_schema_cache
- Dir.chdir(app_path) do
- `bin/rails db:schema:cache:dump db:schema:cache:clear`
- end
- assert !File.exist?(File.join(app_path, "db", "schema_cache.yml"))
+ rails "db:schema:cache:dump", "db:schema:cache:clear"
+ assert_not File.exist?(File.join(app_path, "db", "schema_cache.yml"))
end
def test_copy_templates
- Dir.chdir(app_path) do
- `bin/rails app:templates:copy`
- %w(controller mailer scaffold).each do |dir|
- assert File.exist?(File.join(app_path, "lib", "templates", "erb", dir))
- end
- %w(controller helper scaffold_controller assets).each do |dir|
- assert File.exist?(File.join(app_path, "lib", "templates", "rails", dir))
- end
+ rails "app:templates:copy"
+ %w(controller mailer scaffold).each do |dir|
+ assert File.exist?(File.join(app_path, "lib", "templates", "erb", dir))
+ end
+ %w(controller helper scaffold_controller assets).each do |dir|
+ assert File.exist?(File.join(app_path, "lib", "templates", "rails", dir))
end
end
@@ -385,10 +246,7 @@ module ApplicationTests
app_file "config/initializers/dummy.rb", "puts 'Hello, World!'"
app_file "template.rb", ""
- output = Dir.chdir(app_path) do
- `bin/rails app:template LOCATION=template.rb`
- end
-
+ output = rails("app:template", "LOCATION=template.rb")
assert_match(/Hello, World!/, output)
end
end
diff --git a/railties/test/application/rendering_test.rb b/railties/test/application/rendering_test.rb
index ccafc5b6f1..ab1591f388 100644
--- a/railties/test/application/rendering_test.rb
+++ b/railties/test/application/rendering_test.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
module ApplicationTests
- class RoutingTest < ActiveSupport::TestCase
+ class RenderingTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
include Rack::Test::Methods
diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb
index 6742da20cc..bec038fb51 100644
--- a/railties/test/application/routing_test.rb
+++ b/railties/test/application/routing_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rack/test"
@@ -293,7 +295,7 @@ module ApplicationTests
extend ActiveModel::Naming
include ActiveModel::Conversion
- def model_name
+ def self.model_name
@_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
end
@@ -430,7 +432,7 @@ module ApplicationTests
extend ActiveModel::Naming
include ActiveModel::Conversion
- def model_name
+ def self.model_name
@_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
end
@@ -542,7 +544,7 @@ module ApplicationTests
extend ActiveModel::Naming
include ActiveModel::Conversion
- def model_name
+ def self.model_name
@_model_name ||= ActiveModel::Name.new(self.class, nil, "User")
end
diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb
index 81f717b2c3..8f5f48c281 100644
--- a/railties/test/application/runner_test.rb
+++ b/railties/test/application/runner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "env_helpers"
@@ -24,22 +26,19 @@ module ApplicationTests
end
def test_should_include_runner_in_shebang_line_in_help_without_option
- assert_match "/rails runner", Dir.chdir(app_path) { `bin/rails runner` }
+ assert_match "/rails runner", rails("runner", allow_failure: true)
end
def test_should_include_runner_in_shebang_line_in_help
- assert_match "/rails runner", Dir.chdir(app_path) { `bin/rails runner --help` }
+ assert_match "/rails runner", rails("runner", "--help")
end
def test_should_run_ruby_statement
- assert_match "42", Dir.chdir(app_path) { `bin/rails runner "puts User.count"` }
+ assert_match "42", rails("runner", "puts User.count")
end
def test_should_set_argv_when_running_code
- output = Dir.chdir(app_path) {
- # Both long and short args, at start and end of ARGV
- `bin/rails runner "puts ARGV.join(',')" --foo a1 -b a2 a3 --moo`
- }
+ output = rails("runner", "puts ARGV.join(',')", "--foo", "a1", "-b", "a2", "a3", "--moo")
assert_equal "--foo,a1,-b,a2,a3,--moo", output.chomp
end
@@ -48,7 +47,7 @@ module ApplicationTests
puts User.count
SCRIPT
- assert_match "42", Dir.chdir(app_path) { `bin/rails runner "bin/count_users.rb"` }
+ assert_match "42", rails("runner", "bin/count_users.rb")
end
def test_no_minitest_loaded_in_production_mode
@@ -65,7 +64,7 @@ module ApplicationTests
puts $0
SCRIPT
- assert_match "bin/dollar0.rb", Dir.chdir(app_path) { `bin/rails runner "bin/dollar0.rb"` }
+ assert_match "bin/dollar0.rb", rails("runner", "bin/dollar0.rb")
end
def test_should_set_dollar_program_name_to_file
@@ -73,7 +72,7 @@ module ApplicationTests
puts $PROGRAM_NAME
SCRIPT
- assert_match "bin/program_name.rb", Dir.chdir(app_path) { `bin/rails runner "bin/program_name.rb"` }
+ assert_match "bin/program_name.rb", rails("runner", "bin/program_name.rb")
end
def test_passes_extra_args_to_file
@@ -81,7 +80,7 @@ module ApplicationTests
p ARGV
SCRIPT
- assert_match %w( a b ).to_s, Dir.chdir(app_path) { `bin/rails runner "bin/program_name.rb" a b` }
+ assert_match %w( a b ).to_s, rails("runner", "bin/program_name.rb", "a", "b")
end
def test_should_run_stdin
@@ -99,35 +98,47 @@ module ApplicationTests
end
RUBY
- assert_match "true", Dir.chdir(app_path) { `bin/rails runner "puts Rails.application.config.ran"` }
+ assert_match "true", rails("runner", "puts Rails.application.config.ran")
end
def test_default_environment
- assert_match "development", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` }
+ assert_match "development", rails("runner", "puts Rails.env")
end
def test_runner_detects_syntax_errors
- output = Dir.chdir(app_path) { `bin/rails runner "puts 'hello world" 2>&1` }
- assert_not $?.success?
+ output = rails("runner", "puts 'hello world", allow_failure: true)
+ assert_not_predicate $?, :success?
assert_match "unterminated string meets end of file", output
end
def test_runner_detects_bad_script_name
- output = Dir.chdir(app_path) { `bin/rails runner "iuiqwiourowe" 2>&1` }
- assert_not $?.success?
+ output = rails("runner", "iuiqwiourowe", allow_failure: true)
+ assert_not_predicate $?, :success?
assert_match "undefined local variable or method `iuiqwiourowe' for", output
end
def test_environment_with_rails_env
with_rails_env "production" do
- assert_match "production", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` }
+ assert_match "production", rails("runner", "puts Rails.env")
end
end
def test_environment_with_rack_env
with_rack_env "production" do
- assert_match "production", Dir.chdir(app_path) { `bin/rails runner "puts Rails.env"` }
+ assert_match "production", rails("runner", "puts Rails.env")
+ end
+ end
+
+ def test_can_call_same_name_class_as_defined_in_thor
+ app_file "app/models/task.rb", <<-MODEL
+ class Task
+ def self.count
+ 42
+ end
end
+ MODEL
+
+ assert_match "42", rails("runner", "puts Task.count")
end
end
end
diff --git a/railties/test/application/server_test.rb b/railties/test/application/server_test.rb
new file mode 100644
index 0000000000..f3a7e00a4d
--- /dev/null
+++ b/railties/test/application/server_test.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "console_helpers"
+require "rails/command"
+require "rails/commands/server/server_command"
+
+module ApplicationTests
+ class ServerTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+ include ConsoleHelpers
+
+ def setup
+ build_app
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ test "deprecate support of older `config.ru`" do
+ remove_file "config.ru"
+ app_file "config.ru", <<-RUBY
+ require_relative 'config/environment'
+ run AppTemplate::Application
+ RUBY
+
+ server = Rails::Server.new(config: "#{app_path}/config.ru")
+ server.app
+
+ log = File.read(Rails.application.config.paths["log"].first)
+ assert_match(/DEPRECATION WARNING: Using `Rails::Application` subclass to start the server is deprecated/, log)
+ end
+
+ test "restart rails server with custom pid file path" do
+ skip "PTY unavailable" unless available_pty?
+
+ File.open("#{app_path}/config/boot.rb", "w") do |f|
+ f.puts "ENV['BUNDLE_GEMFILE'] = '#{Bundler.default_gemfile.to_s}'"
+ f.puts "require 'bundler/setup'"
+ end
+
+ master, slave = PTY.open
+ pid = nil
+
+ begin
+ pid = Process.spawn("#{app_path}/bin/rails server -P tmp/dummy.pid", in: slave, out: slave, err: slave)
+ assert_output("Listening", master)
+
+ rails("restart")
+
+ assert_output("Restarting", master)
+ assert_output("Inherited", master)
+ ensure
+ kill(pid) if pid
+ end
+ end
+
+ private
+ def kill(pid)
+ Process.kill("TERM", pid)
+ Process.wait(pid)
+ rescue Errno::ESRCH
+ end
+ end
+end
diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb
index c0027ab9a2..8e5ccf94cc 100644
--- a/railties/test/application/test_runner_test.rb
+++ b/railties/test/application/test_runner_test.rb
@@ -1,5 +1,6 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
-require "active_support/core_ext/string/strip"
require "env_helpers"
module ApplicationTests
@@ -31,19 +32,33 @@ module ApplicationTests
assert_match "1 runs, 1 assertions, 0 failures", run_test_command("test/models/foo_test.rb")
end
+ def test_run_single_file_with_absolute_path
+ create_test_file :models, "foo"
+ create_test_file :models, "bar"
+ assert_match "1 runs, 1 assertions, 0 failures", run_test_command("#{app_path}/test/models/foo_test.rb")
+ end
+
def test_run_multiple_files
create_test_file :models, "foo"
create_test_file :models, "bar"
assert_match "2 runs, 2 assertions, 0 failures", run_test_command("test/models/foo_test.rb test/models/bar_test.rb")
end
+ def test_run_multiple_files_with_absolute_paths
+ create_test_file :models, "foo"
+ create_test_file :controllers, "foobar_controller"
+ create_test_file :models, "bar"
+
+ assert_match "2 runs, 2 assertions, 0 failures", run_test_command("#{app_path}/test/models/foo_test.rb #{app_path}/test/controllers/foobar_controller_test.rb")
+ end
+
def test_run_file_with_syntax_error
app_file "test/models/error_test.rb", <<-RUBY
require 'test_helper'
def; end
RUBY
- error = capture(:stderr) { run_test_command("test/models/error_test.rb") }
+ error = capture(:stderr) { run_test_command("test/models/error_test.rb", stderr: true) }
assert_match "syntax error", error
end
@@ -75,13 +90,11 @@ module ApplicationTests
create_test_file :unit, "baz_unit"
create_test_file :controllers, "foobar_controller"
- Dir.chdir(app_path) do
- `bin/rails test:units`.tap do |output|
- assert_match "FooTest", output
- assert_match "BarHelperTest", output
- assert_match "BazUnitTest", output
- assert_match "3 runs, 3 assertions, 0 failures", output
- end
+ rails("test:units").tap do |output|
+ assert_match "FooTest", output
+ assert_match "BarHelperTest", output
+ assert_match "BazUnitTest", output
+ assert_match "3 runs, 3 assertions, 0 failures", output
end
end
@@ -124,13 +137,11 @@ module ApplicationTests
create_test_file :functional, "baz_functional"
create_test_file :models, "foo"
- Dir.chdir(app_path) do
- `bin/rails test:functionals`.tap do |output|
- assert_match "FooMailerTest", output
- assert_match "BarControllerTest", output
- assert_match "BazFunctionalTest", output
- assert_match "3 runs, 3 assertions, 0 failures", output
- end
+ rails("test:functionals").tap do |output|
+ assert_match "FooMailerTest", output
+ assert_match "BarControllerTest", output
+ assert_match "BazFunctionalTest", output
+ assert_match "3 runs, 3 assertions, 0 failures", output
end
end
@@ -264,6 +275,18 @@ module ApplicationTests
end
end
+ def test_run_multiple_folders_with_absolute_paths
+ create_test_file :models, "account"
+ create_test_file :controllers, "accounts_controller"
+ create_test_file :helpers, "foo_helper"
+
+ run_test_command("#{app_path}/test/models #{app_path}/test/controllers").tap do |output|
+ assert_match "AccountTest", output
+ assert_match "AccountsControllerTest", output
+ assert_match "2 runs, 2 assertions, 0 failures, 0 errors, 0 skips", output
+ end
+ end
+
def test_run_with_ruby_command
app_file "test/models/post_test.rb", <<-RUBY
require 'test_helper'
@@ -478,10 +501,10 @@ module ApplicationTests
end
def test_output_inline_by_default
- create_test_file :models, "post", pass: false
+ create_test_file :models, "post", pass: false, print: false
output = run_test_command("test/models/post_test.rb")
- expect = %r{Running:\n\nPostTest\nF\n\nFailure:\nPostTest#test_truth \[[^\]]+test/models/post_test.rb:6\]:\nwups!\n\nbin/rails test test/models/post_test.rb:4\n\n\n\n}
+ expect = %r{Running:\n\nF\n\nFailure:\nPostTest#test_truth \[[^\]]+test/models/post_test.rb:6\]:\nwups!\n\nbin/rails test test/models/post_test.rb:4\n\n\n\n}
assert_match expect, output
end
@@ -489,18 +512,40 @@ module ApplicationTests
create_test_file :models, "post", pass: false
output = run_test_command("test/models/post_test.rb")
- assert_match %r{Finished in.*\n\n1 runs, 1 assertions}, output
+ assert_match %r{Finished in.*\n1 runs, 1 assertions}, output
end
def test_fail_fast
create_test_file :models, "post", pass: false
assert_match(/Interrupt/,
- capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast") })
+ capture(:stderr) { run_test_command("test/models/post_test.rb --fail-fast", stderr: true) })
+ end
+
+ def test_run_in_parallel_with_processes
+ file_name = create_parallel_processes_test_file
+
+ output = run_test_command(file_name)
+
+ assert_match %r{Finished in.*\n2 runs, 2 assertions}, output
+ end
+
+ def test_run_in_parallel_with_threads
+ app_path("/test/test_helper.rb") do |file_name|
+ file = File.read(file_name)
+ file.sub!(/parallelize\(([^\)]*)\)/, "parallelize(\\1, with: :threads)")
+ File.write(file_name, file)
+ end
+
+ file_name = create_parallel_threads_test_file
+
+ output = run_test_command(file_name)
+
+ assert_match %r{Finished in.*\n2 runs, 2 assertions}, output
end
def test_raise_error_when_specified_file_does_not_exist
- error = capture(:stderr) { run_test_command("test/not_exists.rb") }
+ error = capture(:stderr) { run_test_command("test/not_exists.rb", stderr: true) }
assert_match(%r{cannot load such file.+test/not_exists\.rb}, error)
end
@@ -526,14 +571,16 @@ module ApplicationTests
def test_rails_db_create_all_restores_db_connection
create_test_file :models, "account"
- output = Dir.chdir(app_path) { `bin/rails db:create:all db:migrate && echo ".tables" | rails dbconsole` }
+ rails "db:create:all", "db:migrate"
+ output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` }
assert_match "ar_internal_metadata", output, "tables should be dumped"
end
def test_rails_db_create_all_restores_db_connection_after_drop
create_test_file :models, "account"
- Dir.chdir(app_path) { `bin/rails db:create:all` } # create all to avoid warnings
- output = Dir.chdir(app_path) { `bin/rails db:drop:all db:create:all db:migrate && echo ".tables" | rails dbconsole` }
+ rails "db:create:all" # create all to avoid warnings
+ rails "db:drop:all", "db:create:all", "db:migrate"
+ output = Dir.chdir(app_path) { `echo ".tables" | rails dbconsole` }
assert_match "ar_internal_metadata", output, "tables should be dumped"
end
@@ -543,6 +590,40 @@ module ApplicationTests
assert_match "AccountTest#test_truth", output, "passing TEST= should run selected test"
end
+ def test_running_with_ruby_gets_test_env_by_default
+ # Subshells inherit `ENV`, so we need to ensure `RAILS_ENV` is set to
+ # nil before we run the tests in the test app.
+ re, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], nil
+
+ file = create_test_for_env("test")
+ results = Dir.chdir(app_path) {
+ `ruby -Ilib:test #{file}`.each_line.map { |line| JSON.parse line }
+ }
+ assert_equal 1, results.length
+ failures = results.first["failures"]
+ flunk(failures.first) unless failures.empty?
+
+ ensure
+ ENV["RAILS_ENV"] = re
+ end
+
+ def test_running_with_ruby_can_set_env_via_cmdline
+ # Subshells inherit `ENV`, so we need to ensure `RAILS_ENV` is set to
+ # nil before we run the tests in the test app.
+ re, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], nil
+
+ file = create_test_for_env("development")
+ results = Dir.chdir(app_path) {
+ `RAILS_ENV=development ruby -Ilib:test #{file}`.each_line.map { |line| JSON.parse line }
+ }
+ assert_equal 1, results.length
+ failures = results.first["failures"]
+ flunk(failures.first) unless failures.empty?
+
+ ensure
+ ENV["RAILS_ENV"] = re
+ end
+
def test_rake_passes_multiple_TESTOPTS_to_minitest
create_test_file :models, "account"
output = Dir.chdir(app_path) { `bin/rake test TESTOPTS='-v --seed=1234'` }
@@ -573,7 +654,7 @@ module ApplicationTests
end
RUBY
assert_match(/warning: assigned but unused variable/,
- capture(:stderr) { run_test_command("test/models/warnings_test.rb -w") })
+ capture(:stderr) { run_test_command("test/models/warnings_test.rb -w", stderr: true) })
end
def test_reset_sessions_before_rollback_on_system_tests
@@ -651,14 +732,14 @@ module ApplicationTests
end
private
- def run_test_command(arguments = "test/unit/test_test.rb")
- Dir.chdir(app_path) { `bin/rails t #{arguments}` }
+ def run_test_command(arguments = "test/unit/test_test.rb", **opts)
+ rails "t", *Shellwords.split(arguments), allow_failure: true, **opts
end
def create_model_with_fixture
- script "generate model user name:string"
+ rails "generate", "model", "user", "name:string"
- app_file "test/fixtures/users.yml", <<-YAML.strip_heredoc
+ app_file "test/fixtures/users.yml", <<~YAML
vampire:
id: 1
name: Koyomi Araragi
@@ -701,19 +782,109 @@ module ApplicationTests
app_file "db/schema.rb", ""
end
- def create_test_file(path = :unit, name = "test", pass: true)
+ def create_test_for_env(env)
+ app_file "test/models/environment_test.rb", <<-RUBY
+ require 'test_helper'
+ class JSONReporter < Minitest::AbstractReporter
+ def record(result)
+ puts JSON.dump(klass: result.class.name,
+ name: result.name,
+ failures: result.failures,
+ assertions: result.assertions,
+ time: result.time)
+ end
+ end
+
+ def Minitest.plugin_json_reporter_init(opts)
+ Minitest.reporter.reporters.clear
+ Minitest.reporter.reporters << JSONReporter.new
+ end
+
+ Minitest.extensions << "rails"
+ Minitest.extensions << "json_reporter"
+
+ # Minitest uses RubyGems to find plugins, and since RubyGems
+ # doesn't know about the Rails installation we're pointing at,
+ # Minitest won't require the Rails minitest plugin when we run
+ # these integration tests. So we have to manually require the
+ # Minitest plugin here.
+ require 'minitest/rails_plugin'
+
+ class EnvironmentTest < ActiveSupport::TestCase
+ def test_environment
+ test_db = ActiveRecord::Base.configurations[#{env.dump}]["database"]
+ db_file = ActiveRecord::Base.connection_config[:database]
+ assert_match(test_db, db_file)
+ assert_equal #{env.dump}, ENV["RAILS_ENV"]
+ end
+ end
+ RUBY
+ end
+
+ def create_test_file(path = :unit, name = "test", pass: true, print: true)
app_file "test/#{path}/#{name}_test.rb", <<-RUBY
require 'test_helper'
class #{name.camelize}Test < ActiveSupport::TestCase
def test_truth
- puts "#{name.camelize}Test"
+ puts "#{name.camelize}Test" if #{print}
assert #{pass}, 'wups!'
end
end
RUBY
end
+ def create_parallel_processes_test_file
+ app_file "test/models/parallel_test.rb", <<-RUBY
+ require 'test_helper'
+
+ class ParallelTest < ActiveSupport::TestCase
+ RD1, WR1 = IO.pipe
+ RD2, WR2 = IO.pipe
+
+ test "one" do
+ WR1.close
+ assert_equal "x", RD1.read(1) # blocks until two runs
+
+ RD2.close
+ WR2.write "y" # Allow two to run
+ WR2.close
+ end
+
+ test "two" do
+ RD1.close
+ WR1.write "x" # Allow one to run
+ WR1.close
+
+ WR2.close
+ assert_equal "y", RD2.read(1) # blocks until one runs
+ end
+ end
+ RUBY
+ end
+
+ def create_parallel_threads_test_file
+ app_file "test/models/parallel_test.rb", <<-RUBY
+ require 'test_helper'
+
+ class ParallelTest < ActiveSupport::TestCase
+ Q1 = Queue.new
+ Q2 = Queue.new
+ test "one" do
+ assert_equal "x", Q1.pop # blocks until two runs
+
+ Q2 << "y"
+ end
+
+ test "two" do
+ Q1 << "x"
+
+ assert_equal "y", Q2.pop # blocks until one runs
+ end
+ end
+ RUBY
+ end
+
def create_env_test
app_file "test/unit/env_test.rb", <<-RUBY
require 'test_helper'
@@ -727,17 +898,17 @@ module ApplicationTests
end
def create_scaffold
- script "generate scaffold user name:string"
- Dir.chdir(app_path) { File.exist?("app/models/user.rb") }
+ rails "generate", "scaffold", "user", "name:string"
+ assert File.exist?("#{app_path}/app/models/user.rb")
run_migration
end
def create_controller
- script "generate controller admin/dashboard index"
+ rails "generate", "controller", "admin/dashboard", "index"
end
def run_migration
- Dir.chdir(app_path) { `bin/rails db:migrate` }
+ rails "db:migrate"
end
end
end
diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb
index 32d2a6857c..fb43bebfbe 100644
--- a/railties/test/application/test_test.rb
+++ b/railties/test/application/test_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -5,10 +7,15 @@ module ApplicationTests
include ActiveSupport::Testing::Isolation
def setup
+ @old = ENV["PARALLEL_WORKERS"]
+ ENV["PARALLEL_WORKERS"] = "0"
+
build_app
end
def teardown
+ ENV["PARALLEL_WORKERS"] = @old
+
teardown_app
end
@@ -55,7 +62,7 @@ module ApplicationTests
end
RUBY
- assert_unsuccessful_run "unit/foo_test.rb", "Failed assertion"
+ assert_unsuccessful_run "unit/foo_test.rb", "Failure:\nFooTest#test_truth"
end
test "integration test" do
@@ -100,7 +107,7 @@ module ApplicationTests
end
test "ruby schema migrations" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -137,7 +144,7 @@ module ApplicationTests
end
test "sql structure migrations" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -176,7 +183,7 @@ module ApplicationTests
end
test "sql structure migrations when adding column to existing table" do
- output_1 = script("generate model user name:string")
+ output_1 = rails("generate", "model", "user", "name:string")
version_1 = output_1.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -201,7 +208,7 @@ module ApplicationTests
assert_successful_test_run("models/user_test.rb")
- output_2 = script("generate migration add_email_to_users")
+ output_2 = rails("generate", "migration", "add_email_to_users")
version_2 = output_2.match(/(\d+)_add_email_to_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -229,7 +236,7 @@ module ApplicationTests
# For now, the user has to synchronize the schema manually.
# This test-case serves as a reminder for this use-case.
test "manually synchronize test schema after rollback" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "test/models/user_test.rb", <<-RUBY
@@ -263,7 +270,7 @@ module ApplicationTests
assert_successful_test_run "models/user_test.rb"
- Dir.chdir(app_path) { `bin/rails db:test:prepare` }
+ rails "db:test:prepare"
assert_unsuccessful_run "models/user_test.rb", <<-ASSERTION
Expected: ["id", "name"]
@@ -272,7 +279,7 @@ Expected: ["id", "name"]
end
test "hooks for plugins" do
- output = script("generate model user name:string")
+ output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]
app_file "lib/tasks/hooks.rake", <<-RUBY
@@ -332,7 +339,7 @@ Expected: ["id", "name"]
end
def run_test_file(name, options = {})
- Dir.chdir(app_path) { `bin/rails test "#{app_path}/test/#{name}" 2>&1` }
+ rails "test", "#{app_path}/test/#{name}", allow_failure: true
end
end
end
diff --git a/railties/test/application/url_generation_test.rb b/railties/test/application/url_generation_test.rb
index 37f129475c..f22b9fda3d 100644
--- a/railties/test/application/url_generation_test.rb
+++ b/railties/test/application/url_generation_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -14,7 +16,6 @@ module ApplicationTests
require "action_view/railtie"
class MyApp < Rails::Application
- secrets.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
config.session_store :cookie_store, key: "_myapp_session"
config.active_support.deprecation = :log
config.eager_load = false
diff --git a/railties/test/application/version_test.rb b/railties/test/application/version_test.rb
index 6b419ae7ae..ae85cf8f05 100644
--- a/railties/test/application/version_test.rb
+++ b/railties/test/application/version_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "rails/gem_version"
@@ -13,12 +15,12 @@ class VersionTest < ActiveSupport::TestCase
end
test "command works" do
- output = Dir.chdir(app_path) { `bin/rails version` }
+ output = rails("version")
assert_equal "Rails #{Rails.gem_version}\n", output
end
test "short-cut alias works" do
- output = Dir.chdir(app_path) { `bin/rails -v` }
+ output = rails("-v")
assert_equal "Rails #{Rails.gem_version}\n", output
end
end
diff --git a/railties/test/backtrace_cleaner_test.rb b/railties/test/backtrace_cleaner_test.rb
index f71e56f323..70917ba20b 100644
--- a/railties/test/backtrace_cleaner_test.rb
+++ b/railties/test/backtrace_cleaner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/backtrace_cleaner"
diff --git a/railties/test/code_statistics_calculator_test.rb b/railties/test/code_statistics_calculator_test.rb
index 25a8a40d27..51917de2e0 100644
--- a/railties/test/code_statistics_calculator_test.rb
+++ b/railties/test/code_statistics_calculator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/code_statistics_calculator"
diff --git a/railties/test/code_statistics_test.rb b/railties/test/code_statistics_test.rb
index e6e3943117..7ad1ac3094 100644
--- a/railties/test/code_statistics_test.rb
+++ b/railties/test/code_statistics_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/code_statistics"
diff --git a/railties/test/command/base_test.rb b/railties/test/command/base_test.rb
index bac3285f48..a49ae8aae7 100644
--- a/railties/test/command/base_test.rb
+++ b/railties/test/command/base_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/command"
require "rails/commands/generate/generate_command"
diff --git a/railties/test/command/spellchecker_test.rb b/railties/test/command/spellchecker_test.rb
new file mode 100644
index 0000000000..e6a7a3957c
--- /dev/null
+++ b/railties/test/command/spellchecker_test.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+require "rails/command/spellchecker"
+
+class Rails::Command::SpellcheckerTest < ActiveSupport::TestCase
+ test "suggests a word correction from dictionary" do
+ assert_equal "thin", Rails::Command::Spellchecker.suggest("tin", from: %w(puma thin cgi))
+ end
+end
diff --git a/railties/test/commands/console_test.rb b/railties/test/commands/console_test.rb
index a7169e16fb..b7cdb8229e 100644
--- a/railties/test/commands/console_test.rb
+++ b/railties/test/commands/console_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "env_helpers"
require "rails/command"
@@ -18,30 +20,30 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
def test_sandbox_option
console = Rails::Console.new(app, parse_arguments(["--sandbox"]))
- assert console.sandbox?
+ assert_predicate console, :sandbox?
end
def test_short_version_of_sandbox_option
console = Rails::Console.new(app, parse_arguments(["-s"]))
- assert console.sandbox?
+ assert_predicate console, :sandbox?
end
def test_no_options
console = Rails::Console.new(app, parse_arguments([]))
- assert !console.sandbox?
+ assert_not_predicate console, :sandbox?
end
def test_start
start
- assert app.console.started?
+ assert_predicate app.console, :started?
assert_match(/Loading \w+ environment \(Rails/, output)
end
def test_start_with_sandbox
start ["--sandbox"]
- assert app.console.started?
+ assert_predicate app.console, :started?
assert app.sandbox
assert_match(/Loading \w+ environment in sandbox \(Rails/, output)
end
@@ -170,21 +172,8 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end
def parse_arguments(args)
- Rails::Command::ConsoleCommand.class_eval do
- alias_method :old_perform, :perform
- define_method(:perform) do
- extract_environment_option_from_argument
-
- options
- end
- end
-
- Rails::Command.invoke(:console, args)
- ensure
- Rails::Command::ConsoleCommand.class_eval do
- undef_method :perform
- alias_method :perform, :old_perform
- undef_method :old_perform
- end
+ command = Rails::Command::ConsoleCommand.new([], args)
+ command.send(:extract_environment_option_from_argument)
+ command.options
end
end
diff --git a/railties/test/commands/credentials_test.rb b/railties/test/commands/credentials_test.rb
new file mode 100644
index 0000000000..663ee73bcd
--- /dev/null
+++ b/railties/test/commands/credentials_test.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "env_helpers"
+require "rails/command"
+require "rails/commands/credentials/credentials_command"
+
+class Rails::Command::CredentialsCommandTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation, EnvHelpers
+
+ setup { build_app }
+
+ teardown { teardown_app }
+
+ test "edit without editor gives hint" do
+ run_edit_command(editor: "").tap do |output|
+ assert_match "No $EDITOR to open file in", output
+ assert_match "bin/rails credentials:edit", output
+ end
+ end
+
+ test "edit credentials" do
+ # Run twice to ensure credentials can be reread after first edit pass.
+ 2.times do
+ assert_match(/access_key_id: 123/, run_edit_command)
+ end
+ end
+
+ test "edit command does not add master key to gitignore when already exist" do
+ run_edit_command
+
+ Dir.chdir(app_path) do
+ gitignore = File.read(".gitignore")
+ assert_equal 1, gitignore.scan(%r|config/master\.key|).length
+ end
+ end
+
+ test "edit command does not overwrite by default if credentials already exists" do
+ run_edit_command(editor: "eval echo api_key: abc >")
+ assert_match(/api_key: abc/, run_show_command)
+
+ run_edit_command
+ assert_match(/api_key: abc/, run_show_command)
+ end
+
+ test "edit command does not add master key when `RAILS_MASTER_KEY` env specified" do
+ Dir.chdir(app_path) do
+ key = IO.binread("config/master.key").strip
+ FileUtils.rm("config/master.key")
+
+ switch_env("RAILS_MASTER_KEY", key) do
+ run_edit_command
+ assert_not File.exist?("config/master.key")
+ end
+ end
+ 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
+ remove_file "config/master.key"
+ add_to_config "config.require_master_key = true"
+
+ assert_match(/Missing encryption key to decrypt file with/, run_show_command(allow_failure: true))
+ end
+
+ test "show command does not raise error when require_master_key is false and master key does not exist" do
+ remove_file "config/master.key"
+ add_to_config "config.require_master_key = false"
+
+ assert_match(/Missing master key to decrypt credentials/, run_show_command)
+ end
+
+ private
+ def run_edit_command(editor: "cat")
+ switch_env("EDITOR", editor) do
+ rails "credentials:edit"
+ end
+ end
+
+ def run_show_command(**options)
+ rails "credentials:show", **options
+ end
+end
diff --git a/railties/test/commands/dbconsole_test.rb b/railties/test/commands/dbconsole_test.rb
index 4f55eb9aa6..0aea21051a 100644
--- a/railties/test/commands/dbconsole_test.rb
+++ b/railties/test/commands/dbconsole_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "minitest/mock"
require "rails/command"
@@ -121,31 +123,31 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
def test_mysql
start(adapter: "mysql2", database: "db")
- assert !aborted
+ assert_not aborted
assert_equal [%w[mysql mysql5], "db"], dbconsole.find_cmd_and_exec_args
end
def test_mysql_full
start(adapter: "mysql2", database: "db", host: "locahost", port: 1234, socket: "socket", username: "user", password: "qwerty", encoding: "UTF-8")
- assert !aborted
+ assert_not aborted
assert_equal [%w[mysql mysql5], "--host=locahost", "--port=1234", "--socket=socket", "--user=user", "--default-character-set=UTF-8", "-p", "db"], dbconsole.find_cmd_and_exec_args
end
def test_mysql_include_password
start({ adapter: "mysql2", database: "db", username: "user", password: "qwerty" }, ["-p"])
- assert !aborted
+ assert_not aborted
assert_equal [%w[mysql mysql5], "--user=user", "--password=qwerty", "db"], dbconsole.find_cmd_and_exec_args
end
def test_postgresql
start(adapter: "postgresql", database: "db")
- assert !aborted
+ assert_not aborted
assert_equal ["psql", "db"], dbconsole.find_cmd_and_exec_args
end
def test_postgresql_full
start(adapter: "postgresql", database: "db", username: "user", password: "q1w2e3", host: "host", port: 5432)
- assert !aborted
+ assert_not aborted
assert_equal ["psql", "db"], dbconsole.find_cmd_and_exec_args
assert_equal "user", ENV["PGUSER"]
assert_equal "host", ENV["PGHOST"]
@@ -155,7 +157,7 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
def test_postgresql_include_password
start({ adapter: "postgresql", database: "db", username: "user", password: "q1w2e3" }, ["-p"])
- assert !aborted
+ assert_not aborted
assert_equal ["psql", "db"], dbconsole.find_cmd_and_exec_args
assert_equal "user", ENV["PGUSER"]
assert_equal "q1w2e3", ENV["PGPASSWORD"]
@@ -163,13 +165,13 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
def test_sqlite3
start(adapter: "sqlite3", database: "db.sqlite3")
- assert !aborted
+ assert_not aborted
assert_equal ["sqlite3", Rails.root.join("db.sqlite3").to_s], dbconsole.find_cmd_and_exec_args
end
def test_sqlite3_mode
start({ adapter: "sqlite3", database: "db.sqlite3" }, ["--mode", "html"])
- assert !aborted
+ assert_not aborted
assert_equal ["sqlite3", "-html", Rails.root.join("db.sqlite3").to_s], dbconsole.find_cmd_and_exec_args
end
@@ -180,30 +182,36 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
def test_sqlite3_db_absolute_path
start(adapter: "sqlite3", database: "/tmp/db.sqlite3")
- assert !aborted
+ assert_not aborted
assert_equal ["sqlite3", "/tmp/db.sqlite3"], dbconsole.find_cmd_and_exec_args
end
def test_sqlite3_db_without_defined_rails_root
Rails.stub(:respond_to?, false) do
start(adapter: "sqlite3", database: "config/db.sqlite3")
- assert !aborted
+ assert_not aborted
assert_equal ["sqlite3", Rails.root.join("../config/db.sqlite3").to_s], dbconsole.find_cmd_and_exec_args
end
end
def test_oracle
start(adapter: "oracle", database: "db", username: "user", password: "secret")
- assert !aborted
+ assert_not aborted
assert_equal ["sqlplus", "user@db"], dbconsole.find_cmd_and_exec_args
end
def test_oracle_include_password
start({ adapter: "oracle", database: "db", username: "user", password: "secret" }, ["-p"])
- assert !aborted
+ assert_not aborted
assert_equal ["sqlplus", "user/secret@db"], dbconsole.find_cmd_and_exec_args
end
+ def test_sqlserver
+ start(adapter: "sqlserver", database: "db", username: "user", password: "secret", host: "localhost", port: 1433)
+ assert_not aborted
+ assert_equal ["sqsh", "-D", "db", "-U", "user", "-P", "secret", "-S", "localhost:1433"], dbconsole.find_cmd_and_exec_args
+ end
+
def test_unknown_command_line_client
start(adapter: "unknown", database: "db")
assert aborted
diff --git a/railties/test/commands/encrypted_test.rb b/railties/test/commands/encrypted_test.rb
new file mode 100644
index 0000000000..9fc73d5f18
--- /dev/null
+++ b/railties/test/commands/encrypted_test.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "env_helpers"
+require "rails/command"
+require "rails/commands/encrypted/encrypted_command"
+
+class Rails::Command::EncryptedCommandTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation, EnvHelpers
+
+ setup :build_app
+ teardown :teardown_app
+
+ test "edit without editor gives hint" do
+ run_edit_command("config/tokens.yml.enc", editor: "").tap do |output|
+ assert_match "No $EDITOR to open file in", output
+ assert_match "bin/rails encrypted:edit", output
+ end
+ end
+
+ test "edit encrypted file" do
+ # Run twice to ensure file can be reread after first edit pass.
+ 2.times do
+ assert_match(/access_key_id: 123/, run_edit_command("config/tokens.yml.enc"))
+ end
+ end
+
+ test "edit command does not add master key to gitignore when already exist" do
+ run_edit_command("config/tokens.yml.enc")
+
+ Dir.chdir(app_path) do
+ assert_match "/config/master.key", File.read(".gitignore")
+ end
+ end
+
+ test "edit command does not add master key when `RAILS_MASTER_KEY` env specified" do
+ Dir.chdir(app_path) do
+ key = IO.binread("config/master.key").strip
+ FileUtils.rm("config/master.key")
+
+ switch_env("RAILS_MASTER_KEY", key) do
+ run_edit_command("config/tokens.yml.enc")
+ assert_not File.exist?("config/master.key")
+ end
+ end
+ end
+
+ test "edit encrypts file with custom key" do
+ run_edit_command("config/tokens.yml.enc", key: "config/tokens.key")
+
+ Dir.chdir(app_path) do
+ assert File.exist?("config/tokens.yml.enc")
+ assert File.exist?("config/tokens.key")
+
+ assert_match "/config/tokens.key", File.read(".gitignore")
+ end
+
+ assert_match(/access_key_id: 123/, run_edit_command("config/tokens.yml.enc", key: "config/tokens.key"))
+ end
+
+ test "show encrypted file with custom key" do
+ run_edit_command("config/tokens.yml.enc", key: "config/tokens.key")
+
+ assert_match(/access_key_id: 123/, run_show_command("config/tokens.yml.enc", key: "config/tokens.key"))
+ end
+
+ test "show command raise error when require_master_key is specified and key does not exist" do
+ add_to_config "config.require_master_key = true"
+
+ assert_match(/Missing encryption key to decrypt file with/,
+ run_show_command("config/tokens.yml.enc", key: "unexist.key", allow_failure: true))
+ end
+
+ test "show command does not raise error when require_master_key is false and master key does not exist" do
+ remove_file "config/master.key"
+ add_to_config "config.require_master_key = false"
+
+ assert_match(/Missing 'config\/master\.key' to decrypt data/, run_show_command("config/tokens.yml.enc"))
+ end
+
+ test "won't corrupt encrypted file when passed wrong key" do
+ run_edit_command("config/tokens.yml.enc", key: "config/tokens.key")
+
+ assert_match "passed the wrong key",
+ run_edit_command("config/tokens.yml.enc", allow_failure: true)
+
+ assert_match(/access_key_id: 123/, run_show_command("config/tokens.yml.enc", key: "config/tokens.key"))
+ end
+
+ private
+ def run_edit_command(file, key: nil, editor: "cat", **options)
+ switch_env("EDITOR", editor) do
+ rails "encrypted:edit", prepare_args(file, key), **options
+ end
+ end
+
+ def run_show_command(file, key: nil, **options)
+ rails "encrypted:show", prepare_args(file, key), **options
+ end
+
+ def prepare_args(file, key)
+ args = [ file ]
+ args.push("--key", key) if key
+ args
+ end
+end
diff --git a/railties/test/commands/routes_test.rb b/railties/test/commands/routes_test.rb
new file mode 100644
index 0000000000..77ed2bda61
--- /dev/null
+++ b/railties/test/commands/routes_test.rb
@@ -0,0 +1,175 @@
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
+require "rails/command"
+require "rails/commands/routes/routes_command"
+require "io/console/size"
+
+class Rails::Command::RoutesTest < ActiveSupport::TestCase
+ setup :build_app
+ teardown :teardown_app
+
+ test "singular resource output in rails routes" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ resource :post
+ end
+ RUBY
+
+ expected_output = [" Prefix Verb URI Pattern Controller#Action",
+ " new_post GET /post/new(.:format) posts#new",
+ "edit_post GET /post/edit(.:format) posts#edit",
+ " post GET /post(.:format) posts#show",
+ " PATCH /post(.:format) posts#update",
+ " PUT /post(.:format) posts#update",
+ " DELETE /post(.:format) posts#destroy",
+ " POST /post(.:format) posts#create\n"].join("\n")
+
+ output = run_routes_command(["-c", "PostController"])
+ assert_equal expected_output, output
+ end
+
+ test "rails routes with global search key" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get '/cart', to: 'cart#show'
+ post '/cart', to: 'cart#create'
+ get '/basketballs', to: 'basketball#index'
+ end
+ RUBY
+
+ output = run_routes_command(["-g", "show"])
+ assert_equal <<~MESSAGE, output
+ Prefix Verb URI Pattern Controller#Action
+ cart GET /cart(.:format) cart#show
+ rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
+ rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
+ rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
+ MESSAGE
+
+ output = run_routes_command(["-g", "POST"])
+ assert_equal <<~MESSAGE, output
+ Prefix Verb URI Pattern Controller#Action
+ POST /cart(.:format) cart#create
+ rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
+ MESSAGE
+
+ output = run_routes_command(["-g", "basketballs"])
+ assert_equal " Prefix Verb URI Pattern Controller#Action\n" \
+ "basketballs GET /basketballs(.:format) basketball#index\n", output
+ end
+
+ test "rails routes with controller search key" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get '/cart', to: 'cart#show'
+ get '/basketball', to: 'basketball#index'
+ end
+ RUBY
+
+ output = run_routes_command(["-c", "cart"])
+ assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+
+ output = run_routes_command(["-c", "Cart"])
+ assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+
+ output = run_routes_command(["-c", "CartController"])
+ assert_equal "Prefix Verb URI Pattern Controller#Action\n cart GET /cart(.:format) cart#show\n", output
+ end
+
+ test "rails routes with namespaced controller search key" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ namespace :admin do
+ resource :post
+ end
+ end
+ RUBY
+
+ expected_output = [" Prefix Verb URI Pattern Controller#Action",
+ " new_admin_post GET /admin/post/new(.:format) admin/posts#new",
+ "edit_admin_post GET /admin/post/edit(.:format) admin/posts#edit",
+ " admin_post GET /admin/post(.:format) admin/posts#show",
+ " PATCH /admin/post(.:format) admin/posts#update",
+ " PUT /admin/post(.:format) admin/posts#update",
+ " DELETE /admin/post(.:format) admin/posts#destroy",
+ " POST /admin/post(.:format) admin/posts#create\n"].join("\n")
+
+ output = run_routes_command(["-c", "Admin::PostController"])
+ assert_equal expected_output, output
+
+ output = run_routes_command(["-c", "PostController"])
+ assert_equal expected_output, output
+ end
+
+ test "rails routes displays message when no routes are defined" do
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ end
+ RUBY
+
+ assert_equal <<~MESSAGE, run_routes_command
+ Prefix Verb URI Pattern Controller#Action
+ rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
+ rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
+ rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
+ update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
+ rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
+ MESSAGE
+ end
+
+ test "rails routes with expanded option" do
+ begin
+ previous_console_winsize = IO.console.winsize
+ IO.console.winsize = [0, 27]
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ get '/cart', to: 'cart#show'
+ end
+ RUBY
+
+ output = run_routes_command(["--expanded"])
+
+ assert_equal <<~MESSAGE, output
+ --[ Route 1 ]--------------
+ Prefix | cart
+ Verb | GET
+ URI | /cart(.:format)
+ Controller#Action | cart#show
+ --[ Route 2 ]--------------
+ Prefix | rails_service_blob
+ Verb | GET
+ URI | /rails/active_storage/blobs/:signed_id/*filename(.:format)
+ Controller#Action | active_storage/blobs#show
+ --[ Route 3 ]--------------
+ Prefix | rails_blob_representation
+ Verb | GET
+ URI | /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format)
+ Controller#Action | active_storage/representations#show
+ --[ Route 4 ]--------------
+ Prefix | rails_disk_service
+ Verb | GET
+ URI | /rails/active_storage/disk/:encoded_key/*filename(.:format)
+ Controller#Action | active_storage/disk#show
+ --[ Route 5 ]--------------
+ Prefix | update_rails_disk_service
+ Verb | PUT
+ URI | /rails/active_storage/disk/:encoded_token(.:format)
+ Controller#Action | active_storage/disk#update
+ --[ Route 6 ]--------------
+ Prefix | rails_direct_uploads
+ Verb | POST
+ URI | /rails/active_storage/direct_uploads(.:format)
+ Controller#Action | active_storage/direct_uploads#create
+ MESSAGE
+ ensure
+ IO.console.winsize = previous_console_winsize
+ end
+ end
+
+ private
+ def run_routes_command(args = [])
+ rails "routes", args
+ end
+end
diff --git a/railties/test/commands/secrets_test.rb b/railties/test/commands/secrets_test.rb
index 3771919849..6b9f284a0c 100644
--- a/railties/test/commands/secrets_test.rb
+++ b/railties/test/commands/secrets_test.rb
@@ -1,25 +1,45 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
+require "env_helpers"
require "rails/command"
require "rails/commands/secrets/secrets_command"
class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation, EnvHelpers
+
+ setup :build_app
+ teardown :teardown_app
- def setup
- build_app
+ test "edit without editor gives hint" do
+ assert_match "No $EDITOR to open decrypted secrets in", run_edit_command(editor: "")
end
- def teardown
- teardown_app
+ test "encrypted secrets are deprecated when using credentials" do
+ assert_match "Encrypted secrets is deprecated", run_setup_command
+ assert_equal 1, $?.exitstatus
+ assert_not File.exist?("config/secrets.yml.enc")
end
- test "edit without editor gives hint" do
- assert_match "No $EDITOR to open decrypted secrets in", run_edit_command(editor: "")
+ test "encrypted secrets are deprecated when running edit without setup" do
+ assert_match "Encrypted secrets is deprecated", run_setup_command
+ assert_equal 1, $?.exitstatus
+ assert_not File.exist?("config/secrets.yml.enc")
+ end
+
+ test "encrypted secrets are deprecated for 5.1 config/secrets.yml apps" do
+ Dir.chdir(app_path) do
+ FileUtils.rm("config/credentials.yml.enc")
+ FileUtils.touch("config/secrets.yml")
+
+ assert_match "Encrypted secrets is deprecated", run_setup_command
+ assert_equal 1, $?.exitstatus
+ assert_not File.exist?("config/secrets.yml.enc")
+ end
end
test "edit secrets" do
- # Runs setup before first edit.
- assert_match(/Adding config\/secrets\.yml\.key to store the encryption key/, run_edit_command)
+ prevent_deprecation
# Run twice to ensure encrypted secrets can be reread after first edit pass.
2.times do
@@ -28,20 +48,30 @@ class Rails::Command::SecretsCommandTest < ActiveSupport::TestCase
end
test "show secrets" do
- run_setup_command
+ prevent_deprecation
+
assert_match(/external_api_key: 1466aac22e6a869134be3d09b9e89232fc2c2289/, run_show_command)
end
private
+ def prevent_deprecation
+ Dir.chdir(app_path) do
+ File.write("config/secrets.yml.key", "f731758c639da2604dfb6bf3d1025de8")
+ File.write("config/secrets.yml.enc", "sEB0mHxDbeP1/KdnMk00wyzPFACl9K6t0cZWn5/Mfx/YbTHvnI07vrneqHg9kaH3wOS7L6pIQteu1P077OtE4BSx/ZRc/sgQPHyWu/tXsrfHqnPNpayOF/XZqizE91JacSFItNMWpuPsp9ynbzz+7cGhoB1S4aPNIU6u0doMrzdngDbijsaAFJmsHIQh6t/QHoJx--8aMoE0PvUWmw1Iqz--ldFqnM/K0g9k17M8PKoN/Q==")
+ end
+ end
+
def run_edit_command(editor: "cat")
- Dir.chdir(app_path) { `EDITOR="#{editor}" bin/rails secrets:edit` }
+ switch_env("EDITOR", editor) do
+ rails "secrets:edit", allow_failure: true
+ end
end
def run_show_command
- Dir.chdir(app_path) { `bin/rails secrets:show` }
+ rails "secrets:show", allow_failure: true
end
def run_setup_command
- Dir.chdir(app_path) { `bin/rails secrets:setup` }
+ rails "secrets:setup", allow_failure: true
end
end
diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb
index 722323efdc..e7a56b3e6d 100644
--- a/railties/test/commands/server_test.rb
+++ b/railties/test/commands/server_test.rb
@@ -1,13 +1,15 @@
-require "abstract_unit"
+# frozen_string_literal: true
+
+require "isolation/abstract_unit"
require "env_helpers"
require "rails/command"
require "rails/commands/server/server_command"
-class Rails::ServerTest < ActiveSupport::TestCase
+class Rails::Command::ServerCommandTest < ActiveSupport::TestCase
include EnvHelpers
def test_environment_with_server_option
- args = ["thin", "-e", "production"]
+ args = ["-u", "thin", "-e", "production"]
options = parse_arguments(args)
assert_equal "production", options[:environment]
assert_equal "thin", options[:server]
@@ -20,8 +22,38 @@ class Rails::ServerTest < ActiveSupport::TestCase
assert_nil options[:server]
end
+ def test_explicit_using_option
+ args = ["-u", "thin"]
+ options = parse_arguments(args)
+ assert_equal "thin", options[:server]
+ end
+
+ def test_using_server_mistype
+ assert_match(/Could not find server "tin". Maybe you meant "thin"?/, run_command("--using", "tin"))
+ end
+
+ def test_using_positional_argument_deprecation
+ assert_match(/DEPRECATION WARNING/, run_command("tin"))
+ end
+
+ def test_using_known_server_that_isnt_in_the_gemfile
+ assert_match(/Could not load server "unicorn". Maybe you need to the add it to the Gemfile/, run_command("-u", "unicorn"))
+ end
+
+ def test_daemon_with_option
+ args = ["-d"]
+ options = parse_arguments(args)
+ assert_equal true, options[:daemonize]
+ end
+
+ def test_daemon_without_option
+ args = []
+ options = parse_arguments(args)
+ assert_equal false, options[:daemonize]
+ end
+
def test_server_option_without_environment
- args = ["thin"]
+ args = ["-u", "thin"]
with_rack_env nil do
with_rails_env nil do
options = parse_arguments(args)
@@ -58,6 +90,15 @@ class Rails::ServerTest < ActiveSupport::TestCase
def test_environment_with_host
switch_env "HOST", "1.2.3.4" do
+ assert_deprecated do
+ options = parse_arguments
+ assert_equal "1.2.3.4", options[:Host]
+ end
+ end
+ end
+
+ def test_environment_with_binding
+ switch_env "BINDING", "1.2.3.4" do
options = parse_arguments
assert_equal "1.2.3.4", options[:Host]
end
@@ -79,6 +120,18 @@ class Rails::ServerTest < ActiveSupport::TestCase
assert_equal false, options[:caching]
end
+ def test_early_hints_with_option
+ args = ["--early-hints"]
+ options = parse_arguments(args)
+ assert_equal true, options[:early_hints]
+ end
+
+ def test_early_hints_is_nil_by_default
+ args = []
+ options = parse_arguments(args)
+ assert_nil options[:early_hints]
+ end
+
def test_log_stdout
with_rack_env nil do
with_rails_env nil do
@@ -152,7 +205,7 @@ class Rails::ServerTest < ActiveSupport::TestCase
assert_equal 3000, options[:Port]
end
- switch_env "HOST", "1.2.3.4" do
+ switch_env "BINDING", "1.2.3.4" do
args = ["-b", "127.0.0.1"]
options = parse_arguments(args)
assert_equal "127.0.0.1", options[:Host]
@@ -171,6 +224,11 @@ class Rails::ServerTest < ActiveSupport::TestCase
server_options = parse_arguments(["--port=3001"])
assert_equal [:Port], server_options[:user_supplied_options]
+
+ switch_env "BINDING", "1.2.3.4" do
+ server_options = parse_arguments
+ assert_equal [:Host], server_options[:user_supplied_options]
+ end
end
def test_default_options
@@ -188,14 +246,27 @@ class Rails::ServerTest < ActiveSupport::TestCase
ARGV.replace args
options = parse_arguments(args)
- expected = "bin/rails server -p 4567 -b 127.0.0.1 -c dummy_config.ru -d -e test -P tmp/server.pid -C"
+ expected = "bin/rails server -p 4567 -b 127.0.0.1 -c dummy_config.ru -d -e test -P tmp/server.pid -C --restart"
assert_equal expected, options[:restart_cmd]
ensure
ARGV.replace original_args
end
+ def test_served_url
+ args = %w(-u webrick -b 127.0.0.1 -p 4567)
+ server = Rails::Server.new(parse_arguments(args))
+ assert_equal "http://127.0.0.1:4567", server.served_url
+ end
+
private
+ def run_command(*args)
+ build_app
+ rails "server", *args
+ ensure
+ teardown_app
+ end
+
def parse_arguments(args = [])
Rails::Command::ServerCommand.new([], args).server_options
end
diff --git a/railties/test/configuration/middleware_stack_proxy_test.rb b/railties/test/configuration/middleware_stack_proxy_test.rb
index 559ce72693..bc72b7f0c9 100644
--- a/railties/test/configuration/middleware_stack_proxy_test.rb
+++ b/railties/test/configuration/middleware_stack_proxy_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support"
require "active_support/testing/autorun"
require "rails/configuration"
diff --git a/railties/test/console_helpers.rb b/railties/test/console_helpers.rb
new file mode 100644
index 0000000000..8350fce5ee
--- /dev/null
+++ b/railties/test/console_helpers.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+begin
+ require "pty"
+rescue LoadError
+end
+
+module ConsoleHelpers
+ def assert_output(expected, io, timeout = 10)
+ timeout = Time.now + timeout
+
+ output = "".dup
+ 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
diff --git a/railties/test/engine/commands_test.rb b/railties/test/engine/commands_test.rb
index b1c937143f..aeb64d445b 100644
--- a/railties/test/engine/commands_test.rb
+++ b/railties/test/engine/commands_test.rb
@@ -1,10 +1,11 @@
+# frozen_string_literal: true
+
require "abstract_unit"
-begin
- require "pty"
-rescue LoadError
-end
+require "console_helpers"
class Rails::Engine::CommandsTest < ActiveSupport::TestCase
+ include ConsoleHelpers
+
def setup
@destination_root = Dir.mktmpdir("bukkits")
Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` }
@@ -64,19 +65,6 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase
"#{@destination_root}/bukkits"
end
- def assert_output(expected, io, timeout = 10)
- 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 spawn_command(command, fd)
Process.spawn(
"#{plugin_path}/bin/rails #{command}",
@@ -84,10 +72,6 @@ class Rails::Engine::CommandsTest < ActiveSupport::TestCase
)
end
- def available_pty?
- defined?(PTY) && PTY.respond_to?(:open)
- end
-
def kill(pid)
Process.kill("TERM", pid)
Process.wait(pid)
diff --git a/railties/test/engine/test_test.rb b/railties/test/engine/test_test.rb
new file mode 100644
index 0000000000..18af85a0aa
--- /dev/null
+++ b/railties/test/engine/test_test.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class Rails::Engine::TestTest < ActiveSupport::TestCase
+ setup do
+ @destination_root = Dir.mktmpdir("bukkits")
+ Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` }
+ end
+
+ teardown do
+ FileUtils.rm_rf(@destination_root)
+ end
+
+ test "automatically synchronize test schema" do
+ Dir.chdir(plugin_path) do
+ # In order to confirm that migration files are loaded, generate multiple migration files.
+ `bin/rails generate model user name:string;
+ bin/rails generate model todo name:string;
+ RAILS_ENV=development bin/rails db:migrate`
+
+ output = `bin/rails test test/models/bukkits/user_test.rb`
+ assert_includes(output, "0 runs, 0 assertions, 0 failures, 0 errors, 0 skips")
+ end
+ end
+
+ private
+ def plugin_path
+ "#{@destination_root}/bukkits"
+ end
+end
diff --git a/railties/test/engine_test.rb b/railties/test/engine_test.rb
index 248afa2d2c..19379e200c 100644
--- a/railties/test/engine_test.rb
+++ b/railties/test/engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
class EngineTest < ActiveSupport::TestCase
@@ -9,7 +11,7 @@ class EngineTest < ActiveSupport::TestCase
end
end
- assert !engine.routes?
+ assert_not_predicate engine, :routes?
end
def test_application_can_be_subclassed
diff --git a/railties/test/env_helpers.rb b/railties/test/env_helpers.rb
index 1f64d5fda3..336832b867 100644
--- a/railties/test/env_helpers.rb
+++ b/railties/test/env_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails"
module EnvHelpers
diff --git a/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml b/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml
deleted file mode 100644
index fe80872a16..0000000000
--- a/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml
+++ /dev/null
@@ -1 +0,0 @@
-# an empty YAML file - any content in here seems to get parsed as a string \ No newline at end of file
diff --git a/railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb b/railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb
deleted file mode 100644
index 636bc1a8ab..0000000000
--- a/railties/test/fixtures/about_yml_plugins/bad_about_yml/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-# intentionally empty
diff --git a/railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb b/railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb
deleted file mode 100644
index 636bc1a8ab..0000000000
--- a/railties/test/fixtures/about_yml_plugins/plugin_without_about_yml/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-# intentionally empty
diff --git a/railties/test/fixtures/lib/create_test_dummy_template.rb b/railties/test/fixtures/lib/create_test_dummy_template.rb
index e4378bbd1a..b9eb6a912d 100644
--- a/railties/test/fixtures/lib/create_test_dummy_template.rb
+++ b/railties/test/fixtures/lib/create_test_dummy_template.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
create_dummy_app("spec/dummy")
diff --git a/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb b/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb
index 1139350b94..f196971f20 100644
--- a/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb
+++ b/railties/test/fixtures/lib/generators/active_record/fixjour_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators/active_record"
module ActiveRecord
diff --git a/railties/test/fixtures/lib/generators/fixjour_generator.rb b/railties/test/fixtures/lib/generators/fixjour_generator.rb
index ef3e9edbed..22197835a8 100644
--- a/railties/test/fixtures/lib/generators/fixjour_generator.rb
+++ b/railties/test/fixtures/lib/generators/fixjour_generator.rb
@@ -1,2 +1,4 @@
+# frozen_string_literal: true
+
class FixjourGenerator < Rails::Generators::NamedBase
end
diff --git a/railties/test/fixtures/lib/generators/model_generator.rb b/railties/test/fixtures/lib/generators/model_generator.rb
index 0905fa9631..3009472c3d 100644
--- a/railties/test/fixtures/lib/generators/model_generator.rb
+++ b/railties/test/fixtures/lib/generators/model_generator.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
raise "I should never be loaded"
diff --git a/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb b/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb
index 701515440a..5a847a8bd2 100644
--- a/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb
+++ b/railties/test/fixtures/lib/generators/usage_template/usage_template_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "rails/generators"
class UsageTemplateGenerator < Rails::Generators::Base
diff --git a/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb b/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb
index d1de8c56fa..159843866c 100644
--- a/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb
+++ b/railties/test/fixtures/lib/rails/generators/foobar/foobar_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Foobar
class FoobarGenerator < Rails::Generators::Base
end
diff --git a/railties/test/fixtures/lib/template.rb b/railties/test/fixtures/lib/template.rb
index c14a1a8784..44083c25e8 100644
--- a/railties/test/fixtures/lib/template.rb
+++ b/railties/test/fixtures/lib/template.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
say "It works from file!"
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index 03b29be907..f421207025 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/app/app_generator"
require "env_helpers"
@@ -69,10 +71,17 @@ class ActionsTest < Rails::Generators::TestCase
def test_gem_with_version_should_include_version_in_gemfile
run_generator
-
- action :gem, "rspec", ">=2.0.0.a5"
-
- assert_file "Gemfile", /gem 'rspec', '>=2.0.0.a5'/
+ action :gem, "rspec", ">= 2.0.0.a5"
+ action :gem, "RedCloth", ">= 4.1.0", "< 4.2.0"
+ action :gem, "nokogiri", version: ">= 1.4.2"
+ action :gem, "faker", version: [">= 0.1.0", "< 0.3.0"]
+
+ assert_file "Gemfile" do |content|
+ assert_match(/gem 'rspec', '>= 2\.0\.0\.a5'/, content)
+ assert_match(/gem 'RedCloth', '>= 4\.1\.0', '< 4\.2\.0'/, content)
+ assert_match(/gem 'nokogiri', '>= 1\.4\.2'/, content)
+ assert_match(/gem 'faker', '>= 0\.1\.0', '< 0\.3\.0'/, content)
+ end
end
def test_gem_should_insert_on_separate_lines
@@ -139,14 +148,14 @@ class ActionsTest < Rails::Generators::TestCase
run_generator
autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]'
action :environment, autoload_paths
- assert_file "config/application.rb", / class Application < Rails::Application\n #{Regexp.escape(autoload_paths)}/
+ assert_file "config/application.rb", / class Application < Rails::Application\n #{Regexp.escape(autoload_paths)}\n/
end
def test_environment_should_include_data_in_environment_initializer_block_with_env_option
run_generator
autoload_paths = 'config.autoload_paths += %w["#{Rails.root}/app/extras"]'
action :environment, autoload_paths, env: "development"
- assert_file "config/environments/development.rb", /Rails\.application\.configure do\n #{Regexp.escape(autoload_paths)}/
+ assert_file "config/environments/development.rb", /Rails\.application\.configure do\n #{Regexp.escape(autoload_paths)}\n/
end
def test_environment_with_block_should_include_block_contents_in_environment_initializer_block
@@ -163,6 +172,26 @@ class ActionsTest < Rails::Generators::TestCase
end
end
+ def test_environment_with_block_should_include_block_contents_with_multiline_data_in_environment_initializer_block
+ run_generator
+ data = <<-RUBY
+ config.encoding = "utf-8"
+ config.time_zone = "UTC"
+ RUBY
+ action(:environment) { data }
+ assert_file "config/application.rb", / class Application < Rails::Application\n#{Regexp.escape(data.strip_heredoc.indent(4))}/
+ end
+
+ def test_environment_should_include_block_contents_with_multiline_data_in_environment_initializer_block_with_env_option
+ run_generator
+ data = <<-RUBY
+ config.encoding = "utf-8"
+ config.time_zone = "UTC"
+ RUBY
+ action(:environment, nil, env: "development") { data }
+ assert_file "config/environments/development.rb", /Rails\.application\.configure do\n#{Regexp.escape(data.strip_heredoc.indent(2))}/
+ end
+
def test_git_with_symbol_should_run_command_using_git_scm
assert_called_with(generator, :run, ["git init"]) do
action :git, :init
@@ -177,22 +206,62 @@ class ActionsTest < Rails::Generators::TestCase
def test_vendor_should_write_data_to_file_in_vendor
action :vendor, "vendor_file.rb", "# vendor data"
- assert_file "vendor/vendor_file.rb", "# vendor data"
+ assert_file "vendor/vendor_file.rb", "# vendor data\n"
+ end
+
+ def test_vendor_should_write_data_to_file_with_block_in_vendor
+ code = <<-RUBY
+ puts "one"
+ puts "two"
+ puts "three"
+ RUBY
+ action(:vendor, "vendor_file.rb") { code }
+ assert_file "vendor/vendor_file.rb", code.strip_heredoc
end
def test_lib_should_write_data_to_file_in_lib
action :lib, "my_library.rb", "class MyLibrary"
- assert_file "lib/my_library.rb", "class MyLibrary"
+ assert_file "lib/my_library.rb", "class MyLibrary\n"
+ end
+
+ def test_lib_should_write_data_to_file_with_block_in_lib
+ code = <<-RUBY
+ class MyLib
+ MY_CONSTANT = 123
+ end
+ RUBY
+ action(:lib, "my_library.rb") { code }
+ assert_file "lib/my_library.rb", code.strip_heredoc
end
def test_rakefile_should_write_date_to_file_in_lib_tasks
action :rakefile, "myapp.rake", "task run: [:environment]"
- assert_file "lib/tasks/myapp.rake", "task run: [:environment]"
+ assert_file "lib/tasks/myapp.rake", "task run: [:environment]\n"
+ end
+
+ def test_rakefile_should_write_date_to_file_with_block_in_lib_tasks
+ code = <<-RUBY
+ task rock: :environment do
+ puts "Rockin'"
+ end
+ RUBY
+ action(:rakefile, "myapp.rake") { code }
+ assert_file "lib/tasks/myapp.rake", code.strip_heredoc
end
def test_initializer_should_write_date_to_file_in_config_initializers
action :initializer, "constants.rb", "MY_CONSTANT = 42"
- assert_file "config/initializers/constants.rb", "MY_CONSTANT = 42"
+ assert_file "config/initializers/constants.rb", "MY_CONSTANT = 42\n"
+ end
+
+ def test_initializer_should_write_date_to_file_with_block_in_config_initializers
+ code = <<-RUBY
+ MyLib.configure do |config|
+ config.value = 123
+ end
+ RUBY
+ action(:initializer, "constants.rb") { code }
+ assert_file "config/initializers/constants.rb", code.strip_heredoc
end
def test_generate_should_run_script_generate_with_argument_and_options
@@ -239,6 +308,14 @@ class ActionsTest < Rails::Generators::TestCase
end
end
+ test "rake command with capture option should run rake command with capture" do
+ assert_called_with(generator, :run, ["rake log:clear RAILS_ENV=development", verbose: false, capture: true]) do
+ with_rails_env nil do
+ action :rake, "log:clear", capture: true
+ end
+ end
+ end
+
test "rails command should run rails_command with default env" do
assert_called_with(generator, :run, ["rails log:clear RAILS_ENV=development", verbose: false]) do
with_rails_env nil do
@@ -277,6 +354,14 @@ class ActionsTest < Rails::Generators::TestCase
end
end
+ test "rails command with capture option should run rails_command with capture" do
+ assert_called_with(generator, :run, ["rails log:clear RAILS_ENV=development", verbose: false, capture: true]) do
+ with_rails_env nil do
+ action :rails_command, "log:clear", capture: true
+ end
+ end
+ end
+
def test_capify_should_run_the_capify_command
content = capture(:stderr) do
assert_called_with(generator, :run, ["capify .", verbose: false]) do
diff --git a/railties/test/generators/api_app_generator_test.rb b/railties/test/generators/api_app_generator_test.rb
index a19e0f0dd8..9c523ad372 100644
--- a/railties/test/generators/api_app_generator_test.rb
+++ b/railties/test/generators/api_app_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/app/app_generator"
@@ -11,7 +13,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
Rails.application = TestApp::Application
super
- Kernel::silence_warnings do
+ Kernel.silence_warnings do
Thor::Base.shell.send(:attr_accessor, :always_force)
@shell = Thor::Base.shell.new
@shell.send(:always_force=, true)
@@ -33,26 +35,26 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
def test_api_modified_files
run_generator
+ assert_file ".gitignore" do |content|
+ assert_no_match(/\/public\/assets/, content)
+ end
+
assert_file "Gemfile" do |content|
assert_no_match(/gem 'coffee-rails'/, content)
assert_no_match(/gem 'sass-rails'/, content)
assert_no_match(/gem 'web-console'/, content)
+ assert_no_match(/gem 'capybara'/, content)
+ assert_no_match(/gem 'selenium-webdriver'/, content)
assert_match(/# gem 'jbuilder'/, content)
+ assert_match(/# gem 'rack-cors'/, content)
end
- assert_file "config/application.rb" do |content|
- assert_match(/config.api_only = true/, content)
- end
-
- assert_file "config/initializers/cors.rb"
-
- assert_file "config/initializers/wrap_parameters.rb"
-
+ assert_file "config/application.rb", /config\.api_only = true/
assert_file "app/controllers/application_controller.rb", /ActionController::API/
end
def test_generator_if_skip_action_cable_is_given
- run_generator [destination_root, "--skip-action-cable"]
+ run_generator [destination_root, "--api", "--skip-action-cable"]
assert_file "config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
assert_no_file "config/cable.yml"
assert_no_file "app/channels"
@@ -61,22 +63,40 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_generator_if_skip_action_mailer_is_given
+ run_generator [destination_root, "--api", "--skip-action-mailer"]
+ assert_file "config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
+ assert_file "config/environments/development.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_file "config/environments/test.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_file "config/environments/production.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_no_directory "app/mailers"
+ assert_no_directory "test/mailers"
+ assert_no_directory "app/views"
+ end
+
def test_app_update_does_not_generate_unnecessary_config_files
run_generator
generator = Rails::Generators::AppGenerator.new ["rails"],
- { api: true, update: true }, destination_root: destination_root, shell: @shell
+ { api: true, update: true }, { destination_root: destination_root, shell: @shell }
quietly { generator.send(:update_config_files) }
assert_no_file "config/initializers/cookies_serializer.rb"
assert_no_file "config/initializers/assets.rb"
+ assert_no_file "config/initializers/content_security_policy.rb"
end
def test_app_update_does_not_generate_unnecessary_bin_files
run_generator
generator = Rails::Generators::AppGenerator.new ["rails"],
- { api: true, update: true }, destination_root: destination_root, shell: @shell
+ { api: true, update: true }, { destination_root: destination_root, shell: @shell }
quietly { generator.send(:update_bin_files) }
assert_no_file "bin/yarn"
@@ -85,20 +105,49 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
private
def default_files
- files = %W(
- .gitignore
+ %w(.gitignore
+ .ruby-version
+ README.md
Gemfile
Rakefile
config.ru
+ app/channels
app/controllers
app/mailers
app/models
+ app/views/layouts
app/views/layouts/mailer.html.erb
app/views/layouts/mailer.text.erb
+ bin/bundle
+ bin/rails
+ bin/rake
+ bin/setup
+ bin/update
+ 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/backtrace_silencers.rb
+ config/initializers/cors.rb
+ config/initializers/filter_parameter_logging.rb
+ config/initializers/inflections.rb
+ config/initializers/mime_types.rb
+ config/initializers/wrap_parameters.rb
config/locales
+ config/locales/en.yml
+ config/puma.rb
+ config/routes.rb
+ config/credentials.yml.enc
+ config/spring.rb
+ config/storage.yml
db
+ db/seeds.rb
lib
lib/tasks
log
@@ -109,8 +158,6 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
tmp
vendor
)
- files.concat %w(bin/bundle bin/rails bin/rake)
- files
end
def skipped_files
@@ -120,6 +167,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
bin/yarn
config/initializers/assets.rb
config/initializers/cookies_serializer.rb
+ config/initializers/content_security_policy.rb
lib/assets
test/helpers
tmp/cache/assets
@@ -128,7 +176,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
public/500.html
public/apple-touch-icon-precomposed.png
public/apple-touch-icon.png
- public/favicon.icon
+ public/favicon.ico
package.json
)
end
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index ffdee3a6b5..fa7bcfd6d6 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/app/app_generator"
require "generators/shared_generator_tests"
DEFAULT_APP_FILES = %w(
.gitignore
+ .ruby-version
README.md
Gemfile
Rakefile
@@ -53,6 +56,7 @@ DEFAULT_APP_FILES = %w(
config/initializers/assets.rb
config/initializers/backtrace_silencers.rb
config/initializers/cookies_serializer.rb
+ config/initializers/content_security_policy.rb
config/initializers/filter_parameter_logging.rb
config/initializers/inflections.rb
config/initializers/mime_types.rb
@@ -61,8 +65,9 @@ DEFAULT_APP_FILES = %w(
config/locales/en.yml
config/puma.rb
config/routes.rb
- config/secrets.yml
+ config/credentials.yml.enc
config/spring.rb
+ config/storage.yml
db
db/seeds.rb
lib
@@ -71,6 +76,7 @@ DEFAULT_APP_FILES = %w(
log
package.json
public
+ storage
test/application_system_test_case.rb
test/test_helper.rb
test/fixtures
@@ -85,6 +91,7 @@ DEFAULT_APP_FILES = %w(
tmp
tmp/cache
tmp/cache/assets
+ tmp/storage
)
class AppGeneratorTest < Rails::Generators::TestCase
@@ -98,6 +105,15 @@ class AppGeneratorTest < Rails::Generators::TestCase
::DEFAULT_APP_FILES
end
+ def test_skip_bundle
+ assert_not_called(generator([destination_root], skip_bundle: true), :bundle_command) do
+ quietly { generator.invoke_all }
+ # skip_bundle is only about running bundle install, ensure the Gemfile is still
+ # generated.
+ assert_file "Gemfile"
+ end
+ end
+
def test_assets
run_generator
@@ -195,7 +211,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
def test_new_application_doesnt_need_defaults
- assert_no_file "config/initializers/new_framework_defaults_5_2.rb"
+ assert_no_file "config/initializers/new_framework_defaults_6_0.rb"
end
def test_new_application_load_defaults
@@ -203,6 +219,8 @@ class AppGeneratorTest < Rails::Generators::TestCase
run_generator [app_root]
output = nil
+ assert_file "#{app_root}/config/application.rb", /\s+config\.load_defaults #{Rails::VERSION::STRING.to_f}/
+
Dir.chdir(app_root) do
output = `./bin/rails r "puts Rails.application.config.assets.unknown_asset_fallback"`
end
@@ -241,14 +259,14 @@ class AppGeneratorTest < Rails::Generators::TestCase
app_root = File.join(destination_root, "myapp")
run_generator [app_root]
- assert_no_file "#{app_root}/config/initializers/new_framework_defaults_5_2.rb"
+ assert_no_file "#{app_root}/config/initializers/new_framework_defaults_6_0.rb"
stub_rails_application(app_root) do
- generator = Rails::Generators::AppGenerator.new ["rails"], { update: true }, destination_root: app_root, shell: @shell
+ generator = Rails::Generators::AppGenerator.new ["rails"], { update: true }, { destination_root: app_root, shell: @shell }
generator.send(:app_const)
quietly { generator.send(:update_config_files) }
- assert_file "#{app_root}/config/initializers/new_framework_defaults_5_2.rb"
+ assert_file "#{app_root}/config/initializers/new_framework_defaults_6_0.rb"
end
end
@@ -283,8 +301,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
run_generator [app_root, "--skip-action-cable"]
FileUtils.cd(app_root) do
- # For avoid conflict file
- FileUtils.rm("#{app_root}/config/secrets.yml")
quietly { system("bin/rails app:update") }
end
@@ -294,6 +310,76 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_gem_for_active_storage
+ run_generator
+ assert_file "Gemfile", /^# gem 'image_processing'/
+ end
+
+ def test_gem_for_active_storage_when_skip_active_storage_is_given
+ run_generator [destination_root, "--skip-active-storage"]
+
+ assert_no_gem "image_processing"
+ end
+
+ def test_app_update_does_not_generate_active_storage_contents_when_skip_active_storage_is_given
+ app_root = File.join(destination_root, "myapp")
+ run_generator [app_root, "--skip-active-storage"]
+
+ FileUtils.cd(app_root) do
+ quietly { system("bin/rails app:update") }
+ end
+
+ assert_file "#{app_root}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{app_root}/config/storage.yml"
+ end
+
+ def test_app_update_does_not_generate_active_storage_contents_when_skip_active_record_is_given
+ app_root = File.join(destination_root, "myapp")
+ run_generator [app_root, "--skip-active-record"]
+
+ FileUtils.cd(app_root) do
+ quietly { system("bin/rails app:update") }
+ end
+
+ assert_file "#{app_root}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{app_root}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{app_root}/config/storage.yml"
+ end
+
+ def test_app_update_does_not_change_config_target_version
+ run_generator
+
+ FileUtils.cd(destination_root) do
+ config = "config/application.rb"
+ content = File.read(config)
+ File.write(config, content.gsub(/config\.load_defaults #{Rails::VERSION::STRING.to_f}/, "config.load_defaults 5.1"))
+ quietly { system("bin/rails app:update") }
+ end
+
+ assert_file "config/application.rb", /\s+config\.load_defaults 5\.1/
+ end
+
def test_application_names_are_not_singularized
run_generator [File.join(destination_root, "hats")]
assert_file "hats/config/environment.rb", /Rails\.application\.initialize!/
@@ -319,13 +405,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_config_another_database
+ def test_config_mysql_database
run_generator([destination_root, "-d", "mysql"])
assert_file "config/database.yml", /mysql/
if defined?(JRUBY_VERSION)
assert_gem "activerecord-jdbcmysql-adapter"
else
- assert_gem "mysql2", "'>= 0.3.18', '< 0.5'"
+ assert_gem "mysql2", "'>= 0.4.4', '< 0.6.0'"
end
end
@@ -340,7 +426,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
if defined?(JRUBY_VERSION)
assert_gem "activerecord-jdbcpostgresql-adapter"
else
- assert_gem "pg", "'~> 0.18'"
+ assert_gem "pg", "'>= 0.18', '< 2.0'"
end
end
@@ -377,65 +463,15 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_without_skips
- run_generator
- assert_file "config/application.rb", /\s+require\s+["']rails\/all["']/
- assert_file "config/environments/development.rb" do |content|
- assert_match(/config\.action_mailer\.raise_delivery_errors = false/, content)
- end
- assert_file "config/environments/test.rb" do |content|
- assert_match(/config\.action_mailer\.delivery_method = :test/, content)
- end
- assert_file "config/environments/production.rb" do |content|
- assert_match(/# config\.action_mailer\.raise_delivery_errors = false/, content)
- assert_match(/^ config\.read_encrypted_secrets = true/, content)
- end
- end
-
def test_generator_defaults_to_puma_version
run_generator [destination_root]
- assert_gem "puma", "'~> 3.7'"
+ assert_gem "puma", "'~> 3.11'"
end
def test_generator_if_skip_puma_is_given
run_generator [destination_root, "--skip-puma"]
assert_no_file "config/puma.rb"
- assert_file "Gemfile" do |content|
- assert_no_match(/puma/, content)
- end
- end
-
- def test_generator_if_skip_active_record_is_given
- run_generator [destination_root, "--skip-active-record"]
- assert_no_directory "db/"
- assert_no_file "config/database.yml"
- assert_no_file "app/models/application_record.rb"
- assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
- assert_file "test/test_helper.rb" do |helper_content|
- assert_no_match(/fixtures :all/, helper_content)
- end
- assert_file "bin/setup" do |setup_content|
- assert_no_match(/db:setup/, setup_content)
- end
- assert_file "bin/update" do |update_content|
- assert_no_match(/db:migrate/, update_content)
- end
- end
-
- def test_generator_if_skip_action_mailer_is_given
- run_generator [destination_root, "--skip-action-mailer"]
- assert_file "config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
- assert_file "config/environments/development.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "config/environments/test.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "config/environments/production.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_no_directory "app/mailers"
- assert_no_directory "test/mailers"
+ assert_no_gem "puma"
end
def test_generator_has_assets_gems
@@ -445,38 +481,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_gem "uglifier"
end
- def test_generator_if_skip_sprockets_is_given
- run_generator [destination_root, "--skip-sprockets"]
- assert_no_file "config/initializers/assets.rb"
- assert_file "config/application.rb" do |content|
- assert_match(/#\s+require\s+["']sprockets\/railtie["']/, content)
- end
- assert_file "Gemfile" do |content|
- assert_no_match(/sass-rails/, content)
- assert_no_match(/uglifier/, content)
- assert_no_match(/coffee-rails/, content)
- end
- assert_file "config/environments/development.rb" do |content|
- assert_no_match(/config\.assets\.debug = true/, content)
- end
- assert_file "config/environments/production.rb" do |content|
- assert_no_match(/config\.assets\.digest = true/, content)
- assert_no_match(/config\.assets\.js_compressor = :uglifier/, content)
- assert_no_match(/config\.assets\.css_compressor = :sass/, content)
- end
- end
-
- def test_generator_if_skip_action_cable_is_given
- run_generator [destination_root, "--skip-action-cable"]
- assert_file "config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
- assert_no_file "config/cable.yml"
- assert_no_file "app/assets/javascripts/cable.js"
- assert_no_file "app/channels"
- assert_file "Gemfile" do |content|
- assert_no_match(/redis/, content)
- end
- end
-
def test_action_cable_redis_gems
run_generator
assert_file "Gemfile", /^# gem 'redis'/
@@ -484,18 +488,25 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_generator_if_skip_test_is_given
run_generator [destination_root, "--skip-test"]
- assert_file "Gemfile" do |content|
- assert_no_match(/capybara/, content)
- assert_no_match(/selenium-webdriver/, content)
- end
+
+ assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
+
+ assert_no_gem "capybara"
+ assert_no_gem "selenium-webdriver"
+ assert_no_gem "chromedriver-helper"
+
+ assert_no_directory("test")
end
def test_generator_if_skip_system_test_is_given
run_generator [destination_root, "--skip-system-test"]
- assert_file "Gemfile" do |content|
- assert_no_match(/capybara/, content)
- assert_no_match(/selenium-webdriver/, content)
- end
+ assert_no_gem "capybara"
+ assert_no_gem "selenium-webdriver"
+ assert_no_gem "chromedriver-helper"
+
+ assert_directory("test")
+
+ assert_no_directory("test/system")
end
def test_does_not_generate_system_test_files_if_skip_system_test_is_given
@@ -509,18 +520,12 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_if_api_is_given
- run_generator [destination_root, "--api"]
- assert_file "Gemfile" do |content|
- assert_no_match(/capybara/, content)
- assert_no_match(/selenium-webdriver/, content)
- end
- end
-
def test_inclusion_of_javascript_runtime
run_generator
if defined?(JRUBY_VERSION)
assert_gem "therubyrhino"
+ elsif RUBY_PLATFORM =~ /mingw|mswin/
+ assert_gem "duktape"
else
assert_file "Gemfile", /# gem 'mini_racer', platforms: :ruby/
end
@@ -543,10 +548,8 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_no_match(/javascript_include_tag\s+'application' \%>/, contents)
end
- assert_file "Gemfile" do |content|
- assert_no_match(/coffee-rails/, content)
- assert_no_match(/uglifier/, content)
- end
+ assert_no_gem "coffee-rails"
+ assert_no_gem "uglifier"
assert_file "config/environments/production.rb" do |content|
assert_no_match(/config\.assets\.js_compressor = :uglifier/, content)
@@ -562,27 +565,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_generator_for_yarn
- run_generator([destination_root])
- assert_file "package.json", /dependencies/
- assert_file "config/initializers/assets.rb", /node_modules/
- end
-
- def test_generator_for_yarn_skipped
- run_generator([destination_root, "--skip-yarn"])
- assert_no_file "package.json"
- assert_no_file "bin/yarn"
-
- assert_file "config/initializers/assets.rb" do |content|
- assert_no_match(/node_modules/, content)
- end
-
- assert_file ".gitignore" do |content|
- assert_no_match(/node_modules/, content)
- assert_no_match(/yarn-error\.log/, content)
- end
- end
-
def test_inclusion_of_jbuilder
run_generator
assert_gem "jbuilder"
@@ -591,9 +573,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_inclusion_of_a_debugger
run_generator
if defined?(JRUBY_VERSION) || RUBY_ENGINE == "rbx"
- assert_file "Gemfile" do |content|
- assert_no_match(/byebug/, content)
- end
+ assert_no_gem "byebug"
else
assert_gem "byebug"
end
@@ -650,24 +630,24 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "lib/test_file.rb", "heres test data"
end
- def test_tests_are_removed_from_frameworks_if_skip_test_is_given
- run_generator [destination_root, "--skip-test"]
- assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
- end
-
- def test_no_active_record_or_tests_if_skips_given
- run_generator [destination_root, "--skip-test", "--skip-active-record"]
- assert_file "config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
- assert_file "config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
- assert_file "config/application.rb", /\s+require\s+["']active_job\/railtie["']/
- end
-
def test_pretend_option
output = run_generator [File.join(destination_root, "myapp"), "--pretend"]
assert_no_match(/run bundle install/, output)
assert_no_match(/run git init/, output)
end
+ def test_quiet_option
+ output = run_generator [File.join(destination_root, "myapp"), "--quiet"]
+ assert_empty output
+ end
+
+ def test_force_option_overwrites_every_file_except_master_key
+ run_generator [File.join(destination_root, "myapp")]
+ output = run_generator [File.join(destination_root, "myapp"), "--force"]
+ assert_match(/force/, output)
+ assert_no_match("force config/master.key", output)
+ end
+
def test_application_name_with_spaces
path = File.join(destination_root, "foo bar")
@@ -744,9 +724,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_called_with(Process, :respond_to?, [[:fork], [:fork]], returns: false) do
run_generator
- assert_file "Gemfile" do |content|
- assert_no_match(/spring/, content)
- end
+ assert_no_gem "spring"
end
end
@@ -754,25 +732,58 @@ class AppGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "--skip-spring"]
assert_no_file "config/spring.rb"
- assert_file "Gemfile" do |content|
- assert_no_match(/spring/, content)
- end
+ assert_no_gem "spring"
end
def test_spring_with_dev_option
run_generator [destination_root, "--dev"]
- assert_file "Gemfile" do |content|
- assert_no_match(/spring/, content)
+ assert_no_gem "spring"
+ end
+
+ def test_webpack_option
+ command_check = -> command, *_ do
+ @called ||= 0
+ if command == "webpacker:install"
+ @called += 1
+ assert_equal 1, @called, "webpacker:install expected to be called once, but was called #{@called} times."
+ end
+ end
+
+ generator([destination_root], webpack: "webpack").stub(:rails_command, command_check) do
+ generator.stub :bundle_command, nil do
+ quietly { generator.invoke_all }
+ end
+ end
+
+ assert_gem "webpacker"
+ end
+
+ def test_webpack_option_with_js_framework
+ command_check = -> command, *_ do
+ case command
+ when "webpacker:install"
+ @webpacker ||= 0
+ @webpacker += 1
+ assert_equal 1, @webpacker, "webpacker:install expected to be called once, but was called #{@webpacker} times."
+ when "webpacker:install:react"
+ @react ||= 0
+ @react += 1
+ assert_equal 1, @react, "webpacker:install:react expected to be called once, but was called #{@react} times."
+ end
+ end
+
+ generator([destination_root], webpack: "react").stub(:rails_command, command_check) do
+ generator.stub :bundle_command, nil do
+ quietly { generator.invoke_all }
+ end
end
end
def test_generator_if_skip_turbolinks_is_given
run_generator [destination_root, "--skip-turbolinks"]
- assert_file "Gemfile" do |content|
- assert_no_match(/turbolinks/, content)
- end
+ assert_no_gem "turbolinks"
assert_file "app/views/layouts/application.html.erb" do |content|
assert_no_match(/data-turbolinks-track/, content)
end
@@ -781,27 +792,48 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
- def test_gitignore_when_sqlite3
+ def test_bootsnap
run_generator
- assert_file ".gitignore" do |content|
- assert_match(/sqlite3/, content)
+ unless defined?(JRUBY_VERSION)
+ assert_gem "bootsnap"
+ assert_file "config/boot.rb" do |content|
+ assert_match(/require 'bootsnap\/setup'/, content)
+ end
+ else
+ assert_no_gem "bootsnap"
+ assert_file "config/boot.rb" do |content|
+ assert_no_match(/require 'bootsnap\/setup'/, content)
+ end
end
end
- def test_gitignore_when_no_active_record
- run_generator [destination_root, "--skip-active-record"]
+ def test_skip_bootsnap
+ run_generator [destination_root, "--skip-bootsnap"]
- assert_file ".gitignore" do |content|
- assert_no_match(/sqlite/i, content)
+ assert_no_gem "bootsnap"
+ assert_file "config/boot.rb" do |content|
+ assert_no_match(/require 'bootsnap\/setup'/, content)
end
end
- def test_gitignore_when_non_sqlite3_db
- run_generator([destination_root, "-d", "mysql"])
+ def test_bootsnap_with_dev_option
+ run_generator [destination_root, "--dev"]
- assert_file ".gitignore" do |content|
- assert_no_match(/sqlite/i, content)
+ assert_no_gem "bootsnap"
+ assert_file "config/boot.rb" do |content|
+ assert_no_match(/require 'bootsnap\/setup'/, content)
+ end
+ end
+
+ def test_inclusion_of_ruby_version
+ run_generator
+
+ assert_file "Gemfile" do |content|
+ assert_match(/ruby '#{RUBY_VERSION}'/, content)
+ end
+ assert_file ".ruby-version" do |content|
+ assert_match(/#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}/, content)
end
end
@@ -848,7 +880,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
def test_after_bundle_callback
path = "http://example.org/rails_template"
- template = %{ after_bundle { run 'echo ran after_bundle' } }
+ template = %{ after_bundle { run 'echo ran after_bundle' } }.dup
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
@@ -858,7 +890,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
sequence = ["git init", "install", "exec spring binstub --all", "echo ran after_bundle"]
@sequence_step ||= 0
- ensure_bundler_first = -> command do
+ ensure_bundler_first = -> command, options = nil do
assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}"
@sequence_step += 1
end
@@ -866,7 +898,9 @@ class AppGeneratorTest < Rails::Generators::TestCase
generator([destination_root], template: path).stub(:open, check_open, template) do
generator.stub(:bundle_command, ensure_bundler_first) do
generator.stub(:run, ensure_bundler_first) do
- quietly { generator.invoke_all }
+ generator.stub(:rails_command, ensure_bundler_first) do
+ quietly { generator.invoke_all }
+ end
end
end
end
@@ -874,23 +908,28 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_equal 4, @sequence_step
end
- def test_system_tests_directory_generated
+ def test_gitignore
run_generator
- assert_file("test/system/.keep")
- assert_directory("test/system")
+ assert_file ".gitignore" do |content|
+ assert_match(/config\/master\.key/, content)
+ end
end
- def test_system_tests_are_not_generated_on_system_test_skip
- run_generator [destination_root, "--skip-system-test"]
+ def test_system_tests_directory_generated
+ run_generator
- assert_no_directory("test/system")
+ assert_directory("test/system")
+ assert_file("test/system/.keep")
end
- def test_system_tests_are_not_generated_on_test_skip
- run_generator [destination_root, "--skip-test"]
+ unless Gem.win_platform?
+ def test_master_key_is_only_readable_by_the_owner
+ run_generator
- assert_no_directory("test/system")
+ stat = File.stat("config/master.key")
+ assert_equal "100600", sprintf("%o", stat.mode)
+ end
end
private
@@ -913,6 +952,12 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
end
+ def assert_no_gem(gem)
+ assert_file "Gemfile" do |content|
+ assert_no_match(gem, content)
+ end
+ end
+
def assert_listen_related_configuration
assert_gem "listen"
assert_gem "spring-watcher-listen"
@@ -923,9 +968,7 @@ class AppGeneratorTest < Rails::Generators::TestCase
end
def assert_no_listen_related_configuration
- assert_file "Gemfile" do |content|
- assert_no_match(/listen/, content)
- end
+ assert_no_gem "listen"
assert_file "config/environments/development.rb" do |content|
assert_match(/^\s*# config\.file_watcher = ActiveSupport::EventedFileUpdateChecker/, content)
diff --git a/railties/test/generators/application_record_generator_test.rb b/railties/test/generators/application_record_generator_test.rb
new file mode 100644
index 0000000000..2c0aa7211b
--- /dev/null
+++ b/railties/test/generators/application_record_generator_test.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require "generators/generators_test_helper"
+require "rails/generators/rails/application_record/application_record_generator"
+
+class ApplicationRecordGeneratorTest < Rails::Generators::TestCase
+ include GeneratorsTestHelper
+
+ def test_application_record_skeleton_is_created
+ run_generator
+ assert_file "app/models/application_record.rb" do |record|
+ assert_match(/class ApplicationRecord < ActiveRecord::Base/, record)
+ assert_match(/self\.abstract_class = true/, record)
+ end
+ end
+end
diff --git a/railties/test/generators/argv_scrubber_test.rb b/railties/test/generators/argv_scrubber_test.rb
index 7f4295a20f..9ef61dc978 100644
--- a/railties/test/generators/argv_scrubber_test.rb
+++ b/railties/test/generators/argv_scrubber_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/test_case"
require "active_support/testing/autorun"
require "rails/generators/rails/app/app_generator"
@@ -80,9 +82,8 @@ module Rails
file.puts "--hello --world"
file.flush
- message = nil
scrubber = Class.new(ARGVScrubber) {
- define_method(:puts) { |msg| message = msg }
+ define_method(:puts) { |msg| }
}.new ["new", "--rc=#{file.path}"]
args = scrubber.prepare!
assert_equal ["--hello", "--world"], args
diff --git a/railties/test/generators/assets_generator_test.rb b/railties/test/generators/assets_generator_test.rb
index 1c02c67e42..3cec41dbf8 100644
--- a/railties/test/generators/assets_generator_test.rb
+++ b/railties/test/generators/assets_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/assets/assets_generator"
diff --git a/railties/test/generators/channel_generator_test.rb b/railties/test/generators/channel_generator_test.rb
index af68a9c49f..e543cc11b8 100644
--- a/railties/test/generators/channel_generator_test.rb
+++ b/railties/test/generators/channel_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/channel/channel_generator"
@@ -74,4 +76,14 @@ class ChannelGeneratorTest < Rails::Generators::TestCase
assert_file "app/channels/application_cable/connection.rb"
assert_file "app/assets/javascripts/cable.js"
end
+
+ def test_channel_suffix_is_not_duplicated
+ run_generator ["chat_channel"]
+
+ assert_no_file "app/channels/chat_channel_channel.rb"
+ assert_file "app/channels/chat_channel.rb"
+
+ assert_no_file "app/assets/javascripts/channels/chat_channel.js"
+ assert_file "app/assets/javascripts/channels/chat.js"
+ end
end
diff --git a/railties/test/generators/controller_generator_test.rb b/railties/test/generators/controller_generator_test.rb
index af86a0136f..021004c9b8 100644
--- a/railties/test/generators/controller_generator_test.rb
+++ b/railties/test/generators/controller_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/controller/controller_generator"
@@ -100,4 +102,40 @@ class ControllerGeneratorTest < Rails::Generators::TestCase
assert_match(/^ namespace :admin do\n get 'dashboard\/index'\n end$/, route)
end
end
+
+ def test_namespaced_routes_with_multiple_actions_are_created_in_routes
+ run_generator ["admin/dashboard", "index", "show"]
+ assert_file "config/routes.rb" do |route|
+ assert_match(/^ namespace :admin do\n get 'dashboard\/index'\n get 'dashboard\/show'\n end$/, route)
+ end
+ end
+
+ def test_does_not_add_routes_when_action_is_not_specified
+ run_generator ["admin/dashboard"]
+ assert_file "config/routes.rb" do |routes|
+ assert_no_match(/namespace :admin/, routes)
+ end
+ end
+
+ def test_controller_suffix_is_not_duplicated
+ run_generator ["account_controller"]
+
+ assert_no_file "app/controllers/account_controller_controller.rb"
+ assert_file "app/controllers/account_controller.rb"
+
+ assert_no_file "app/views/account_controller/"
+ assert_file "app/views/account/"
+
+ assert_no_file "test/controllers/account_controller_controller_test.rb"
+ assert_file "test/controllers/account_controller_test.rb"
+
+ assert_no_file "app/helpers/account_controller_helper.rb"
+ assert_file "app/helpers/account_helper.rb"
+
+ assert_no_file "app/assets/javascripts/account_controller.js"
+ assert_file "app/assets/javascripts/account.js"
+
+ assert_no_file "app/assets/stylesheets/account_controller.css"
+ assert_file "app/assets/stylesheets/account.css"
+ end
end
diff --git a/railties/test/generators/create_migration_test.rb b/railties/test/generators/create_migration_test.rb
index c7b0237f02..2ae38045c5 100644
--- a/railties/test/generators/create_migration_test.rb
+++ b/railties/test/generators/create_migration_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/migration/migration_generator"
@@ -51,7 +53,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
end
def test_invoke_pretended
- create_migration(default_destination_path, {}, pretend: true)
+ create_migration(default_destination_path, {}, { pretend: true })
assert_no_file @migration.destination
end
@@ -68,7 +70,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
create_migration
assert_match(/identical db\/migrate\/1_create_articles\.rb\n/, invoke!)
- assert @migration.identical?
+ assert_predicate @migration, :identical?
end
def test_invoke_when_exists_not_identical
@@ -92,7 +94,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
def test_invoke_forced_pretended_when_exists_not_identical
migration_exists!
- create_migration(default_destination_path, { force: true }, pretend: true) do
+ create_migration(default_destination_path, { force: true }, { pretend: true }) do
"different content"
end
@@ -104,7 +106,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
def test_invoke_skipped_when_exists_not_identical
migration_exists!
- create_migration(default_destination_path, {}, skip: true) { "different content" }
+ create_migration(default_destination_path, {}, { skip: true }) { "different content" }
assert_match(/skip db\/migrate\/2_create_articles\.rb\n/, invoke!)
assert_no_file @migration.destination
@@ -120,7 +122,7 @@ class CreateMigrationTest < Rails::Generators::TestCase
def test_revoke_pretended
migration_exists!
- create_migration(default_destination_path, {}, pretend: true)
+ create_migration(default_destination_path, {}, { pretend: true })
assert_match(/remove db\/migrate\/1_create_articles\.rb\n/, revoke!)
assert_file @existing_migration.destination
diff --git a/railties/test/generators/encrypted_secrets_generator_test.rb b/railties/test/generators/encrypted_secrets_generator_test.rb
deleted file mode 100644
index 21fdcab19f..0000000000
--- a/railties/test/generators/encrypted_secrets_generator_test.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require "generators/generators_test_helper"
-require "rails/generators/rails/encrypted_secrets/encrypted_secrets_generator"
-
-class EncryptedSecretsGeneratorTest < Rails::Generators::TestCase
- include GeneratorsTestHelper
-
- def setup
- super
- cd destination_root
- end
-
- def test_generates_key_file_and_encrypted_secrets_file
- run_generator
-
- assert_file "config/secrets.yml.key", /\w+/
-
- assert File.exist?("config/secrets.yml.enc")
- assert_no_match(/production:\n# external_api_key: \w+/, IO.binread("config/secrets.yml.enc"))
- assert_match(/production:\n# external_api_key: \w+/, Rails::Secrets.read)
- end
-
- def test_appends_to_gitignore
- FileUtils.touch(".gitignore")
-
- run_generator
-
- assert_file ".gitignore", /config\/secrets.yml.key/, /(?!config\/secrets.yml.enc)/
- end
-
- def test_warns_when_ignore_is_missing
- assert_match(/Add this to your ignore file/i, run_generator)
- end
-
- def test_doesnt_generate_a_new_key_file_if_already_opted_in_to_encrypted_secrets
- FileUtils.mkdir("config")
- File.open("config/secrets.yml.enc", "w") { |f| f.puts "already secrety" }
-
- run_generator
-
- assert_no_file "config/secrets.yml.key"
- end
-end
diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb
index 97847c8624..772b4f6f0d 100644
--- a/railties/test/generators/generated_attribute_test.rb
+++ b/railties/test/generators/generated_attribute_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/generated_attribute"
@@ -102,25 +104,25 @@ class GeneratedAttributeTest < Rails::Generators::TestCase
def test_reference_is_true
%w(references belongs_to).each do |attribute_type|
- assert create_generated_attribute(attribute_type).reference?
+ assert_predicate create_generated_attribute(attribute_type), :reference?
end
end
def test_reference_is_false
%w(foo bar baz).each do |attribute_type|
- assert !create_generated_attribute(attribute_type).reference?
+ assert_not_predicate create_generated_attribute(attribute_type), :reference?
end
end
def test_polymorphic_reference_is_true
%w(references belongs_to).each do |attribute_type|
- assert create_generated_attribute("#{attribute_type}{polymorphic}").polymorphic?
+ assert_predicate create_generated_attribute("#{attribute_type}{polymorphic}"), :polymorphic?
end
end
def test_polymorphic_reference_is_false
%w(foo bar baz).each do |attribute_type|
- assert !create_generated_attribute("#{attribute_type}{polymorphic}").polymorphic?
+ assert_not_predicate create_generated_attribute("#{attribute_type}{polymorphic}"), :polymorphic?
end
end
@@ -146,7 +148,7 @@ class GeneratedAttributeTest < Rails::Generators::TestCase
att = Rails::Generators::GeneratedAttribute.parse("supplier:references{required}:index")
assert_equal "supplier", att.name
assert_equal :references, att.type
- assert att.has_index?
- assert att.required?
+ assert_predicate att, :has_index?
+ assert_predicate att, :required?
end
end
diff --git a/railties/test/generators/generator_generator_test.rb b/railties/test/generators/generator_generator_test.rb
index 5ff8bb0357..eaa964cabc 100644
--- a/railties/test/generators/generator_generator_test.rb
+++ b/railties/test/generators/generator_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/generator/generator_generator"
diff --git a/railties/test/generators/generator_test.rb b/railties/test/generators/generator_test.rb
index 4444b3a56e..5f7daf5ac3 100644
--- a/railties/test/generators/generator_test.rb
+++ b/railties/test/generators/generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "active_support/test_case"
require "active_support/testing/autorun"
require "rails/generators/app_base"
diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb
index 5fb331e197..ad2a55f496 100644
--- a/railties/test/generators/generators_test_helper.rb
+++ b/railties/test/generators/generators_test_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "active_support/core_ext/module/remove_method"
require "active_support/testing/stream"
@@ -41,9 +43,9 @@ module GeneratorsTestHelper
end
def copy_routes
- routes = File.expand_path("../../lib/rails/generators/rails/app/templates/config/routes.rb", __dir__)
+ routes = File.expand_path("../../lib/rails/generators/rails/app/templates/config/routes.rb.tt", __dir__)
destination = File.join(destination_root, "config")
FileUtils.mkdir_p(destination)
- FileUtils.cp routes, destination
+ FileUtils.cp routes, File.join(destination, "routes.rb")
end
end
diff --git a/railties/test/generators/helper_generator_test.rb b/railties/test/generators/helper_generator_test.rb
index d9e6e0a85a..4cdb6adf82 100644
--- a/railties/test/generators/helper_generator_test.rb
+++ b/railties/test/generators/helper_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/helper/helper_generator"
diff --git a/railties/test/generators/integration_test_generator_test.rb b/railties/test/generators/integration_test_generator_test.rb
index 9358b63bd4..82791f1a27 100644
--- a/railties/test/generators/integration_test_generator_test.rb
+++ b/railties/test/generators/integration_test_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/integration_test/integration_test_generator"
diff --git a/railties/test/generators/job_generator_test.rb b/railties/test/generators/job_generator_test.rb
index 68d158eb39..234ba6dad7 100644
--- a/railties/test/generators/job_generator_test.rb
+++ b/railties/test/generators/job_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/job/job_generator"
@@ -33,4 +35,14 @@ class JobGeneratorTest < Rails::Generators::TestCase
assert_match(/class ApplicationJob < ActiveJob::Base/, job)
end
end
+
+ def test_job_suffix_is_not_duplicated
+ run_generator ["notifier_job"]
+
+ assert_no_file "app/jobs/notifier_job_job.rb"
+ assert_file "app/jobs/notifier_job.rb"
+
+ assert_no_file "test/jobs/notifier_job_job_test.rb"
+ assert_file "test/jobs/notifier_job_test.rb"
+ end
end
diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb
index 2ff03ea65e..ddac6e1a1e 100644
--- a/railties/test/generators/mailer_generator_test.rb
+++ b/railties/test/generators/mailer_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/mailer/mailer_generator"
diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb
index 6fe6e4ca07..88a939a55a 100644
--- a/railties/test/generators/migration_generator_test.rb
+++ b/railties/test/generators/migration_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/migration/migration_generator"
@@ -48,6 +50,17 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_add_migration_with_table_having_from_in_title
+ migration = "add_email_address_to_blacklisted_from_campaign"
+ run_generator [migration, "email_address:string"]
+
+ assert_migration "db/migrate/#{migration}.rb" do |content|
+ assert_method :change, content do |change|
+ assert_match(/add_column :blacklisted_from_campaigns, :email_address, :string/, change)
+ end
+ end
+ end
+
def test_remove_migration_with_indexed_attribute
migration = "remove_title_body_from_posts"
run_generator [migration, "title:string:index", "body:text"]
@@ -73,6 +86,17 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
end
end
+ def test_remove_migration_with_table_having_to_in_title
+ migration = "remove_email_address_from_sent_to_user"
+ run_generator [migration, "email_address:string"]
+
+ assert_migration "db/migrate/#{migration}.rb" do |content|
+ assert_method :change, content do |change|
+ assert_match(/remove_column :sent_to_users, :email_address, :string/, change)
+ end
+ end
+ end
+
def test_remove_migration_with_references_options
migration = "remove_references_from_books"
run_generator [migration, "author:belongs_to", "distributor:references{polymorphic}"]
diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb
index f41969fc46..8d933e82c3 100644
--- a/railties/test/generators/model_generator_test.rb
+++ b/railties/test/generators/model_generator_test.rb
@@ -1,19 +1,12 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/model/model_generator"
-require "active_support/core_ext/string/strip"
class ModelGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
arguments %w(Account name:string age:integer)
- def test_application_record_skeleton_is_created
- run_generator
- assert_file "app/models/application_record.rb" do |record|
- assert_match(/class ApplicationRecord < ActiveRecord::Base/, record)
- assert_match(/self\.abstract_class = true/, record)
- end
- end
-
def test_help_shows_invoked_generators_options
content = run_generator ["--help"]
assert_match(/ActiveRecord options:/, content)
@@ -43,17 +36,6 @@ class ModelGeneratorTest < Rails::Generators::TestCase
assert_no_migration "db/migrate/create_accounts.rb"
end
- def test_model_with_existent_application_record
- mkdir_p "#{destination_root}/app/models"
- touch "#{destination_root}/app/models/application_record.rb"
-
- Dir.chdir(destination_root) do
- run_generator ["account"]
- end
-
- assert_file "app/models/account.rb", /class Account < ApplicationRecord/
- end
-
def test_plural_names_are_singularized
content = run_generator ["accounts".freeze]
assert_file "app/models/account.rb", /class Account < ApplicationRecord/
@@ -396,10 +378,10 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_required_belongs_to_adds_required_association
run_generator ["account", "supplier:references{required}"]
- expected_file = <<-FILE.strip_heredoc
- class Account < ApplicationRecord
- belongs_to :supplier, required: true
- end
+ expected_file = <<~FILE
+ class Account < ApplicationRecord
+ belongs_to :supplier, required: true
+ end
FILE
assert_file "app/models/account.rb", expected_file
end
@@ -407,10 +389,10 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_required_polymorphic_belongs_to_generages_correct_model
run_generator ["account", "supplier:references{required,polymorphic}"]
- expected_file = <<-FILE.strip_heredoc
- class Account < ApplicationRecord
- belongs_to :supplier, polymorphic: true, required: true
- end
+ expected_file = <<~FILE
+ class Account < ApplicationRecord
+ belongs_to :supplier, polymorphic: true, required: true
+ end
FILE
assert_file "app/models/account.rb", expected_file
end
@@ -418,10 +400,10 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_required_and_polymorphic_are_order_independent
run_generator ["account", "supplier:references{polymorphic.required}"]
- expected_file = <<-FILE.strip_heredoc
- class Account < ApplicationRecord
- belongs_to :supplier, polymorphic: true, required: true
- end
+ expected_file = <<~FILE
+ class Account < ApplicationRecord
+ belongs_to :supplier, polymorphic: true, required: true
+ end
FILE
assert_file "app/models/account.rb", expected_file
end
@@ -469,11 +451,11 @@ class ModelGeneratorTest < Rails::Generators::TestCase
def test_token_option_adds_has_secure_token
run_generator ["user", "token:token", "auth_token:token"]
- expected_file = <<-FILE.strip_heredoc
- class User < ApplicationRecord
- has_secure_token
- has_secure_token :auth_token
- end
+ expected_file = <<~FILE
+ class User < ApplicationRecord
+ has_secure_token
+ has_secure_token :auth_token
+ end
FILE
assert_file "app/models/user.rb", expected_file
end
diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb
index 3015b5363b..4e61b660d7 100644
--- a/railties/test/generators/named_base_test.rb
+++ b/railties/test/generators/named_base_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
@@ -31,6 +33,17 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "foos", :plural_name
assert_name g, "admin.foo", :i18n_scope
assert_name g, "admin_foos", :table_name
+ assert_name g, "admin/foos", :controller_name
+ assert_name g, %w(admin), :controller_class_path
+ assert_name g, "Admin::Foos", :controller_class_name
+ assert_name g, "admin/foos", :controller_file_path
+ assert_name g, "foos", :controller_file_name
+ assert_name g, "admin.foos", :controller_i18n_scope
+ assert_name g, "admin_foo", :singular_route_name
+ assert_name g, "admin_foos", :plural_route_name
+ assert_name g, "@admin_foo", :redirect_resource_name
+ assert_name g, "admin_foo", :model_resource_name
+ assert_name g, "admin_foos", :index_helper
end
def test_named_generator_attributes_as_ruby
@@ -45,6 +58,17 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "foos", :plural_name
assert_name g, "admin.foo", :i18n_scope
assert_name g, "admin_foos", :table_name
+ assert_name g, "Admin::Foos", :controller_name
+ assert_name g, %w(admin), :controller_class_path
+ assert_name g, "Admin::Foos", :controller_class_name
+ assert_name g, "admin/foos", :controller_file_path
+ assert_name g, "foos", :controller_file_name
+ assert_name g, "admin.foos", :controller_i18n_scope
+ assert_name g, "admin_foo", :singular_route_name
+ assert_name g, "admin_foos", :plural_route_name
+ assert_name g, "@admin_foo", :redirect_resource_name
+ assert_name g, "admin_foo", :model_resource_name
+ assert_name g, "admin_foos", :index_helper
end
def test_named_generator_attributes_without_pluralized
@@ -57,7 +81,7 @@ class NamedBaseTest < Rails::Generators::TestCase
ActiveRecord::Base.pluralize_table_names = original_pluralize_table_names
end
- def test_scaffold_plural_names
+ def test_namespaced_scaffold_plural_names
g = generator ["admin/foo"]
assert_name g, "admin/foos", :controller_name
assert_name g, %w(admin), :controller_class_path
@@ -67,7 +91,7 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "admin.foos", :controller_i18n_scope
end
- def test_scaffold_plural_names_as_ruby
+ def test_namespaced_scaffold_plural_names_as_ruby
g = generator ["Admin::Foo"]
assert_name g, "Admin::Foos", :controller_name
assert_name g, %w(admin), :controller_class_path
@@ -129,6 +153,19 @@ class NamedBaseTest < Rails::Generators::TestCase
assert_name g, "admin/foos", :controller_file_path
assert_name g, "foos", :controller_file_name
assert_name g, "admin.foos", :controller_i18n_scope
+ assert_name g, "admin_user", :singular_route_name
+ assert_name g, "admin_users", :plural_route_name
+ assert_name g, "[:admin, @user]", :redirect_resource_name
+ assert_name g, "[:admin, user]", :model_resource_name
+ assert_name g, "admin_users", :index_helper
+ end
+
+ def test_scaffold_plural_names
+ g = generator ["User"]
+ assert_name g, "@user", :redirect_resource_name
+ assert_name g, "user", :model_resource_name
+ assert_name g, "user", :singular_route_name
+ assert_name g, "users", :plural_route_name
end
private
diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb
index 1caabbe6b1..4b75a31f17 100644
--- a/railties/test/generators/namespaced_generators_test.rb
+++ b/railties/test/generators/namespaced_generators_test.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/controller/controller_generator"
require "rails/generators/rails/model/model_generator"
require "rails/generators/mailer/mailer_generator"
require "rails/generators/rails/scaffold/scaffold_generator"
+require "rails/generators/rails/application_record/application_record_generator"
class NamespacedGeneratorTestCase < Rails::Generators::TestCase
include GeneratorsTestHelper
@@ -149,7 +152,7 @@ class NamespacedMailerGeneratorTest < NamespacedGeneratorTestCase
assert_file "app/mailers/test_app/notifier_mailer.rb" do |mailer|
assert_match(/module TestApp/, mailer)
assert_match(/class NotifierMailer < ApplicationMailer/, mailer)
- assert_no_match(/default from: "from@example.com"/, mailer)
+ assert_no_match(/default from: "from@example\.com"/, mailer)
end
end
@@ -421,3 +424,13 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase
/module TestApp\n class Admin::RolesControllerTest < ActionDispatch::IntegrationTest/
end
end
+
+class NamespacedApplicationRecordGeneratorTest < NamespacedGeneratorTestCase
+ include GeneratorsTestHelper
+ tests Rails::Generators::ApplicationRecordGenerator
+
+ def test_adds_namespace_to_application_record
+ run_generator
+ assert_file "app/models/test_app/application_record.rb", /module TestApp/, / class ApplicationRecord < ActiveRecord::Base/
+ end
+end
diff --git a/railties/test/generators/orm_test.rb b/railties/test/generators/orm_test.rb
index 88ae930554..6eaf2fbfd3 100644
--- a/railties/test/generators/orm_test.rb
+++ b/railties/test/generators/orm_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb
index f8512f9157..28ac3611b7 100644
--- a/railties/test/generators/plugin_generator_test.rb
+++ b/railties/test/generators/plugin_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/plugin/plugin_generator"
require "generators/shared_generator_tests"
@@ -24,6 +26,10 @@ class PluginGeneratorTest < Rails::Generators::TestCase
destination File.join(Rails.root, "tmp/bukkits")
arguments [destination_root]
+ def application_path
+ "#{destination_root}/test/dummy"
+ end
+
# brings setup, teardown, and some tests
include SharedGeneratorTests
@@ -75,6 +81,19 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_no_file "bin/rails"
end
+ def test_generating_in_full_mode_with_almost_of_all_skip_options
+ run_generator [destination_root, "--full", "-M", "-O", "-C", "-S", "-T", "--skip-active-storage"]
+ assert_file "bin/rails" do |content|
+ assert_no_match(/\s+require\s+["']rails\/all["']/, content)
+ end
+ assert_file "bin/rails", /#\s+require\s+["']active_record\/railtie["']/
+ assert_file "bin/rails", /#\s+require\s+["']active_storage\/engine["']/
+ assert_file "bin/rails", /#\s+require\s+["']action_mailer\/railtie["']/
+ assert_file "bin/rails", /#\s+require\s+["']action_cable\/engine["']/
+ assert_file "bin/rails", /#\s+require\s+["']sprockets\/railtie["']/
+ assert_file "bin/rails", /#\s+require\s+["']rails\/test_unit\/railtie["']/
+ end
+
def test_generating_test_files_in_full_mode
run_generator [destination_root, "--full"]
assert_directory "test/integration/"
@@ -82,6 +101,11 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "test/integration/navigation_test.rb", /ActionDispatch::IntegrationTest/
end
+ def test_inclusion_of_git_source
+ run_generator [destination_root]
+ assert_file "Gemfile", /git_source/
+ end
+
def test_inclusion_of_a_debugger
run_generator [destination_root, "--full"]
if defined?(JRUBY_VERSION) || RUBY_ENGINE == "rbx"
@@ -97,23 +121,19 @@ class PluginGeneratorTest < Rails::Generators::TestCase
run_generator [destination_root, "-T", "--full"]
assert_no_directory "test/integration/"
- assert_no_file "test"
+ assert_no_directory "test"
assert_file "Rakefile" do |contents|
assert_no_match(/APP_RAKEFILE/, contents)
end
- end
-
- def test_generating_adds_dummy_app_in_full_mode_without_sprockets
- run_generator [destination_root, "-S", "--full"]
-
- assert_file "test/dummy/config/environments/production.rb" do |contents|
- assert_no_match(/config\.assets/, contents)
+ assert_file "bin/rails" do |contents|
+ assert_no_match(/APP_PATH/, contents)
end
end
def test_generating_adds_dummy_app_rake_tasks_without_unit_test_files
run_generator [destination_root, "-T", "--mountable", "--dummy-path", "my_dummy_app"]
assert_file "Rakefile", /APP_RAKEFILE/
+ assert_file "bin/rails", /APP_PATH/
end
def test_generating_adds_dummy_app_without_javascript_and_assets_deps
@@ -134,8 +154,8 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_ensure_that_test_dummy_can_be_generated_from_a_template
FileUtils.cd(Rails.root)
run_generator([destination_root, "-m", "lib/create_test_dummy_template.rb", "--skip-test"])
- assert_file "spec/dummy"
- assert_no_file "test"
+ assert_directory "spec/dummy"
+ assert_no_directory "test"
end
def test_database_entry_is_generated_for_sqlite3_by_default_in_full_mode
@@ -158,47 +178,13 @@ class PluginGeneratorTest < Rails::Generators::TestCase
end
end
- def test_app_generator_without_skips
- run_generator
- assert_file "test/dummy/config/application.rb", /\s+require\s+["']rails\/all["']/
- assert_file "test/dummy/config/environments/development.rb" do |content|
- assert_match(/config\.action_mailer\.raise_delivery_errors = false/, content)
- end
- assert_file "test/dummy/config/environments/test.rb" do |content|
- assert_match(/config\.action_mailer\.delivery_method = :test/, content)
- end
- assert_file "test/dummy/config/environments/production.rb" do |content|
- assert_match(/# config\.action_mailer\.raise_delivery_errors = false/, content)
- end
- end
-
- def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given
- run_generator [destination_root, "--skip-active-record"]
- assert_file "test/dummy/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
- end
-
def test_ensure_that_skip_active_record_option_is_passed_to_app_generator
run_generator [destination_root, "--skip_active_record"]
- assert_no_file "test/dummy/config/database.yml"
assert_file "test/test_helper.rb" do |contents|
assert_no_match(/ActiveRecord/, contents)
end
end
- def test_action_mailer_is_removed_from_frameworks_if_skip_action_mailer_is_given
- run_generator [destination_root, "--skip-action-mailer"]
- assert_file "test/dummy/config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
- assert_file "test/dummy/config/environments/development.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "test/dummy/config/environments/test.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- assert_file "test/dummy/config/environments/production.rb" do |content|
- assert_no_match(/config\.action_mailer/, content)
- end
- end
-
def test_ensure_that_database_option_is_passed_to_app_generator
run_generator [destination_root, "--database", "postgresql"]
assert_file "test/dummy/config/database.yml", /postgres/
@@ -231,12 +217,22 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_javascripts_generation
run_generator [destination_root, "--mountable"]
- assert_file "app/assets/javascripts/bukkits/application.js"
+ assert_file "app/assets/javascripts/bukkits/application.js" do |content|
+ assert_match "//= require rails-ujs", content
+ assert_match "//= require activestorage", content
+ assert_match "//= require_tree .", content
+ end
+ assert_file "app/views/layouts/bukkits/application.html.erb" do |content|
+ assert_match "javascript_include_tag", content
+ end
end
def test_skip_javascripts
run_generator [destination_root, "--skip-javascript", "--mountable"]
assert_no_file "app/assets/javascripts/bukkits/application.js"
+ assert_file "app/views/layouts/bukkits/application.html.erb" do |content|
+ assert_no_match "javascript_include_tag", content
+ end
end
def test_template_from_dir_pwd
@@ -276,7 +272,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "app/views"
assert_file "app/helpers"
assert_file "app/mailers"
- assert_file "bin/rails"
+ assert_file "bin/rails", /\s+require\s+["']rails\/all["']/
assert_file "config/routes.rb", /Rails.application.routes.draw do/
assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < ::Rails::Engine\n end\nend/
assert_file "lib/bukkits.rb", /require "bukkits\/engine"/
@@ -335,8 +331,11 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "app/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/
assert_file "app/views/layouts/bukkits/application.html.erb" do |contents|
assert_match "<title>Bukkits</title>", contents
+ assert_match "<%= csrf_meta_tags %>", contents
+ assert_match "<%= csp_meta_tag %>", contents
assert_match(/stylesheet_link_tag\s+['"]bukkits\/application['"]/, contents)
assert_match(/javascript_include_tag\s+['"]bukkits\/application['"]/, contents)
+ assert_match "<%= yield %>", contents
end
assert_file "test/test_helper.rb" do |content|
assert_match(/ActiveRecord::Migrator\.migrations_paths.+\.\.\/test\/dummy\/db\/migrate/, content)
@@ -458,10 +457,9 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_creating_dummy_without_tests_but_with_dummy_path
run_generator [destination_root, "--dummy_path", "spec/dummy", "--skip-test"]
- assert_file "spec/dummy"
- assert_file "spec/dummy/config/application.rb"
- assert_no_file "test"
- assert_no_file "test/test_helper.rb"
+ assert_directory "spec/dummy"
+ assert_file "spec/dummy/config/application.rb", /#\s+require\s+["']rails\/test_unit\/railtie["']/
+ assert_no_directory "test"
assert_file ".gitignore" do |contents|
assert_match(/spec\/dummy/, contents)
end
@@ -490,8 +488,9 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_no_file "test/dummy/Gemfile"
assert_no_file "test/dummy/public/robots.txt"
assert_no_file "test/dummy/README.md"
+ assert_no_file "test/dummy/config/master.key"
+ assert_no_file "test/dummy/config/credentials.yml.enc"
assert_no_directory "test/dummy/lib/tasks"
- assert_no_directory "test/dummy/doc"
assert_no_directory "test/dummy/test"
assert_no_directory "test/dummy/vendor"
assert_no_directory "test/dummy/.git"
@@ -499,9 +498,9 @@ class PluginGeneratorTest < Rails::Generators::TestCase
def test_skipping_test_files
run_generator [destination_root, "--skip-test"]
- assert_no_file "test"
+ assert_no_directory "test"
assert_file ".gitignore" do |contents|
- assert_no_match(/test\dummy/, contents)
+ assert_no_match(/test\/dummy/, contents)
end
end
@@ -530,10 +529,11 @@ class PluginGeneratorTest < Rails::Generators::TestCase
gemfile_path = "#{Rails.root}/Gemfile"
Object.const_set("APP_PATH", Rails.root)
FileUtils.touch gemfile_path
+ File.write(gemfile_path, "#foo")
run_generator
- assert_file gemfile_path, /gem 'bukkits', path: 'tmp\/bukkits'/
+ assert_file gemfile_path, /^gem 'bukkits', path: 'tmp\/bukkits'/
ensure
Object.send(:remove_const, "APP_PATH")
FileUtils.rm gemfile_path
@@ -679,20 +679,6 @@ class PluginGeneratorTest < Rails::Generators::TestCase
assert_file "app/models/bukkits/article.rb", /class Article < ApplicationRecord/
end
- def test_generate_application_record_when_does_not_exist_in_mountable_engine
- run_generator [destination_root, "--mountable"]
- FileUtils.rm "#{destination_root}/app/models/bukkits/application_record.rb"
- capture(:stdout) do
- `#{destination_root}/bin/rails g model article`
- end
-
- assert_file "#{destination_root}/app/models/bukkits/application_record.rb" do |record|
- assert_match(/module Bukkits/, record)
- assert_match(/class ApplicationRecord < ActiveRecord::Base/, record)
- assert_match(/self\.abstract_class = true/, record)
- end
- end
-
def test_generate_application_mailer_when_does_not_exist_in_mountable_engine
run_generator [destination_root, "--mountable"]
FileUtils.rm "#{destination_root}/app/mailers/bukkits/application_mailer.rb"
@@ -749,6 +735,38 @@ class PluginGeneratorTest < Rails::Generators::TestCase
Object.send(:remove_const, "ENGINE_ROOT")
end
+ def test_after_bundle_callback
+ path = "http://example.org/rails_template"
+ template = %{ after_bundle { run "echo ran after_bundle" } }.dup
+ template.instance_eval "def read; self; end" # Make the string respond to read
+
+ check_open = -> *args do
+ assert_equal [ path, "Accept" => "application/x-thor-template" ], args
+ template
+ end
+
+ sequence = ["echo ran after_bundle"]
+ @sequence_step ||= 0
+ ensure_bundler_first = -> command do
+ assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}"
+ @sequence_step += 1
+ end
+
+ content = nil
+ generator([destination_root], template: path).stub(:open, check_open, template) do
+ generator.stub(:bundle_command, ensure_bundler_first) do
+ generator.stub(:run, ensure_bundler_first) do
+ silence_stream($stdout) do
+ content = capture(:stderr) { generator.invoke_all }
+ end
+ end
+ end
+ end
+
+ assert_equal 1, @sequence_step
+ assert_match(/DEPRECATION WARNING: `after_bundle` is deprecated/, content)
+ end
+
private
def action(*args, &block)
diff --git a/railties/test/generators/plugin_test_helper.rb b/railties/test/generators/plugin_test_helper.rb
index 8ac90e3484..528f8d88f9 100644
--- a/railties/test/generators/plugin_test_helper.rb
+++ b/railties/test/generators/plugin_test_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "tmpdir"
diff --git a/railties/test/generators/plugin_test_runner_test.rb b/railties/test/generators/plugin_test_runner_test.rb
index 0bdd2a77d2..89c3f1e496 100644
--- a/railties/test/generators/plugin_test_runner_test.rb
+++ b/railties/test/generators/plugin_test_runner_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/plugin_test_helper"
class PluginTestRunnerTest < ActiveSupport::TestCase
@@ -71,7 +73,7 @@ class PluginTestRunnerTest < ActiveSupport::TestCase
create_test_file "post", pass: false
output = run_test_command("test/post_test.rb")
- assert_match %r{Finished in.*\n\n1 runs, 1 assertions}, output
+ assert_match %r{Finished in.*\n1 runs, 1 assertions}, output
end
def test_fail_fast
@@ -103,6 +105,12 @@ class PluginTestRunnerTest < ActiveSupport::TestCase
capture(:stderr) { run_test_command("test/models/warnings_test.rb -w") })
end
+ def test_run_rake_test
+ create_test_file "foo"
+ result = Dir.chdir(plugin_path) { `rake test TEST=test/foo_test.rb` }
+ assert_match "1 runs, 1 assertions, 0 failures", result
+ end
+
private
def plugin_path
"#{@destination_root}/bukkits"
diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb
index e976e58180..63a2cd3869 100644
--- a/railties/test/generators/resource_generator_test.rb
+++ b/railties/test/generators/resource_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/resource/resource_generator"
diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb
index 9971626f9f..fd5aa817b4 100644
--- a/railties/test/generators/scaffold_controller_generator_test.rb
+++ b/railties/test/generators/scaffold_controller_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
@@ -172,6 +174,29 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_instance_method :index, content do |m|
assert_match("@users = User.all", m)
end
+
+ assert_instance_method :create, content do |m|
+ assert_match("redirect_to [:admin, @user]", m)
+ end
+
+ assert_instance_method :update, content do |m|
+ assert_match("redirect_to [:admin, @user]", m)
+ end
+ end
+
+ assert_file "app/views/admin/users/index.html.erb" do |content|
+ assert_match("'Show', [:admin, user]", content)
+ assert_match("'Edit', edit_admin_user_path(user)", content)
+ assert_match("'Destroy', [:admin, user]", content)
+ assert_match("'New User', new_admin_user_path", content)
+ end
+
+ assert_file "app/views/admin/users/new.html.erb" do |content|
+ assert_match("'Back', admin_users_path", content)
+ end
+
+ assert_file "app/views/admin/users/_form.html.erb" do |content|
+ assert_match("model: [:admin, user]", content)
end
end
@@ -182,6 +207,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
Dir.chdir(engine_path) do
quietly { `bin/rails g controller dashboard foo` }
+ quietly { `bin/rails db:migrate RAILS_ENV=test` }
assert_match(/2 runs, 2 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`)
end
end
@@ -193,6 +219,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
Dir.chdir(engine_path) do
quietly { `bin/rails g controller dashboard foo` }
+ quietly { `bin/rails db:migrate RAILS_ENV=test` }
assert_match(/2 runs, 2 assertions, 0 failures, 0 errors/, `bin/rails test 2>&1`)
end
end
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index 9926d58d16..29426cd99f 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/scaffold/scaffold_generator"
@@ -280,7 +282,14 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
/class Admin::RolesTest < ApplicationSystemTestCase/
# Views
- %w(index edit new show _form).each do |view|
+ assert_file "app/views/admin/roles/index.html.erb" do |content|
+ assert_match("'Show', admin_role", content)
+ assert_match("'Edit', edit_admin_role_path(admin_role)", content)
+ assert_match("'Destroy', admin_role", content)
+ assert_match("'New Admin Role', new_admin_role_path", content)
+ end
+
+ %w(edit new show _form).each do |view|
assert_file "app/views/admin/roles/#{view}.html.erb"
end
assert_no_file "app/views/layouts/admin/roles.html.erb"
@@ -462,8 +471,8 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
assert_file "app/views/accounts/_form.html.erb" do |content|
- assert_match(/^\W{4}<%= form\.text_field :name, id: :account_name %>/, content)
- assert_match(/^\W{4}<%= form\.text_field :currency_id, id: :account_currency_id %>/, content)
+ assert_match(/^\W{4}<%= form\.text_field :name %>/, content)
+ assert_match(/^\W{4}<%= form\.text_field :currency_id %>/, content)
end
end
@@ -486,8 +495,8 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
assert_file "app/views/users/_form.html.erb" do |content|
- assert_match(/<%= form\.password_field :password, id: :user_password %>/, content)
- assert_match(/<%= form\.password_field :password_confirmation, id: :user_password_confirmation %>/, content)
+ assert_match(/<%= form\.password_field :password %>/, content)
+ assert_match(/<%= form\.password_field :password_confirmation %>/, content)
end
assert_file "app/views/users/index.html.erb" do |content|
diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb
index 5e75879964..aa577e4234 100644
--- a/railties/test/generators/shared_generator_tests.rb
+++ b/railties/test/generators/shared_generator_tests.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
#
# Tests, setup, and teardown common to the application and plugin generator suites.
#
@@ -7,7 +9,7 @@ module SharedGeneratorTests
super
Rails::Generators::AppGenerator.instance_variable_set("@desc", nil)
- Kernel::silence_warnings do
+ Kernel.silence_warnings do
Thor::Base.shell.send(:attr_accessor, :always_force)
@shell = Thor::Base.shell.new
@shell.send(:always_force=, true)
@@ -20,6 +22,10 @@ module SharedGeneratorTests
Rails.application = TestApp::Application.instance
end
+ def application_path
+ destination_root
+ end
+
def test_skeleton_is_created
run_generator
@@ -77,7 +83,7 @@ module SharedGeneratorTests
def test_template_is_executed_when_supplied_an_https_path
path = "https://gist.github.com/josevalim/103208/raw/"
- template = %{ say "It works!" }
+ template = %{ say "It works!" }.dup
template.instance_eval "def read; self; end" # Make the string respond to read
check_open = -> *args do
@@ -86,7 +92,9 @@ module SharedGeneratorTests
end
generator([destination_root], template: path).stub(:open, check_open, template) do
- quietly { assert_match(/It works!/, capture(:stdout) { generator.invoke_all }) }
+ generator.stub :bundle_command, nil do
+ quietly { assert_match(/It works!/, capture(:stdout) { generator.invoke_all }) }
+ end
end
end
@@ -97,15 +105,6 @@ module SharedGeneratorTests
end
end
- def test_skip_bundle
- assert_not_called(generator([destination_root], skip_bundle: true), :bundle_command) do
- quietly { generator.invoke_all }
- # skip_bundle is only about running bundle install, ensure the Gemfile is still
- # generated.
- assert_file "Gemfile"
- end
- end
-
def test_skip_git
run_generator [destination_root, "--skip-git", "--full"]
assert_no_file(".gitignore")
@@ -121,4 +120,245 @@ module SharedGeneratorTests
assert_no_file("app/models/concerns/.keep")
end
+
+ def test_default_frameworks_are_required_when_others_are_removed
+ run_generator [
+ destination_root,
+ "--skip-active-record",
+ "--skip-active-storage",
+ "--skip-action-mailer",
+ "--skip-action-cable",
+ "--skip-sprockets"
+ ]
+
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']rails["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']active_model\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']active_job\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_record\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']active_storage\/engine["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']action_controller\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_mailer\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']action_view\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']action_cable\/engine["']/
+ assert_file "#{application_path}/config/application.rb", /^# require\s+["']sprockets\/railtie["']/
+ assert_file "#{application_path}/config/application.rb", /^require\s+["']rails\/test_unit\/railtie["']/
+ end
+
+ def test_generator_without_skips
+ run_generator
+ assert_file "#{application_path}/config/application.rb", /\s+require\s+["']rails\/all["']/
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_match(/config\.action_mailer\.raise_delivery_errors = false/, content)
+ end
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_match(/config\.action_mailer\.delivery_method = :test/, content)
+ end
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_match(/# config\.action_mailer\.raise_delivery_errors = false/, content)
+ assert_match(/^ # config\.require_master_key = true/, content)
+ end
+ end
+
+ def test_gitignore_when_sqlite3
+ run_generator
+
+ assert_file ".gitignore" do |content|
+ assert_match(/sqlite3/, content)
+ end
+ end
+
+ def test_gitignore_when_non_sqlite3_db
+ run_generator([destination_root, "-d", "mysql"])
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/sqlite/i, content)
+ end
+ end
+
+ def test_generator_if_skip_active_record_is_given
+ run_generator [destination_root, "--skip-active-record"]
+ assert_no_directory "#{application_path}/db/"
+ assert_no_file "#{application_path}/config/database.yml"
+ assert_no_file "#{application_path}/app/models/application_record.rb"
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/
+ assert_file "test/test_helper.rb" do |helper_content|
+ assert_no_match(/fixtures :all/, helper_content)
+ end
+ assert_file "#{application_path}/bin/setup" do |setup_content|
+ assert_no_match(/db:setup/, setup_content)
+ end
+ assert_file "#{application_path}/bin/update" do |update_content|
+ assert_no_match(/db:migrate/, update_content)
+ end
+ assert_file ".gitignore" do |content|
+ assert_no_match(/sqlite/i, content)
+ end
+ end
+
+ def test_generator_for_active_storage
+ run_generator
+
+ assert_file "#{application_path}/app/assets/javascripts/application.js" do |content|
+ assert_match(/^\/\/= require activestorage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/storage.yml"
+ assert_directory "#{application_path}/storage"
+ assert_directory "#{application_path}/tmp/storage"
+
+ assert_file ".gitignore" do |content|
+ assert_match(/\/storage\//, content)
+ end
+ end
+
+ def test_generator_if_skip_active_storage_is_given
+ run_generator [destination_root, "--skip-active-storage"]
+
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/
+
+ assert_file "#{application_path}/app/assets/javascripts/application.js" do |content|
+ assert_no_match(/^\/\/= require activestorage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{application_path}/config/storage.yml"
+ assert_no_directory "#{application_path}/storage"
+ assert_no_directory "#{application_path}/tmp/storage"
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/\/storage\//, content)
+ end
+ end
+
+ def test_generator_does_not_generate_active_storage_contents_if_skip_active_record_is_given
+ run_generator [destination_root, "--skip-active-record"]
+
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/
+
+ assert_file "#{application_path}/app/assets/javascripts/application.js" do |content|
+ assert_no_match(/^\/\/= require activestorage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.active_storage/, content)
+ end
+
+ assert_no_file "#{application_path}/config/storage.yml"
+ assert_no_directory "#{application_path}/storage"
+ assert_no_directory "#{application_path}/tmp/storage"
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/\/storage\//, content)
+ end
+ end
+
+ def test_generator_if_skip_action_mailer_is_given
+ run_generator [destination_root, "--skip-action-mailer"]
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_mailer\/railtie["']/
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_file "#{application_path}/config/environments/test.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.action_mailer/, content)
+ end
+ assert_no_directory "#{application_path}/app/mailers"
+ assert_no_directory "#{application_path}/test/mailers"
+ end
+
+ def test_generator_if_skip_action_cable_is_given
+ run_generator [destination_root, "--skip-action-cable"]
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']action_cable\/engine["']/
+ assert_no_file "#{application_path}/config/cable.yml"
+ assert_no_file "#{application_path}/app/assets/javascripts/cable.js"
+ assert_no_directory "#{application_path}/app/assets/javascripts/channels"
+ assert_no_directory "#{application_path}/app/channels"
+ assert_file "Gemfile" do |content|
+ assert_no_match(/redis/, content)
+ end
+ end
+
+ def test_generator_if_skip_sprockets_is_given
+ run_generator [destination_root, "--skip-sprockets"]
+
+ assert_no_file "#{application_path}/config/initializers/assets.rb"
+
+ assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']sprockets\/railtie["']/
+
+ assert_file "Gemfile" do |content|
+ assert_no_match(/sass-rails/, content)
+ assert_no_match(/uglifier/, content)
+ assert_no_match(/coffee-rails/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/development.rb" do |content|
+ assert_no_match(/config\.assets\.debug/, content)
+ end
+
+ assert_file "#{application_path}/config/environments/production.rb" do |content|
+ assert_no_match(/config\.assets\.digest/, content)
+ assert_no_match(/config\.assets\.js_compressor/, content)
+ assert_no_match(/config\.assets\.css_compressor/, content)
+ assert_no_match(/config\.assets\.compile/, content)
+ end
+ end
+
+ def test_generator_for_yarn
+ run_generator
+ assert_file "#{application_path}/package.json", /dependencies/
+ assert_file "#{application_path}/config/initializers/assets.rb", /node_modules/
+
+ assert_file ".gitignore" do |content|
+ assert_match(/node_modules/, content)
+ assert_match(/yarn-error\.log/, content)
+ end
+ end
+
+ def test_generator_for_yarn_skipped
+ run_generator([destination_root, "--skip-yarn"])
+ assert_no_file "#{application_path}/package.json"
+ assert_no_file "#{application_path}/bin/yarn"
+
+ assert_file "#{application_path}/config/initializers/assets.rb" do |content|
+ assert_no_match(/node_modules/, content)
+ end
+
+ assert_file ".gitignore" do |content|
+ assert_no_match(/node_modules/, content)
+ assert_no_match(/yarn-error\.log/, content)
+ end
+ end
end
diff --git a/railties/test/generators/system_test_generator_test.rb b/railties/test/generators/system_test_generator_test.rb
index 4622360244..efa70a050b 100644
--- a/railties/test/generators/system_test_generator_test.rb
+++ b/railties/test/generators/system_test_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/system_test/system_test_generator"
diff --git a/railties/test/generators/task_generator_test.rb b/railties/test/generators/task_generator_test.rb
index 2285534bb9..5f162919d8 100644
--- a/railties/test/generators/task_generator_test.rb
+++ b/railties/test/generators/task_generator_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/task/task_generator"
diff --git a/railties/test/generators/test_runner_in_engine_test.rb b/railties/test/generators/test_runner_in_engine_test.rb
index 680dc2608e..0e15b5e388 100644
--- a/railties/test/generators/test_runner_in_engine_test.rb
+++ b/railties/test/generators/test_runner_in_engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/plugin_test_helper"
class TestRunnerInEngineTest < ActiveSupport::TestCase
diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb
index e07627f36d..a16a2d3f0a 100644
--- a/railties/test/generators_test.rb
+++ b/railties/test/generators_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "generators/generators_test_helper"
require "rails/generators/rails/model/model_generator"
require "rails/generators/test_unit/model/model_generator"
@@ -31,13 +33,26 @@ class GeneratorsTest < Rails::Generators::TestCase
def test_generator_suggestions
name = :migrationz
output = capture(:stdout) { Rails::Generators.invoke name }
- assert_match "Maybe you meant 'migration'", output
+ assert_match 'Maybe you meant "migration"?', output
+ end
+
+ def test_generator_suggestions_except_en_locale
+ orig_available_locales = I18n.available_locales
+ orig_default_locale = I18n.default_locale
+ I18n.available_locales = :ja
+ I18n.default_locale = :ja
+ name = :tas
+ output = capture(:stdout) { Rails::Generators.invoke name }
+ assert_match 'Maybe you meant "task"?', output
+ ensure
+ I18n.available_locales = orig_available_locales
+ I18n.default_locale = orig_default_locale
end
def test_generator_multiple_suggestions
name = :tas
output = capture(:stdout) { Rails::Generators.invoke name }
- assert_match "Maybe you meant 'task', 'job' or", output
+ assert_match 'Maybe you meant "task"?', output
end
def test_help_when_a_generator_with_required_arguments_is_invoked_without_arguments
@@ -49,7 +64,7 @@ class GeneratorsTest < Rails::Generators::TestCase
assert File.exist?(File.join(@path, "generators", "model_generator.rb"))
assert_called_with(Rails::Generators::ModelGenerator, :start, [["Account"], {}]) do
warnings = capture(:stderr) { Rails::Generators.invoke :model, ["Account"] }
- assert warnings.empty?
+ assert_empty warnings
end
end
@@ -124,7 +139,7 @@ class GeneratorsTest < Rails::Generators::TestCase
def test_rails_generators_help_does_not_include_app_nor_plugin_new
output = capture(:stdout) { Rails::Generators.help }
- assert_no_match(/app/, output)
+ assert_no_match(/app\W/, output)
assert_no_match(/[^:]plugin/, output)
end
diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb
index 4b67c91cc5..59fee245f9 100644
--- a/railties/test/initializable_test.rb
+++ b/railties/test/initializable_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/initializable"
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 7496b5f84a..3cde7c03b0 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Note:
# It is important to keep this file as light as possible
# the goal for tests that require this is to test booting up
@@ -36,7 +38,12 @@ module TestHelpers
end
def app_path(*args)
- tmp_path(*%w[app] + args)
+ path = tmp_path(*%w[app] + args)
+ if block_given?
+ yield path
+ else
+ path
+ end
end
def framework_path
@@ -54,10 +61,7 @@ module TestHelpers
@app ||= begin
ENV["RAILS_ENV"] = env
- # FIXME: shush Sass warning spam, not relevant to testing Railties
- Kernel.silence_warnings do
- require "#{app_path}/config/environment"
- end
+ require "#{app_path}/config/environment"
Rails.application
end
@@ -66,7 +70,7 @@ module TestHelpers
end
def extract_body(response)
- "".tap do |body|
+ "".dup.tap do |body|
response[2].each { |chunk| body << chunk }
end
end
@@ -83,22 +87,6 @@ module TestHelpers
assert_match "charset=utf-8", resp[1]["Content-Type"]
assert extract_body(resp).match(/Yay! You.*re on Rails!/)
end
-
- def assert_success(resp)
- assert_equal 202, resp[0]
- end
-
- def assert_missing(resp)
- assert_equal 404, resp[0]
- end
-
- def assert_header(key, value, resp)
- assert_equal value, resp[1][key.to_s]
- end
-
- def assert_body(expected, resp)
- assert_equal expected, extract_body(resp)
- end
end
module Generation
@@ -106,7 +94,6 @@ module TestHelpers
def build_app(options = {})
@prev_rails_env = ENV["RAILS_ENV"]
ENV["RAILS_ENV"] = "development"
- ENV["SECRET_KEY_BASE"] ||= SecureRandom.hex(16)
FileUtils.rm_rf(app_path)
FileUtils.cp_r(app_template_path, app_path)
@@ -125,22 +112,57 @@ module TestHelpers
end
end
- File.open("#{app_path}/config/database.yml", "w") do |f|
- f.puts <<-YAML
- default: &default
- adapter: sqlite3
- pool: 5
- timeout: 5000
- development:
- <<: *default
- database: db/development.sqlite3
- test:
- <<: *default
- database: db/test.sqlite3
- production:
- <<: *default
- database: db/production.sqlite3
- YAML
+ if options[:multi_db]
+ File.open("#{app_path}/config/database.yml", "w") do |f|
+ f.puts <<-YAML
+ default: &default
+ adapter: sqlite3
+ pool: 5
+ timeout: 5000
+ development:
+ primary:
+ <<: *default
+ database: db/development.sqlite3
+ animals:
+ <<: *default
+ database: db/development_animals.sqlite3
+ migrations_paths: db/animals_migrate
+ test:
+ primary:
+ <<: *default
+ database: db/test.sqlite3
+ animals:
+ <<: *default
+ database: db/test_animals.sqlite3
+ migrations_paths: db/animals_migrate
+ production:
+ primary:
+ <<: *default
+ database: db/production.sqlite3
+ animals:
+ <<: *default
+ database: db/production_animals.sqlite3
+ migrations_paths: db/animals_migrate
+ YAML
+ end
+ else
+ File.open("#{app_path}/config/database.yml", "w") do |f|
+ f.puts <<-YAML
+ default: &default
+ adapter: sqlite3
+ pool: 5
+ timeout: 5000
+ development:
+ <<: *default
+ database: db/development.sqlite3
+ test:
+ <<: *default
+ database: db/test.sqlite3
+ production:
+ <<: *default
+ database: db/production.sqlite3
+ YAML
+ end
end
add_to_config <<-RUBY
@@ -155,6 +177,7 @@ module TestHelpers
def teardown_app
ENV["RAILS_ENV"] = @prev_rails_env if @prev_rails_env
+ FileUtils.rm_rf(tmp_path)
end
# Make a very basic app, without creating the whole directory structure.
@@ -164,9 +187,10 @@ module TestHelpers
require "action_controller/railtie"
require "action_view/railtie"
- @app = Class.new(Rails::Application)
+ @app = Class.new(Rails::Application) do
+ def self.name; "RailtiesTestApp"; end
+ end
@app.config.eager_load = false
- @app.secrets.secret_key_base = "3b7cd727ee24e8444053437c36cc66c4"
@app.config.session_store :cookie_store, key: "_myapp_session"
@app.config.active_support.deprecation = :log
@app.config.active_support.test_order = :random
@@ -222,8 +246,8 @@ module TestHelpers
FileUtils.mkdir_p(dir)
app = File.readlines("#{app_path}/config/application.rb")
- app.insert(2, "$:.unshift(\"#{dir}/lib\")")
- app.insert(3, "require #{name.inspect}")
+ app.insert(4, "$:.unshift(\"#{dir}/lib\")")
+ app.insert(5, "require #{name.inspect}")
File.open("#{app_path}/config/application.rb", "r+") do |f|
f.puts app
@@ -234,10 +258,86 @@ module TestHelpers
end
end
- def script(script)
- Dir.chdir(app_path) do
- `#{Gem.ruby} #{app_path}/bin/rails #{script}`
+ # Invoke a bin/rails command inside the app
+ #
+ # allow_failure:: true to return normally if the command exits with
+ # a non-zero status. By default, this method will raise.
+ # stderr:: true to pass STDERR output straight to the "real" STDERR.
+ # By default, the STDERR and STDOUT of the process will be
+ # combined in the returned string.
+ def rails(*args, allow_failure: false, stderr: false)
+ args = args.flatten
+ fork = true
+
+ command = "bin/rails #{Shellwords.join args}#{' 2>&1' unless stderr}"
+
+ # Don't fork if the environment has disabled it
+ fork = false if ENV["NO_FORK"]
+
+ # Don't fork if the runtime isn't able to
+ fork = false if !Process.respond_to?(:fork)
+
+ # Don't fork if we're re-invoking minitest
+ fork = false if args.first == "t" || args.grep(/\Atest(:|\z)/).any?
+
+ if fork
+ out_read, out_write = IO.pipe
+ if stderr
+ err_read, err_write = IO.pipe
+ else
+ err_write = out_write
+ end
+
+ pid = fork do
+ out_read.close
+ err_read.close if err_read
+
+ $stdin.reopen(File::NULL, "r")
+ $stdout.reopen(out_write)
+ $stderr.reopen(err_write)
+
+ at_exit do
+ case $!
+ when SystemExit
+ exit! $!.status
+ when nil
+ exit! 0
+ else
+ err_write.puts "#{$!.class}: #{$!}"
+ exit! 1
+ end
+ end
+
+ Rails.instance_variable_set :@_env, nil
+
+ $-v = $-w = false
+ Dir.chdir app_path unless Dir.pwd == app_path
+
+ ARGV.replace(args)
+ load "./bin/rails"
+
+ exit! 0
+ end
+
+ out_write.close
+
+ if err_read
+ err_write.close
+
+ $stderr.write err_read.read
+ end
+
+ output = out_read.read
+
+ Process.waitpid pid
+
+ else
+ output = `cd #{app_path}; #{command}`
end
+
+ raise "rails command failed (#{$?.exitstatus}): #{command}\n#{output}" unless allow_failure || $?.success?
+
+ output
end
def add_to_top_of_config(str)
@@ -282,10 +382,12 @@ module TestHelpers
end
def app_file(path, contents, mode = "w")
- FileUtils.mkdir_p File.dirname("#{app_path}/#{path}")
- File.open("#{app_path}/#{path}", mode) do |f|
+ file_name = "#{app_path}/#{path}"
+ FileUtils.mkdir_p File.dirname(file_name)
+ File.open(file_name, mode) do |f|
f.puts contents
end
+ file_name
end
def remove_file(path)
@@ -297,7 +399,7 @@ module TestHelpers
end
def use_frameworks(arr)
- to_remove = [:actionmailer, :activerecord] - arr
+ to_remove = [:actionmailer, :activerecord, :activestorage, :activejob] - arr
if to_remove.include?(:activerecord)
remove_from_config "config.active_record.*"
@@ -305,6 +407,21 @@ module TestHelpers
$:.reject! { |path| path =~ %r'/(#{to_remove.join('|')})/' }
end
+
+ def use_postgresql
+ File.open("#{app_path}/config/database.yml", "w") do |f|
+ f.puts <<-YAML
+ default: &default
+ adapter: postgresql
+ pool: 5
+ database: railties_test
+ development:
+ <<: *default
+ test:
+ <<: *default
+ YAML
+ end
+ end
end
end
@@ -314,7 +431,9 @@ class ActiveSupport::TestCase
include TestHelpers::Generation
include ActiveSupport::Testing::Stream
- self.test_order = :sorted
+ def frozen_error_class
+ Object.const_defined?(:FrozenError) ? FrozenError : RuntimeError
+ end
end
# Create a scope and build a fixture rails app
@@ -329,4 +448,25 @@ Module.new do
File.open("#{app_template_path}/config/boot.rb", "w") do |f|
f.puts "require 'rails/all'"
end
+
+ # 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")
+ contents.sub!(/^Bundler\.require.*/, "%w(turbolinks).each { |r| require r }")
+ File.write("#{app_template_path}/config/application.rb", contents)
+
+ require "rails"
+
+ require "active_model"
+ require "active_job"
+ require "active_record"
+ require "action_controller"
+ require "action_mailer"
+ require "action_view"
+ require "active_storage"
+ require "action_cable"
+ require "sprockets"
+
+ require "action_view/helpers"
+ require "action_dispatch/routing/route_set"
end unless defined?(RAILS_ISOLATED_ENGINE)
diff --git a/railties/test/json_params_parsing_test.rb b/railties/test/json_params_parsing_test.rb
index 7fff3bb465..65ad9673ff 100644
--- a/railties/test/json_params_parsing_test.rb
+++ b/railties/test/json_params_parsing_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "action_dispatch"
require "active_record"
diff --git a/railties/test/minitest/rails_plugin_test.rb b/railties/test/minitest/rails_plugin_test.rb
new file mode 100644
index 0000000000..7c3a2022a9
--- /dev/null
+++ b/railties/test/minitest/rails_plugin_test.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class Minitest::RailsPluginTest < ActiveSupport::TestCase
+ setup do
+ @options = Minitest.process_args []
+ @output = StringIO.new("".encode("UTF-8"))
+ end
+
+ test "default reporters are replaced" do
+ with_reporter Minitest::CompositeReporter.new do |reporter|
+ reporter << Minitest::SummaryReporter.new(@output, @options)
+ reporter << Minitest::ProgressReporter.new(@output, @options)
+ reporter << Minitest::Reporter.new(@output, @options)
+
+ Minitest.plugin_rails_init({})
+
+ assert_equal 3, reporter.reporters.count
+ assert reporter.reporters.any? { |candidate| candidate.kind_of?(Minitest::SuppressedSummaryReporter) }
+ assert reporter.reporters.any? { |candidate| candidate.kind_of?(::Rails::TestUnitReporter) }
+ assert reporter.reporters.any? { |candidate| candidate.kind_of?(Minitest::Reporter) }
+ end
+ end
+
+ test "no custom reporters are added if nothing to replace" do
+ with_reporter Minitest::CompositeReporter.new do |reporter|
+ Minitest.plugin_rails_init({})
+
+ assert_empty reporter.reporters
+ end
+ end
+
+ private
+ def with_reporter(reporter)
+ old_reporter, Minitest.reporter = Minitest.reporter, reporter
+
+ yield reporter
+ ensure
+ Minitest.reporter = old_reporter
+ end
+end
diff --git a/railties/test/path_generation_test.rb b/railties/test/path_generation_test.rb
index c0b03d0c15..849b183b37 100644
--- a/railties/test/path_generation_test.rb
+++ b/railties/test/path_generation_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "active_support/core_ext/object/with_options"
require "active_support/core_ext/object/json"
@@ -56,12 +58,14 @@ class PathGenerationTest < ActiveSupport::TestCase
Rails.logger = Logger.new nil
app = Class.new(Rails::Application) {
+ def self.name; "ScriptNameTestApp"; end
+
attr_accessor :controller
+
def initialize
super
app = self
@routes = TestSet.new ->(c) { app.controller = c }
- secrets.secret_key_base = "foo"
secrets.secret_token = "foo"
end
def app; routes; end
diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb
index f3db0a51d2..9f5bb37c20 100644
--- a/railties/test/paths_test.rb
+++ b/railties/test/paths_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/paths"
require "minitest/mock"
@@ -102,7 +104,7 @@ class PathsTest < ActiveSupport::TestCase
File.stub(:exist?, true) do
@root.add "app", with: "/app"
@root["app"].autoload_once!
- assert @root["app"].autoload_once?
+ assert_predicate @root["app"], :autoload_once?
assert_includes @root.autoload_once, @root["app"].expanded.first
end
end
@@ -110,17 +112,17 @@ class PathsTest < ActiveSupport::TestCase
test "it is possible to remove a path that should be autoloaded only once" do
@root["app"] = "/app"
@root["app"].autoload_once!
- assert @root["app"].autoload_once?
+ assert_predicate @root["app"], :autoload_once?
@root["app"].skip_autoload_once!
- assert !@root["app"].autoload_once?
+ assert_not_predicate @root["app"], :autoload_once?
assert_not_includes @root.autoload_once, @root["app"].expanded.first
end
test "it is possible to add a path without assignment and specify it should be loaded only once" do
File.stub(:exist?, true) do
@root.add "app", with: "/app", autoload_once: true
- assert @root["app"].autoload_once?
+ assert_predicate @root["app"], :autoload_once?
assert_includes @root.autoload_once, "/app"
end
end
@@ -128,7 +130,7 @@ class PathsTest < ActiveSupport::TestCase
test "it is possible to add multiple paths without assignment and specify it should be loaded only once" do
File.stub(:exist?, true) do
@root.add "app", with: ["/app", "/app2"], autoload_once: true
- assert @root["app"].autoload_once?
+ assert_predicate @root["app"], :autoload_once?
assert_includes @root.autoload_once, "/app"
assert_includes @root.autoload_once, "/app2"
end
@@ -156,7 +158,7 @@ class PathsTest < ActiveSupport::TestCase
File.stub(:exist?, true) do
@root["app"] = "/app"
@root["app"].eager_load!
- assert @root["app"].eager_load?
+ assert_predicate @root["app"], :eager_load?
assert_includes @root.eager_load, @root["app"].to_a.first
end
end
@@ -164,17 +166,17 @@ class PathsTest < ActiveSupport::TestCase
test "it is possible to skip a path from eager loading" do
@root["app"] = "/app"
@root["app"].eager_load!
- assert @root["app"].eager_load?
+ assert_predicate @root["app"], :eager_load?
@root["app"].skip_eager_load!
- assert !@root["app"].eager_load?
+ assert_not_predicate @root["app"], :eager_load?
assert_not_includes @root.eager_load, @root["app"].to_a.first
end
test "it is possible to add a path without assignment and mark it as eager" do
File.stub(:exist?, true) do
@root.add "app", with: "/app", eager_load: true
- assert @root["app"].eager_load?
+ assert_predicate @root["app"], :eager_load?
assert_includes @root.eager_load, "/app"
end
end
@@ -182,7 +184,7 @@ class PathsTest < ActiveSupport::TestCase
test "it is possible to add multiple paths without assignment and mark them as eager" do
File.stub(:exist?, true) do
@root.add "app", with: ["/app", "/app2"], eager_load: true
- assert @root["app"].eager_load?
+ assert_predicate @root["app"], :eager_load?
assert_includes @root.eager_load, "/app"
assert_includes @root.eager_load, "/app2"
end
@@ -191,8 +193,8 @@ class PathsTest < ActiveSupport::TestCase
test "it is possible to create a path without assignment and mark it both as eager and load once" do
File.stub(:exist?, true) do
@root.add "app", with: "/app", eager_load: true, autoload_once: true
- assert @root["app"].eager_load?
- assert @root["app"].autoload_once?
+ assert_predicate @root["app"], :eager_load?
+ assert_predicate @root["app"], :autoload_once?
assert_includes @root.eager_load, "/app"
assert_includes @root.autoload_once, "/app"
end
@@ -252,7 +254,7 @@ class PathsTest < ActiveSupport::TestCase
test "a path can be added to the load path on creation" do
File.stub(:exist?, true) do
@root.add "app", with: "/app", load_path: true
- assert @root["app"].load_path?
+ assert_predicate @root["app"], :load_path?
assert_equal ["/app"], @root.load_paths
end
end
@@ -269,7 +271,7 @@ class PathsTest < ActiveSupport::TestCase
test "a path can be marked as autoload on creation" do
File.stub(:exist?, true) do
@root.add "app", with: "/app", autoload: true
- assert @root["app"].autoload?
+ assert_predicate @root["app"], :autoload?
assert_equal ["/app"], @root.autoload_paths
end
end
diff --git a/railties/test/rack_logger_test.rb b/railties/test/rack_logger_test.rb
index 33b4bc6a3a..6e8f333e1d 100644
--- a/railties/test/rack_logger_test.rb
+++ b/railties/test/rack_logger_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "active_support/testing/autorun"
require "active_support/test_case"
@@ -12,14 +14,21 @@ module Rails
attr_reader :logger
- def initialize(logger = NULL, taggers = nil, &block)
- super(->(_) { block.call; [200, {}, []] }, taggers)
+ def initialize(logger = NULL, app: nil, taggers: nil, &block)
+ app ||= ->(_) { block.call; [200, {}, []] }
+ super(app, taggers)
@logger = logger
end
def development?; false; end
end
+ class TestApp < Struct.new(:response)
+ def call(_env)
+ response
+ end
+ end
+
Subscriber = Struct.new(:starts, :finishes) do
def initialize(starts = [], finishes = [])
super
@@ -70,6 +79,17 @@ module Rails
end
end
end
+
+ def test_logger_does_not_mutate_app_return
+ response = [].freeze
+ app = TestApp.new(response)
+ logger = TestLogger.new(app: app)
+ assert_no_changes("response") do
+ assert_nothing_raised do
+ logger.call("REQUEST_METHOD" => "GET")
+ end
+ end
+ end
end
end
end
diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb
index d795629ccd..878a238f8d 100644
--- a/railties/test/rails_info_controller_test.rb
+++ b/railties/test/rails_info_controller_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
module ActionController
diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb
index 383adcc55d..50522c1be6 100644
--- a/railties/test/rails_info_test.rb
+++ b/railties/test/rails_info_test.rb
@@ -1,26 +1,15 @@
-require "abstract_unit"
-
-unless defined?(Rails) && defined?(Rails::Info)
- module Rails
- class Info; end
- end
-end
+# frozen_string_literal: true
-require "active_support/core_ext/kernel/reporting"
+require "abstract_unit"
class InfoTest < ActiveSupport::TestCase
- def setup
- Rails.send :remove_const, :Info
- silence_warnings { load "rails/info.rb" }
- end
-
def test_property_with_block_swallows_exceptions_and_ignores_property
assert_nothing_raised do
Rails::Info.module_eval do
property("Bogus") { raise }
end
end
- assert !property_defined?("Bogus")
+ assert_not property_defined?("Bogus")
end
def test_property_with_string
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 0379394f31..9a3ddc8d5e 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
require "stringio"
require "rack/test"
@@ -30,6 +32,11 @@ module RailtiesTest
require "#{app_path}/config/environment"
end
+ def migrations
+ migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path)
+ ActiveRecord::MigrationContext.new(migration_root).migrations
+ end
+
test "serving sprocket's assets" do
@plugin.write "app/assets/javascripts/engine.js.erb", "<%= :alert %>();"
add_to_env_config "development", "config.assets.digest = false"
@@ -80,31 +87,32 @@ module RailtiesTest
end
RUBY
- add_to_config "ActiveRecord::Base.timestamped_migrations = false"
-
boot_rails
Dir.chdir(app_path) do
+ # Install Active Storage migration file first so as not to affect test.
+ `bundle exec rake active_storage:install`
output = `bundle exec rake bukkits:install:migrations`
- assert File.exist?("#{app_path}/db/migrate/2_create_users.bukkits.rb")
- assert File.exist?("#{app_path}/db/migrate/3_add_last_name_to_users.bukkits.rb")
- assert_match(/Copied migration 2_create_users\.bukkits\.rb from bukkits/, output)
- assert_match(/Copied migration 3_add_last_name_to_users\.bukkits\.rb from bukkits/, output)
- assert_match(/NOTE: Migration 3_create_sessions\.rb from bukkits has been skipped/, output)
- assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length
-
- output = `bundle exec rake railties:install:migrations`.split("\n")
+ ["CreateUsers", "AddLastNameToUsers", "CreateSessions"].each do |migration_name|
+ assert migrations.detect { |migration| migration.name == migration_name }
+ end
+ assert_match(/Copied migration \d+_create_users\.bukkits\.rb from bukkits/, output)
+ assert_match(/Copied migration \d+_add_last_name_to_users\.bukkits\.rb from bukkits/, output)
+ assert_match(/NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/, output)
- assert_no_match(/2_create_users/, output.join("\n"))
+ migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration 3_create_sessions\.rb from bukkits has been skipped/ =~ o })
- assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
+ assert_equal migrations.length, migrations_count
- migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- `bundle exec rake railties:install:migrations`
+ output = `bundle exec rake railties:install:migrations`.split("\n")
assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length
+
+ assert_no_match(/\d+_create_users/, output.join("\n"))
+
+ bukkits_migration_order = output.index(output.detect { |o| /NOTE: Migration \d+_create_sessions\.rb from bukkits has been skipped/ =~ o })
+ assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
end
end
@@ -136,7 +144,7 @@ module RailtiesTest
output = `bundle exec rake railties:install:migrations`.split("\n")
assert_match(/Copied migration \d+_create_users\.bukkits\.rb from bukkits/, output.first)
- assert_match(/Copied migration \d+_create_blogs\.blog_engine\.rb from blog_engine/, output.last)
+ assert_match(/Copied migration \d+_create_blogs\.blog_engine\.rb from blog_engine/, output.second)
end
end
@@ -169,10 +177,12 @@ module RailtiesTest
boot_rails
Dir.chdir(app_path) do
+ # Install Active Storage migration file first so as not to affect test.
+ `bundle exec rake active_storage:install`
output = `bundle exec rake railties:install:migrations`.split("\n")
assert_match(/Copied migration \d+_create_users\.core_engine\.rb from core_engine/, output.first)
- assert_match(/Copied migration \d+_create_keys\.api_engine\.rb from api_engine/, output.last)
+ assert_match(/Copied migration \d+_create_keys\.api_engine\.rb from api_engine/, output.second)
end
end
@@ -201,9 +211,12 @@ module RailtiesTest
Dir.chdir(@plugin.path) do
output = `bundle exec rake app:bukkits:install:migrations`
- assert File.exist?("#{app_path}/db/migrate/0_add_first_name_to_users.bukkits.rb")
- assert_match(/Copied migration 0_add_first_name_to_users\.bukkits\.rb from bukkits/, output)
- assert_equal 1, Dir["#{app_path}/db/migrate/*.rb"].length
+
+ migration_with_engine_path = migrations.detect { |migration| migration.name == "AddFirstNameToUsers" }
+ assert migration_with_engine_path
+ assert_match(/\/db\/migrate\/\d+_add_first_name_to_users\.bukkits\.rb/, migration_with_engine_path.filename)
+ assert_match(/Copied migration \d+_add_first_name_to_users\.bukkits\.rb from bukkits/, output)
+ assert_equal migrations.length, Dir["#{app_path}/db/migrate/*.rb"].length
end
end
@@ -213,7 +226,7 @@ module RailtiesTest
require "rdoc/task"
require "rake/testtask"
Rails.application.load_tasks
- assert !Rake::Task.task_defined?("bukkits:install:migrations")
+ assert_not Rake::Task.task_defined?("bukkits:install:migrations")
end
test "puts its lib directory on load path" do
@@ -503,7 +516,7 @@ YAML
def call(env)
response = @app.call(env)
- response[2].each(&:upcase!)
+ response[2] = response[2].collect(&:upcase)
response
end
end
@@ -732,7 +745,7 @@ YAML
assert_equal "bukkits", Bukkits::Engine.engine_name
assert_equal Bukkits.railtie_namespace, Bukkits::Engine
assert ::Bukkits::MyMailer.method_defined?(:foo_url)
- assert !::Bukkits::MyMailer.method_defined?(:bar_url)
+ assert_not ::Bukkits::MyMailer.method_defined?(:bar_url)
get("/bukkits/from_app")
assert_equal "false", last_response.body
@@ -882,7 +895,17 @@ YAML
end
RUBY
- add_to_config "isolate_namespace AppTemplate"
+ engine "loaded_first" do |plugin|
+ plugin.write "lib/loaded_first.rb", <<-RUBY
+ module AppTemplate
+ module LoadedFirst
+ class Engine < ::Rails::Engine
+ isolate_namespace(AppTemplate)
+ end
+ end
+ end
+ RUBY
+ end
app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do end
@@ -890,7 +913,7 @@ YAML
boot_rails
- assert_equal AppTemplate::Engine, AppTemplate.railtie_namespace
+ assert_equal AppTemplate::LoadedFirst::Engine, AppTemplate.railtie_namespace
end
test "properly reload routes" do
@@ -957,14 +980,14 @@ YAML
boot_rails
app_generators = Rails.application.config.generators.options[:rails]
- assert_equal :mongoid , app_generators[:orm]
- assert_equal :liquid , app_generators[:template_engine]
+ assert_equal :mongoid, app_generators[:orm]
+ assert_equal :liquid, app_generators[:template_engine]
assert_equal :test_unit, app_generators[:test_framework]
generators = Bukkits::Engine.config.generators.options[:rails]
assert_equal :data_mapper, generators[:orm]
- assert_equal :haml , generators[:template_engine]
- assert_equal :rspec , generators[:test_framework]
+ assert_equal :haml, generators[:template_engine]
+ assert_equal :rspec, generators[:test_framework]
end
test "engine should get default generators with ability to overwrite them" do
@@ -980,10 +1003,10 @@ YAML
generators = Bukkits::Engine.config.generators.options[:rails]
assert_equal :active_record, generators[:orm]
- assert_equal :rspec , generators[:test_framework]
+ assert_equal :rspec, generators[:test_framework]
app_generators = Rails.application.config.generators.options[:rails]
- assert_equal :test_unit , app_generators[:test_framework]
+ assert_equal :test_unit, app_generators[:test_framework]
end
test "do not create table_name_prefix method if it already exists" do
@@ -1285,10 +1308,10 @@ YAML
boot_rails
- get("/bukkits/bukkit", {}, "SCRIPT_NAME" => "/foo")
+ get("/bukkits/bukkit", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bar", last_response.body
- get("/bar", {}, "SCRIPT_NAME" => "/foo")
+ get("/bar", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bukkits/bukkit", last_response.body
end
@@ -1334,10 +1357,10 @@ YAML
boot_rails
- get("/bukkits/bukkit", {}, "SCRIPT_NAME" => "/foo")
+ get("/bukkits/bukkit", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bar", last_response.body
- get("/bar", {}, "SCRIPT_NAME" => "/foo")
+ get("/bar", {}, { "SCRIPT_NAME" => "/foo" })
assert_equal "/foo/bukkits/bukkit", last_response.body
end
@@ -1427,6 +1450,50 @@ YAML
assert_equal "/vegetables/1/bukkits/posts", last_response.body
end
+ test "route helpers resolve script name correctly when called with different script name from current one" do
+ @plugin.write "app/controllers/posts_controller.rb", <<-RUBY
+ class PostsController < ActionController::Base
+ def index
+ render plain: fruit_bukkits.posts_path(fruit_id: 2)
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ Rails.application.routes.draw do
+ resources :fruits do
+ mount Bukkits::Engine => "/bukkits"
+ end
+ end
+ RUBY
+
+ @plugin.write "config/routes.rb", <<-RUBY
+ Bukkits::Engine.routes.draw do
+ resources :posts, only: :index
+ end
+ RUBY
+
+ boot_rails
+
+ get("/fruits/1/bukkits/posts")
+ assert_equal "/fruits/2/bukkits/posts", last_response.body
+ end
+
+ test "active_storage:install task works within engine" do
+ @plugin.write "Rakefile", <<-RUBY
+ APP_RAKEFILE = '#{app_path}/Rakefile'
+ load 'rails/tasks/engine.rake'
+ RUBY
+
+ Dir.chdir(@plugin.path) do
+ output = `bundle exec rake app:active_storage:install`
+ assert $?.success?, output
+
+ active_storage_migration = migrations.detect { |migration| migration.name == "CreateActiveStorageTables" }
+ assert active_storage_migration
+ end
+ end
+
private
def app
Rails.application
diff --git a/railties/test/railties/generators_test.rb b/railties/test/railties/generators_test.rb
index 5c691b9ec4..8383cb3050 100644
--- a/railties/test/railties/generators_test.rb
+++ b/railties/test/railties/generators_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RAILS_ISOLATED_ENGINE = true
require "isolation/abstract_unit"
diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb
index 6639e55382..48f0fbc80f 100644
--- a/railties/test/railties/mounted_engine_test.rb
+++ b/railties/test/railties/mounted_engine_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module ApplicationTests
@@ -111,6 +113,7 @@ module ApplicationTests
@plugin.write "config/routes.rb", <<-RUBY
Blog::Engine.routes.draw do
resources :posts
+ get '/different_context', to: 'posts#different_context'
get '/generate_application_route', to: 'posts#generate_application_route'
get '/application_route_in_view', to: 'posts#application_route_in_view'
get '/engine_polymorphic_path', to: 'posts#engine_polymorphic_path'
@@ -125,6 +128,10 @@ module ApplicationTests
render plain: blog.post_path(1)
end
+ def different_context
+ render plain: blog.post_path(1, user: "ada")
+ end
+
def generate_application_route
path = main_app.url_for(controller: "/main",
action: "index",
@@ -196,8 +203,12 @@ module ApplicationTests
get "/john/blog/posts"
assert_equal "/john/blog/posts/1", last_response.body
+ # test generating engine route from engine with a different context
+ get "/john/blog/different_context"
+ assert_equal "/ada/blog/posts/1", last_response.body
+
# test generating engine's route from engine with default_url_options
- get "/john/blog/posts", {}, "SCRIPT_NAME" => "/foo"
+ get "/john/blog/posts", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/john/blog/posts/1", last_response.body
# test generating engine's route from application
@@ -211,10 +222,10 @@ module ApplicationTests
assert_equal "/john/blog/posts", last_response.body
# test generating engine's route from application with default_url_options
- get "/engine_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/engine_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/anonymous/blog/posts", last_response.body
- get "/url_for_engine_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/url_for_engine_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/john/blog/posts", last_response.body
# test generating application's route from engine
@@ -232,14 +243,14 @@ module ApplicationTests
assert_equal "/anonymous/blog/posts/1", last_response.body
# test generating engine's route from other engine with default_url_options
- get "/metrics/generate_blog_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/metrics/generate_blog_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/anonymous/blog/posts/1", last_response.body
- get "/metrics/generate_blog_route_in_view", {}, "SCRIPT_NAME" => "/foo"
+ get "/metrics/generate_blog_route_in_view", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/anonymous/blog/posts/1", last_response.body
# test generating application's route from engine with default_url_options
- get "/someone/blog/generate_application_route", {}, "SCRIPT_NAME" => "/foo"
+ get "/someone/blog/generate_application_route", {}, { "SCRIPT_NAME" => "/foo" }
assert_equal "/foo/", last_response.body
# test polymorphic routes
diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb
index 30cd525266..7c3d1e3759 100644
--- a/railties/test/railties/railtie_test.rb
+++ b/railties/test/railties/railtie_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
module RailtiesTest
@@ -63,7 +65,7 @@ module RailtiesTest
test "railtie can add to_prepare callbacks" do
$to_prepare = false
class Foo < Rails::Railtie ; config.to_prepare { $to_prepare = true } ; end
- assert !$to_prepare
+ assert_not $to_prepare
require "#{app_path}/config/environment"
require "rack/test"
extend Rack::Test::Methods
@@ -89,7 +91,7 @@ module RailtiesTest
test "railtie can add after_initialize callbacks" do
$after_initialize = false
class Foo < Rails::Railtie ; config.after_initialize { $after_initialize = true } ; end
- assert !$after_initialize
+ assert_not $after_initialize
require "#{app_path}/config/environment"
assert $after_initialize
end
@@ -105,7 +107,7 @@ module RailtiesTest
require "#{app_path}/config/environment"
- assert !$ran_block
+ assert_not $ran_block
require "rake"
require "rake/testtask"
require "rdoc/task"
@@ -149,7 +151,7 @@ module RailtiesTest
require "#{app_path}/config/environment"
- assert !$ran_block
+ assert_not $ran_block
Rails.application.load_generators
assert $ran_block
end
@@ -165,7 +167,7 @@ module RailtiesTest
require "#{app_path}/config/environment"
- assert !$ran_block
+ assert_not $ran_block
Rails.application.load_console
assert $ran_block
end
@@ -181,7 +183,7 @@ module RailtiesTest
require "#{app_path}/config/environment"
- assert !$ran_block
+ assert_not $ran_block
Rails.application.load_runner
assert $ran_block
end
@@ -195,7 +197,7 @@ module RailtiesTest
end
end
- assert !$ran_block
+ assert_not $ran_block
require "#{app_path}/config/environment"
assert $ran_block
end
diff --git a/railties/test/secrets_test.rb b/railties/test/secrets_test.rb
index d78c253765..06877bc76a 100644
--- a/railties/test/secrets_test.rb
+++ b/railties/test/secrets_test.rb
@@ -1,29 +1,24 @@
-require "abstract_unit"
+# frozen_string_literal: true
+
require "isolation/abstract_unit"
-require "rails/generators"
-require "rails/generators/rails/encrypted_secrets/encrypted_secrets_generator"
require "rails/secrets"
class Rails::SecretsTest < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
- def setup
- build_app
- end
-
- def teardown
- teardown_app
- end
+ setup :build_app
+ teardown :teardown_app
test "setting read to false skips parsing" do
run_secrets_generator do
Rails::Secrets.write(<<-end_of_secrets)
- test:
+ production:
yeah_yeah: lets-walk-in-the-cool-evening-light
end_of_secrets
- Rails.application.config.read_encrypted_secrets = false
- Rails.application.instance_variable_set(:@secrets, nil) # Dance around caching 💃🕺
+ add_to_env_config("production", "config.read_encrypted_secrets = false")
+ app("production")
+
assert_not Rails.application.secrets.yeah_yeah
end
end
@@ -45,7 +40,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase
ENV["RAILS_MASTER_KEY"] = IO.binread("config/secrets.yml.key").strip
FileUtils.rm("config/secrets.yml.key")
- assert_match "production:\n# external_api_key", Rails::Secrets.read
+ assert_match "# production:\n# external_api_key:", Rails::Secrets.read
ensure
ENV["RAILS_MASTER_KEY"] = old_key
end
@@ -67,7 +62,7 @@ class Rails::SecretsTest < ActiveSupport::TestCase
Rails::Secrets.read_for_editing do |tmp_path|
decrypted_path = tmp_path
- assert_match(/production:\n# external_api_key/, File.read(tmp_path))
+ assert_match(/# production:\n# external_api_key/, File.read(tmp_path))
File.write(tmp_path, "Empty streets, empty nights. The Downtown Lights.")
end
@@ -80,17 +75,18 @@ class Rails::SecretsTest < ActiveSupport::TestCase
test "merging secrets with encrypted precedence" do
run_secrets_generator do
File.write("config/secrets.yml", <<-end_of_secrets)
- test:
+ production:
yeah_yeah: lets-go-walking-down-this-empty-street
end_of_secrets
Rails::Secrets.write(<<-end_of_secrets)
- test:
+ production:
yeah_yeah: lets-walk-in-the-cool-evening-light
end_of_secrets
- Rails.application.config.read_encrypted_secrets = true
- Rails.application.instance_variable_set(:@secrets, nil) # Dance around caching 💃🕺
+ add_to_env_config("production", "config.read_encrypted_secrets = true")
+ app("production")
+
assert_equal "lets-walk-in-the-cool-evening-light", Rails.application.secrets.yeah_yeah
end
end
@@ -106,7 +102,9 @@ class Rails::SecretsTest < ActiveSupport::TestCase
config.dereferenced_secret = Rails.application.secrets.some_secret
end_of_config
- assert_equal "yeah yeah\n", `bin/rails runner -e production "puts Rails.application.config.dereferenced_secret"`
+ app("production")
+
+ assert_equal "yeah yeah", Rails.application.config.dereferenced_secret
end
end
@@ -133,13 +131,15 @@ class Rails::SecretsTest < ActiveSupport::TestCase
api_key: 00112233445566778899aabbccddeeff…
end_of_secrets
- Rails::Secrets.write(secrets.force_encoding(Encoding::ASCII_8BIT))
+ Rails::Secrets.write(secrets.dup.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"`
+ app("production")
+
+ assert_equal "00112233445566778899aabbccddeeff…", Rails.application.secrets.api_key
end
end
@@ -153,22 +153,24 @@ class Rails::SecretsTest < ActiveSupport::TestCase
Rails::Secrets.write(secrets)
Rails::Secrets.read_for_editing do |tmp_path|
- assert_equal(secrets.force_encoding(Encoding::ASCII_8BIT), IO.binread(tmp_path))
+ assert_equal(secrets.dup.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"`
+ app("production")
+
+ assert_equal "00112233445566778899aabbccddeeff…", Rails.application.secrets.api_key
end
end
private
def run_secrets_generator
Dir.chdir(app_path) do
- capture(:stdout) do
- Rails::Generators::EncryptedSecretsGenerator.start
- end
+ File.write("config/secrets.yml.key", "f731758c639da2604dfb6bf3d1025de8")
+ File.write("config/secrets.yml.enc", "sEB0mHxDbeP1/KdnMk00wyzPFACl9K6t0cZWn5/Mfx/YbTHvnI07vrneqHg9kaH3wOS7L6pIQteu1P077OtE4BSx/ZRc/sgQPHyWu/tXsrfHqnPNpayOF/XZqizE91JacSFItNMWpuPsp9ynbzz+7cGhoB1S4aPNIU6u0doMrzdngDbijsaAFJmsHIQh6t/QHoJx--8aMoE0PvUWmw1Iqz--ldFqnM/K0g9k17M8PKoN/Q==")
- # Make config.paths["config/secrets"] to be relative to app_path
- Rails.application.config.root = app_path
+ add_to_config <<-RUBY
+ config.read_encrypted_secrets = true
+ RUBY
yield
end
diff --git a/railties/test/test_unit/reporter_test.rb b/railties/test/test_unit/reporter_test.rb
index 42f973357b..91cb47779b 100644
--- a/railties/test/test_unit/reporter_test.rb
+++ b/railties/test/test_unit/reporter_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
require "rails/test_unit/reporter"
require "minitest/mock"
@@ -161,7 +163,7 @@ class TestUnitReporterTest < ActiveSupport::TestCase
end
def failed_test
- ft = ExampleTest.new(:woot)
+ ft = Minitest::Result.from(ExampleTest.new(:woot))
ft.failures << begin
raise Minitest::Assertion, "boo"
rescue Minitest::Assertion => e
@@ -174,17 +176,17 @@ class TestUnitReporterTest < ActiveSupport::TestCase
error = ArgumentError.new("wups")
error.set_backtrace([ "some_test.rb:4" ])
- et = ExampleTest.new(:woot)
+ et = Minitest::Result.from(ExampleTest.new(:woot))
et.failures << Minitest::UnexpectedError.new(error)
et
end
def passing_test
- ExampleTest.new(:woot)
+ Minitest::Result.from(ExampleTest.new(:woot))
end
def skipped_test
- st = ExampleTest.new(:woot)
+ st = Minitest::Result.from(ExampleTest.new(:woot))
st.failures << begin
raise Minitest::Skip, "skipchurches, misstemples"
rescue Minitest::Assertion => e
diff --git a/railties/test/version_test.rb b/railties/test/version_test.rb
index 86a482e091..17a024fe7f 100644
--- a/railties/test/version_test.rb
+++ b/railties/test/version_test.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "abstract_unit"
class VersionTest < ActiveSupport::TestCase