diff options
Diffstat (limited to 'railties')
76 files changed, 1425 insertions, 478 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index faf6846e4b..15cf087ddf 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,145 @@ +* Add `bin/test` script to rails plugin. + + `bin/test` can use the same API as `bin/rails test`. + + *Yuji Yaginuma* + +* Make `static_index` part of the `config.public_file_server` config and + call it `public_file_server.index_name`. + + *Yuki Nishijima* + +* Generated `Gemfile`s for new applications include a new dependency on + [listen](https://github.com/guard/listen) commented out. + + *Puneet Agarwal* and *Xavier Noria* + +* Deprecate `serve_static_files` in favor of `public_file_server.enabled`. + + Unifies the static asset options under `public_file_server`. + + To upgrade, replace occurrences of: + + ``` + config.serve_static_files = # false or true + ``` + + in your environment files, with: + + ``` + config.public_file_server.enabled = # false or true + ``` + + *Kasper Timm Hansen* + +* Deprecate `config.static_cache_control` in favor of + `config.public_file_server.headers`. + + To upgrade, replace occurrences of: + + ``` + config.static_cache_control = 'public, max-age=60' + ``` + + in your environment files, with: + + ``` + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=60' + } + ``` + + `config.public_file_server.headers` can set arbitrary headers, sent along when + a response is delivered. + + *Yuki Nishijima* + +* Route generator should be idempotent + running generators several times no longer require you to cleanup routes.rb + + *Thiago Pinto* + +* Allow passing an environment to `config_for`. + + *Simon Eskildsen* + +* Allow rake:stats to account for rake tasks in lib/tasks + + *Kevin Deisz* + +* Added javascript to update the URL on mailer previews with the currently + selected email format. Reloading the page now keeps you on your selected + format rather than going back to the default html version. + + *James Kerr* + +* Add fail fast to `bin/rails test` + + Adding `--fail-fast` or `-f` when running tests will interrupt the run on + the first failure: + + ``` + # Running: + + ................................................S......E + + ArgumentError: Wups! Bet you didn't expect this! + test/models/bunny_test.rb:19:in `block in <class:BunnyTest>' + + bin/rails test test/models/bunny_test.rb:18 + + ....................................F + + This failed + + bin/rails test test/models/bunny_test.rb:14 + + Interrupted. Exiting... + + + Finished in 0.051427s, 1808.3872 runs/s, 1769.4972 assertions/s. + + ``` + + Note that any unexpected errors don't abort the run. + + *Kasper Timm Hansen* + +* Add inline output to `bin/rails test` + + Any failures or errors (and skips if running in verbose mode) are output + during a test run: + + ``` + # Running: + + .....S..........................................F + + This failed + + bin/rails test test/models/bunny_test.rb:14 + + .................................E + + ArgumentError: Wups! Bet you didn't expect this! + test/models/bunny_test.rb:19:in `block in <class:BunnyTest>' + + bin/rails test test/models/bunny_test.rb:18 + + .................... + + Finished in 0.069708s, 1477.6019 runs/s, 1448.9106 assertions/s. + ``` + + Output can be deferred to after a run with the `--defer-output` option. + + *Kasper Timm Hansen* + +* Fix displaying mailer previews on non local requests when config + `action_mailer.show_previews` is set + + *Wojciech Wnętrzak* + * `rails server` will now honour the `PORT` environment variable *David Cornu* @@ -229,10 +371,11 @@ Newly generated Rails apps have a new initializer called `callback_terminator.rb` which sets the value of the configuration option - `config.active_support.halt_callback_chains_on_return_false` to `false`. + `ActiveSupport.halt_callback_chains_on_return_false` to `false`. - As a result, new Rails apps do not halt callback chains when a callback - returns `false`; only when they are explicitly halted with `throw(:abort)`. + As a result, new Rails apps do not halt Active Record and Active Model + callback chains when a callback returns `false`; only when they are + explicitly halted with `throw(:abort)`. The terminator is *not* added when running `rake rails:update`, so returning `false` will still work on old apps ported to Rails 5, displaying a diff --git a/railties/Rakefile b/railties/Rakefile index cf130a5f14..73d881b318 100644 --- a/railties/Rakefile +++ b/railties/Rakefile @@ -5,20 +5,33 @@ task :default => :test desc "Run all unit tests" task :test => 'test:isolated' +dash_i = [ + 'test', + 'lib', + "#{File.dirname(__FILE__)}/../activesupport/lib", + "#{File.dirname(__FILE__)}/../actionpack/lib", + "#{File.dirname(__FILE__)}/../activemodel/lib" +] + +dash_i.reverse_each do |x| + $:.unshift x unless $:.include? x +end +$-w = true + +require 'bundler/setup' unless defined?(Bundler) +require 'active_support' + namespace :test do task :isolated do dirs = (ENV["TEST_DIR"] || ENV["TEST_DIRS"] || "**").split(",") test_files = dirs.map { |dir| "test/#{dir}/*_test.rb" } Dir[*test_files].each do |file| next true if file.include?("fixtures") - dash_i = [ - 'test', - 'lib', - "#{File.dirname(__FILE__)}/../activesupport/lib", - "#{File.dirname(__FILE__)}/../actionpack/lib", - "#{File.dirname(__FILE__)}/../activemodel/lib" - ] - ruby "-w", "-I#{dash_i.join ':'}", file + puts "#{FileUtils::RUBY} -w -I#{dash_i.join ':'} #{file}" + + # We could run these in parallel, but pretty much all of the + # railties tests already run in parallel, so ¯\_(⊙︿⊙)_/¯ + Process.waitpid fork { ARGV.clear; load file } end end end diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 8075068b3f..77efe3248d 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -156,26 +156,20 @@ module Rails self end - # Implements call according to the Rack API. It simply - # dispatches the request to the underlying middleware stack. - def call(env) - req = ActionDispatch::Request.new env - env["ORIGINAL_FULLPATH"] = req.fullpath - env["ORIGINAL_SCRIPT_NAME"] = req.script_name - super(env) - end - # Reload application routes regardless if they changed or not. def reload_routes! routes_reloader.reload! end - # Return the application's KeyGenerator + # Returns the application's KeyGenerator def key_generator # number of iterations selected based on consultation with the google security # team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220 @caching_key_generator ||= if secrets.secret_key_base + unless secrets.secret_key_base.kind_of?(String) + raise ArgumentError, "`secret_key_base` for #{Rails.env} environment must be a type of String, change this value in `config/secrets.yml`" + end key_generator = ActiveSupport::KeyGenerator.new(secrets.secret_key_base, iterations: 1000) ActiveSupport::CachingKeyGenerator.new(key_generator) else @@ -224,12 +218,12 @@ module Rails # Rails.application.configure do # config.middleware.use ExceptionNotifier, config_for(:exception_notification) # end - def config_for(name) + def config_for(name, env: Rails.env) yaml = Pathname.new("#{paths["config"].existent.first}/#{name}.yml") if yaml.exist? require "erb" - (YAML.load(ERB.new(yaml.read).result) || {})[Rails.env] || {} + (YAML.load(ERB.new(yaml.read).result) || {})[env] || {} else raise "Could not load configuration. No such file - #{yaml}" end @@ -514,5 +508,18 @@ module Rails end end end + + private + + def build_request(env) + req = super + env["ORIGINAL_FULLPATH"] = req.fullpath + env["ORIGINAL_SCRIPT_NAME"] = req.script_name + req + end + + def build_middleware + config.app_middleware + super + end end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 4fc7a1db62..80733c2d90 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -3,6 +3,9 @@ require 'active_support/file_update_checker' require 'rails/engine/configuration' require 'rails/source_annotation_extractor' +require 'active_support/deprecation' +require 'active_support/core_ext/string/strip' # for strip_heredoc + module Rails class Application class Configuration < ::Rails::Engine::Configuration @@ -11,12 +14,12 @@ module Rails :eager_load, :exceptions_app, :file_watcher, :filter_parameters, :force_ssl, :helpers_paths, :logger, :log_formatter, :log_tags, :railties_order, :relative_url_root, :secret_key_base, :secret_token, - :serve_static_files, :ssl_options, :static_cache_control, :static_index, + :ssl_options, :public_file_server, :session_options, :time_zone, :reload_classes_only_on_change, :beginning_of_week, :filter_redirect, :x attr_writer :log_level - attr_reader :encoding, :api_only + attr_reader :encoding, :api_only, :static_cache_control def initialize(*) super @@ -26,9 +29,9 @@ module Rails @filter_parameters = [] @filter_redirect = [] @helpers_paths = [] - @serve_static_files = true - @static_cache_control = nil - @static_index = "index" + @public_file_server = ActiveSupport::OrderedOptions.new + @public_file_server.enabled = true + @public_file_server.index_name = "index" @force_ssl = false @ssl_options = {} @session_store = :cookie_store @@ -36,13 +39,12 @@ module Rails @time_zone = "UTC" @beginning_of_week = :monday @log_level = nil - @middleware = app_middleware @generators = app_generators @cache_store = [ :file_store, "#{root}/tmp/cache/" ] @railties_order = [:all] @relative_url_root = ENV["RAILS_RELATIVE_URL_ROOT"] @reload_classes_only_on_change = true - @file_watcher = ActiveSupport::FileUpdateChecker + @file_watcher = file_update_checker @exceptions_app = nil @autoflush_log = true @log_formatter = ActiveSupport::Logger::SimpleFormatter.new @@ -53,6 +55,35 @@ module Rails @x = Custom.new end + def static_cache_control=(value) + ActiveSupport::Deprecation.warn <<-eow.strip_heredoc + `static_cache_control` is deprecated and will be removed in Rails 5.1. + Please use + `config.public_file_server.headers = { 'Cache-Control' => '#{value}' }` + instead. + eow + + @static_cache_control = value + end + + def serve_static_files + ActiveSupport::Deprecation.warn <<-eow.strip_heredoc + `serve_static_files` is deprecated and will be removed in Rails 5.1. + Please use `public_file_server.enabled` instead. + eow + + @public_file_server.enabled + end + + def serve_static_files=(value) + ActiveSupport::Deprecation.warn <<-eow.strip_heredoc + `serve_static_files` is deprecated and will be removed in Rails 5.1. + Please use `public_file_server.enabled = #{value}` instead. + eow + + @public_file_server.enabled = value + end + def encoding=(value) @encoding = value silence_warnings do @@ -150,6 +181,14 @@ module Rails end private + def file_update_checker + if defined?(Listen) && Listen::Adapter.select() != Listen::Adapter::Polling + ActiveSupport::FileEventedUpdateChecker + else + ActiveSupport::FileUpdateChecker + end + end + class Custom #:nodoc: def initialize @configurations = Hash.new diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb index 88eade5c5a..5cb5bfb8b7 100644 --- a/railties/lib/rails/application/default_middleware_stack.rb +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -17,8 +17,11 @@ module Rails middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header - if config.serve_static_files - middleware.use ::ActionDispatch::Static, paths["public"].first, config.static_cache_control, index: config.static_index + if config.public_file_server.enabled + headers = config.public_file_server.headers || {} + headers['Cache-Control'.freeze] = config.static_cache_control if config.static_cache_control + + middleware.use ::ActionDispatch::Static, paths["public"].first, index: config.public_file_server.index_name, headers: headers end if rack_cache = load_rack_cache @@ -72,7 +75,6 @@ module Rails middleware.use ::ActionDispatch::Flash end - middleware.use ::ActionDispatch::ParamsParser middleware.use ::Rack::Head middleware.use ::Rack::ConditionalGet middleware.use ::Rack::ETag, "no-cache" diff --git a/railties/lib/rails/code_statistics.rb b/railties/lib/rails/code_statistics.rb index fd352dc9b7..8e9097e1ef 100644 --- a/railties/lib/rails/code_statistics.rb +++ b/railties/lib/rails/code_statistics.rb @@ -33,7 +33,7 @@ class CodeStatistics #:nodoc: Hash[@pairs.map{|pair| [pair.first, calculate_directory_statistics(pair.last)]}] end - def calculate_directory_statistics(directory, pattern = /.*\.(rb|js|coffee)$/) + def calculate_directory_statistics(directory, pattern = /.*\.(rb|js|coffee|rake)$/) stats = CodeStatisticsCalculator.new Dir.foreach(directory) do |file_name| diff --git a/railties/lib/rails/code_statistics_calculator.rb b/railties/lib/rails/code_statistics_calculator.rb index a142236dbe..fad13e8517 100644 --- a/railties/lib/rails/code_statistics_calculator.rb +++ b/railties/lib/rails/code_statistics_calculator.rb @@ -25,6 +25,7 @@ class CodeStatisticsCalculator #:nodoc: } PATTERNS[:minitest] = PATTERNS[:rb].merge method: /^\s*(def|test)\s+['"_a-z]/ + PATTERNS[:rake] = PATTERNS[:rb] def initialize(lines = 0, code_lines = 0, classes = 0, methods = 0) @lines = lines diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index d99d27a756..30eafd59f2 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -33,9 +33,9 @@ module Rails # config.middleware.delete ActionDispatch::Flash # class MiddlewareStackProxy - def initialize - @operations = [] - @delete_operations = [] + def initialize(operations = [], delete_operations = []) + @operations = operations + @delete_operations = delete_operations end def insert_before(*args, &block) @@ -71,6 +71,19 @@ module Rails other end + + def +(other) # :nodoc: + MiddlewareStackProxy.new(@operations + other.operations, @delete_operations + other.delete_operations) + end + + protected + def operations + @operations + end + + def delete_operations + @delete_operations + end end class Generators #:nodoc: diff --git a/railties/lib/rails/console/helpers.rb b/railties/lib/rails/console/helpers.rb index b775f1ff8d..a33f71dc5b 100644 --- a/railties/lib/rails/console/helpers.rb +++ b/railties/lib/rails/console/helpers.rb @@ -4,7 +4,7 @@ module Rails # # This method assumes an +ApplicationController+ exists, and it extends +ActionController::Base+ def helper - @helper ||= ApplicationController.helpers + ApplicationController.helpers end # Gets a new instance of a controller object. diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index e90d41cbec..5757d235d2 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -2,6 +2,7 @@ require 'rails/railtie' require 'rails/engine/railties' require 'active_support/core_ext/module/delegation' require 'pathname' +require 'thread' module Rails # <tt>Rails::Engine</tt> allows you to wrap a specific Rails application or subset of @@ -357,12 +358,7 @@ module Rails Rails::Railtie::Configuration.eager_load_namespaces << base base.called_from = begin - call_stack = if Kernel.respond_to?(:caller_locations) - caller_locations.map { |l| l.absolute_path || l.path } - else - # Remove the line number from backtraces making sure we don't leave anything behind - caller.map { |p| p.sub(/:\d+.*/, '') } - end + call_stack = caller_locations.map { |l| l.absolute_path || l.path } File.dirname(call_stack.detect { |p| p !~ %r[railties[\w.-]*/lib/rails|rack[\w.-]*/lib/rack] }) end @@ -434,6 +430,7 @@ module Rails @env_config = nil @helpers = nil @routes = nil + @app_build_lock = Mutex.new super end @@ -504,10 +501,13 @@ module Rails # Returns the underlying rack application for this engine. def app - @app ||= begin - config.middleware = config.middleware.merge_into(default_middleware_stack) - config.middleware.build(endpoint) - end + @app || @app_build_lock.synchronize { + @app ||= begin + stack = default_middleware_stack + config.middleware = build_middleware.merge_into(stack) + config.middleware.build(endpoint) + end + } end # Returns the endpoint for this engine. If none is registered, @@ -518,11 +518,8 @@ module Rails # Define the Rack API for this engine. def call(env) - env.merge!(env_config) - req = ActionDispatch::Request.new env - req.routes = routes - req.engine_script_name = req.script_name - app.call(env) + req = build_request env + app.call req.env end # Defines additional Rack env configuration that is added on each call. @@ -689,5 +686,19 @@ module Rails def _all_load_paths #:nodoc: @_all_load_paths ||= (config.paths.load_paths + _all_autoload_paths).uniq end + + private + + def build_request(env) + env.merge!(env_config) + req = ActionDispatch::Request.new env + req.routes = routes + req.engine_script_name = req.script_name + req + end + + def build_middleware + config.middleware + end end end diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 62a4139d07..8cadbc3ddd 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -4,17 +4,14 @@ module Rails class Engine class Configuration < ::Rails::Railtie::Configuration attr_reader :root - attr_writer :middleware, :eager_load_paths, :autoload_once_paths, :autoload_paths + attr_accessor :middleware + attr_writer :eager_load_paths, :autoload_once_paths, :autoload_paths def initialize(root=nil) super() @root = root @generators = app_generators.dup - end - - # Returns the middleware stack for the engine. - def middleware - @middleware ||= Rails::Configuration::MiddlewareStackProxy.new + @middleware = Rails::Configuration::MiddlewareStackProxy.new end # Holds generators configuration: @@ -29,7 +26,7 @@ module Rails # # config.generators.colorize_logging = false # - def generators #:nodoc: + def generators @generators ||= Rails::Configuration::Generators.new yield(@generators) if block_given? @generators diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index 2645102619..e3d79521e7 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -208,6 +208,7 @@ module Rails "#{test}:model", "#{test}:scaffold", "#{test}:view", + "#{test}:job", "#{template}:controller", "#{template}:scaffold", "#{template}:mailer", diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb index b4356f71e0..5bbd2f1aed 100644 --- a/railties/lib/rails/generators/actions.rb +++ b/railties/lib/rails/generators/actions.rb @@ -235,7 +235,7 @@ module Rails sentinel = /\.routes\.draw do\s*\n/m in_root do - inject_into_file 'config/routes.rb', " #{routing_code}\n", { after: sentinel, verbose: false, force: true } + inject_into_file 'config/routes.rb', " #{routing_code}\n", { after: sentinel, verbose: false, force: false } end end diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 38074e80e0..56c9d3e354 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -162,7 +162,8 @@ module Rails def database_gemfile_entry return [] if options[:skip_active_record] - GemfileEntry.version gem_for_database, nil, + gem_name, gem_version = gem_for_database + GemfileEntry.version gem_name, gem_version, "Use #{options[:database]} as the database for Active Record" end @@ -202,27 +203,34 @@ module Rails def self.path(name, path, comment = nil) new(name, nil, comment, path: path) end + + def version + version = super + + if version.is_a?(Array) + version.join("', '") + else + version + end + end end def rails_gemfile_entry - if options.dev? - [ - GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH), + dev_edge_common = [ GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails'), GemfileEntry.github('sprockets', 'rails/sprockets'), GemfileEntry.github('sass-rails', 'rails/sass-rails'), GemfileEntry.github('arel', 'rails/arel'), GemfileEntry.github('rack', 'rack/rack') ] + if options.dev? + [ + GemfileEntry.path('rails', Rails::Generators::RAILS_DEV_PATH) + ] + dev_edge_common elsif options.edge? [ - GemfileEntry.github('rails', 'rails/rails'), - GemfileEntry.github('sprockets-rails', 'rails/sprockets-rails'), - GemfileEntry.github('sprockets', 'rails/sprockets'), - GemfileEntry.github('sass-rails', 'rails/sass-rails'), - GemfileEntry.github('arel', 'rails/arel'), - GemfileEntry.github('rack', 'rack/rack') - ] + GemfileEntry.github('rails', 'rails/rails') + ] + dev_edge_common else [GemfileEntry.version('rails', Rails::VERSION::STRING, @@ -233,16 +241,16 @@ module Rails def gem_for_database # %w( mysql oracle postgresql sqlite3 frontbase ibm_db sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql ) case options[:database] - when "oracle" then "ruby-oci8" - when "postgresql" then "pg" - when "frontbase" then "ruby-frontbase" - when "mysql" then "mysql2" - when "sqlserver" then "activerecord-sqlserver-adapter" - when "jdbcmysql" then "activerecord-jdbcmysql-adapter" - when "jdbcsqlite3" then "activerecord-jdbcsqlite3-adapter" - when "jdbcpostgresql" then "activerecord-jdbcpostgresql-adapter" - when "jdbc" then "activerecord-jdbc-adapter" - else options[:database] + when "oracle" then ["ruby-oci8", nil] + when "postgresql" then ["pg", ["~> 0.18"]] + when "frontbase" then ["ruby-frontbase", nil] + when "mysql" then ["mysql2", [">= 0.3.18", "< 0.5"]] + when "sqlserver" then ["activerecord-sqlserver-adapter", nil] + when "jdbcmysql" then ["activerecord-jdbcmysql-adapter", nil] + when "jdbcsqlite3" then ["activerecord-jdbcsqlite3-adapter", nil] + when "jdbcpostgresql" then ["activerecord-jdbcpostgresql-adapter", nil] + when "jdbc" then ["activerecord-jdbc-adapter", nil] + else [options[:database], nil] end end diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb index 6fa413f8b0..c72ec400a0 100644 --- a/railties/lib/rails/generators/base.rb +++ b/railties/lib/rails/generators/base.rb @@ -302,13 +302,13 @@ module Rails default_for_option(Rails::Generators.options, name, options, options[:default]) end - # Return default aliases for the option name given doing a lookup in + # Returns default aliases for the option name given doing a lookup in # Rails::Generators.aliases. def self.default_aliases_for_option(name, options) default_for_option(Rails::Generators.aliases, name, options, options[:aliases]) end - # Return default for the option name given doing a lookup in config. + # Returns default for the option name given doing a lookup in config. def self.default_for_option(config, name, options, default) if generator_name and c = config[generator_name.to_sym] and c.key?(name) c[name] diff --git a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb index d99b27cb2d..519b6c8603 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb @@ -14,15 +14,15 @@ <% attributes.each do |attribute| -%> <div class="field"> <% if attribute.password_digest? -%> - <%%= f.label :password %><br> + <%%= f.label :password %> <%%= f.password_field :password %> </div> <div class="field"> - <%%= f.label :password_confirmation %><br> + <%%= f.label :password_confirmation %> <%%= f.password_field :password_confirmation %> <% else -%> - <%%= f.label :<%= attribute.column_name %> %><br> + <%%= f.label :<%= attribute.column_name %> %> <%%= f.<%= attribute.field_type %> :<%= attribute.column_name %> %> <% end -%> </div> diff --git a/railties/lib/rails/generators/migration.rb b/railties/lib/rails/generators/migration.rb index 51e6d68bf0..87f2e1d42b 100644 --- a/railties/lib/rails/generators/migration.rb +++ b/railties/lib/rails/generators/migration.rb @@ -10,22 +10,22 @@ module Rails extend ActiveSupport::Concern attr_reader :migration_number, :migration_file_name, :migration_class_name - module ClassMethods - def migration_lookup_at(dirname) #:nodoc: + module ClassMethods #:nodoc: + def migration_lookup_at(dirname) Dir.glob("#{dirname}/[0-9]*_*.rb") end - def migration_exists?(dirname, file_name) #:nodoc: + def migration_exists?(dirname, file_name) migration_lookup_at(dirname).grep(/\d+_#{file_name}.rb$/).first end - def current_migration_number(dirname) #:nodoc: + def current_migration_number(dirname) migration_lookup_at(dirname).collect do |file| File.basename(file).split("_").first.to_i end.max.to_i end - def next_migration_number(dirname) #:nodoc: + def next_migration_number(dirname) raise NotImplementedError end end diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 6a1c2faaab..a0880d5166 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -48,10 +48,12 @@ group :development do # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' <% end -%> + + # Loading the listen gem enables an evented file system monitor. Check + # https://github.com/guard/listen#listen-adapters if on Windows or *BSD. + # gem 'listen', '~> 3.0.5' end <% end -%> -<% if RUBY_PLATFORM.match(/bccwin|cygwin|emx|mingw|mswin|wince|java/) -%> # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] -<% end -%> diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt new file mode 100644 index 0000000000..f80631bac6 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt @@ -0,0 +1,8 @@ + +<% unless options.api? -%> +//= link_tree ../images +<% end -%> +<% unless options.skip_javascript -%> +//= link_directory ../javascripts .js +<% end -%> +//= link_directory ../stylesheets .css diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/manifest.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/manifest.js.tt deleted file mode 100644 index 3325553f57..0000000000 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/manifest.js.tt +++ /dev/null @@ -1,8 +0,0 @@ - -<% unless options.api? -%> -//= link_tree ./images -<% end -%> -<% unless options.skip_javascript -%> -//= link ./javascripts/application.js -<% end -%> -//= link ./stylesheets/application.css diff --git a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt index 75ea52828e..8bb4440f55 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt @@ -1,23 +1,24 @@ <!DOCTYPE html> <html> -<head> - <title><%= camelized %></title> - <%- if options[:skip_javascript] -%> - <%%= stylesheet_link_tag 'application', media: 'all' %> - <%- else -%> - <%- if gemfile_entries.any? { |m| m.name == 'turbolinks' } -%> - <%%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> - <%%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> + <head> + <title><%= camelized %></title> + <%- if options[:skip_javascript] -%> + <%%= stylesheet_link_tag 'application', media: 'all' %> <%- else -%> - <%%= stylesheet_link_tag 'application', media: 'all' %> - <%%= javascript_include_tag 'application' %> + <%- if gemfile_entries.any? { |m| m.name == 'turbolinks' } -%> + <%%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> + <%%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> + <%- else -%> + <%%= stylesheet_link_tag 'application', media: 'all' %> + <%%= javascript_include_tag 'application' %> + <%- end -%> <%- end -%> - <%- end -%> - <%%= csrf_meta_tags %> -</head> -<body> + <%%= csrf_meta_tags %> + </head> -<%%= yield %> + <body> -</body> + <%%= yield %> + + </body> </html> diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb index 6b7d7abd0b..ddd0fcade1 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/application.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb @@ -26,7 +26,7 @@ module <%= app_const_base %> # -- all .rb files in that directory are automatically loaded. # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. + # Run "rake time:zones:all" for a time zone names list. Default is UTC. # config.time_zone = 'Central Time (US & Canada)' # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml index f5b62e8fb3..5ca549a8c8 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml @@ -7,7 +7,7 @@ # gem 'activerecord-jdbcmysql-adapter' # # And be sure to use new-style password hashing: -# http://dev.mysql.com/doc/refman/5.6/en/old-client.html +# http://dev.mysql.com/doc/refman/5.7/en/old-client.html # default: &default adapter: mysql diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml index b0767bd93a..119c2fe2c3 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml @@ -7,7 +7,7 @@ # gem 'mysql2' # # And be sure to use new-style password hashing: -# http://dev.mysql.com/doc/refman/5.6/en/old-client.html +# http://dev.mysql.com/doc/refman/5.7/en/old-client.html # default: &default adapter: mysql2 diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt index e29f0bacaa..4dd20a9d2e 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt @@ -15,8 +15,10 @@ Rails.application.configure do # Enable/disable caching. By default caching is disabled. if Rails.root.join('tmp/caching-dev.txt').exist? config.action_controller.perform_caching = true - config.static_cache_control = "public, max-age=172800" config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=172800' + } else config.action_controller.perform_caching = false config.cache_store = :null_store diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt index 0297ab75f6..a5302550fa 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt @@ -16,7 +16,7 @@ Rails.application.configure do # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. - config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? <%- unless options.skip_sprockets? -%> # Compress JavaScripts and CSS. diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt index 0306deb18c..8133917591 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt @@ -12,9 +12,11 @@ Rails.application.configure do # preloads Rails for running tests, you may have to set it to true. config.eager_load = false - # Configure static file server for tests with Cache-Control for performance. - config.serve_static_files = true - config.static_cache_control = 'public, max-age=3600' + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => 'public, max-age=3600' + } # Show full error reports and disable caching. config.consider_all_requests_local = true diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb index 45c44d24f8..3b1c1b5ed1 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/cors.rb @@ -1,9 +1,11 @@ -# Avoid CORS issues when API is called from the frontend app -# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests +# Be sure to restart your server when you modify this file. + +# Avoid CORS issues when API is called from the frontend app. +# Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. # Read more: https://github.com/cyu/rack-cors -# Rails.application.config.middleware.insert_before 0, "Rack::Cors" do +# Rails.application.config.middleware.insert_before 0, Rack::Cors do # allow do # origins 'example.com' # diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/request_forgery_protection.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/request_forgery_protection.rb new file mode 100644 index 0000000000..3eab78a885 --- /dev/null +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/request_forgery_protection.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Enable origin-checking CSRF mitigation. +Rails.application.config.action_controller.forgery_protection_origin_check = true diff --git a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb index 8fea30189e..776019a6a0 100644 --- a/railties/lib/rails/generators/rails/plugin/plugin_generator.rb +++ b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb @@ -106,7 +106,7 @@ task default: :test def test_dummy_assets template "rails/javascripts.js", "#{dummy_path}/app/assets/javascripts/application.js", force: true template "rails/stylesheets.css", "#{dummy_path}/app/assets/stylesheets/application.css", force: true - template "rails/dummy_manifest.js", "#{dummy_path}/app/assets/manifest.js", force: true + template "rails/dummy_manifest.js", "#{dummy_path}/app/assets/config/manifest.js", force: true end def test_dummy_clean @@ -117,14 +117,14 @@ task default: :test remove_file "Gemfile" remove_file "lib/tasks" remove_file "public/robots.txt" - remove_file "README" + remove_file "README.md" remove_file "test" remove_file "vendor" end end def assets_manifest - template "rails/engine_manifest.js", "app/assets/#{underscored_name}_manifest.js" + template "rails/engine_manifest.js", "app/assets/config/#{underscored_name}_manifest.js" end def stylesheets @@ -148,9 +148,8 @@ task default: :test end def bin(force = false) - return unless engine? - - directory "bin", force: force do |content| + bin_file = engine? ? 'bin/rails.tt' : 'bin/test.tt' + template bin_file, force: force do |content| "#{shebang}\n" + content end chmod "bin", 0755, verbose: false @@ -226,7 +225,7 @@ task default: :test end def create_assets_manifest_file - build(:assets_manifest) unless api? + build(:assets_manifest) if !api? && engine? end def create_public_stylesheets_files @@ -237,10 +236,6 @@ task default: :test build(:javascripts) unless api? end - def create_images_directory - build(:images) unless api? - end - def create_bin_files build(:bin) end diff --git a/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec index f8ece4fe73..3f5682b0c1 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec +++ b/railties/lib/rails/generators/rails/plugin/templates/%name%.gemspec @@ -15,13 +15,10 @@ Gem::Specification.new do |s| s.license = "MIT" s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] -<% unless options.skip_test? -%> - s.test_files = Dir["test/**/*"] -<% end -%> <%= '# ' if options.dev? || options.edge? -%>s.add_dependency "rails", "~> <%= Rails::VERSION::STRING %>" <% unless options[:skip_active_record] -%> - s.add_development_dependency "<%= gem_for_database %>" + s.add_development_dependency "<%= gem_for_database[0] %>" <% end -%> end diff --git a/railties/lib/rails/generators/rails/plugin/templates/Gemfile b/railties/lib/rails/generators/rails/plugin/templates/Gemfile index 2c91c6a0ea..f085a2577a 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin/templates/Gemfile @@ -11,7 +11,7 @@ gemspec <% if options[:skip_gemspec] -%> group :development do - gem '<%= gem_for_database %>' + gem '<%= gem_for_database[0] %>' end <% else -%> # Declare any dependencies that are still in development here instead of in diff --git a/railties/lib/rails/generators/rails/plugin/templates/app/jobs/%namespaced_name%/application_job.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/app/jobs/%namespaced_name%/application_job.rb.tt new file mode 100644 index 0000000000..bad1ff2d16 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin/templates/app/jobs/%namespaced_name%/application_job.rb.tt @@ -0,0 +1,5 @@ +<%= wrap_in_modules <<-rb.strip_heredoc + class ApplicationJob < ActiveJob::Base + end +rb +%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/bin/test.tt b/railties/lib/rails/generators/rails/plugin/templates/bin/test.tt new file mode 100644 index 0000000000..62b94618fd --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin/templates/bin/test.tt @@ -0,0 +1,8 @@ +$: << File.expand_path(File.expand_path('../../test', __FILE__)) + +require 'bundler/setup' +require 'rails/test_unit/minitest_plugin' + +Rails::TestUnitReporter.executable = 'bin/test' + +exit Minitest.run(ARGV) diff --git a/railties/lib/rails/generators/rails/plugin/templates/gitignore b/railties/lib/rails/generators/rails/plugin/templates/gitignore index d524fcbc4e..54c78d7927 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/gitignore +++ b/railties/lib/rails/generators/rails/plugin/templates/gitignore @@ -6,5 +6,4 @@ pkg/ <%= dummy_path %>/db/*.sqlite3-journal <%= dummy_path %>/log/*.log <%= dummy_path %>/tmp/ -<%= dummy_path %>/.sass-cache <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js b/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js index ace695a811..8d21b2b6fb 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js @@ -1,11 +1,11 @@ <% unless api? -%> -//= link_tree ./images +//= link_tree ../images <% end -%> <% unless options.skip_javascript -%> -//= link ./javascripts/application.js +//= link_directory ../javascripts .js <% end -%> -//= link ./stylesheets/application.css +//= link_directory ../stylesheets .css <% if mountable? && !api? -%> //= link <%= underscored_name %>_manifest.js <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js b/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js index f8ef26982a..2f23844f5e 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js @@ -1,6 +1,6 @@ <% if mountable? -%> -<% unless options.skip_javascript -%> -//= link ./javascripts/<%= namespaced_name %>/application.js +<% if !options.skip_javascript -%> +//= link_directory ../javascripts/<%= namespaced_name %> .js <% end -%> -//= link ./stylesheets/<%= namespaced_name %>/application.css +//= link_directory ../stylesheets/<%= namespaced_name %> .css <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb index 673de44108..694510edc0 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/routes.rb @@ -1,4 +1,3 @@ Rails.application.routes.draw do - mount <%= camelized_modules %>::Engine => "/<%= name %>" end diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb index f315144723..a0b00fc5c5 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb @@ -14,6 +14,10 @@ require "rails/test_help" # to be shown. Minitest.backtrace_filter = Minitest::BacktraceFilter.new +<% unless engine? -%> +Rails::TestUnitReporter.executable = 'bin/test' +<% end -%> + # Load fixtures from the engine if ActiveSupport::TestCase.respond_to?(:fixture_path=) ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__) diff --git a/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css b/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css index b7818883d1..79f8b7f96f 100644 --- a/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css +++ b/railties/lib/rails/generators/rails/scaffold/templates/scaffold.css @@ -78,3 +78,7 @@ div.actions { font-size: 12px; list-style: square; } + +label { + display: block; +} diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb index bc3c9b3f6b..17a86f376b 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb @@ -1,5 +1,5 @@ <% if namespaced? -%> -require_dependency "<%= namespaced_file_path %>/application_controller" +require_dependency "<%= namespaced_path %>/application_controller" <% end -%> <% module_namespacing do -%> diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index 2c3b04043f..f73e9a96ba 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -1,5 +1,5 @@ <% if namespaced? -%> -require_dependency "<%= namespaced_file_path %>/application_controller" +require_dependency "<%= namespaced_path %>/application_controller" <% end -%> <% module_namespacing do -%> diff --git a/railties/lib/rails/generators/testing/assertions.rb b/railties/lib/rails/generators/testing/assertions.rb index 17af6eddfa..76758df86d 100644 --- a/railties/lib/rails/generators/testing/assertions.rb +++ b/railties/lib/rails/generators/testing/assertions.rb @@ -1,5 +1,3 @@ -require 'shellwords' - module Rails module Generators module Testing diff --git a/railties/lib/rails/generators/testing/behaviour.rb b/railties/lib/rails/generators/testing/behaviour.rb index c9700e1cd7..94b5e52224 100644 --- a/railties/lib/rails/generators/testing/behaviour.rb +++ b/railties/lib/rails/generators/testing/behaviour.rb @@ -92,7 +92,8 @@ module Rails cd current_path end - def prepare_destination # :nodoc: + # Clears all files and directories in destination. + def prepare_destination rm_rf(destination_root) mkdir_p(destination_root) end diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb index 78a857e0f1..6143cf2dd9 100644 --- a/railties/lib/rails/mailers_controller.rb +++ b/railties/lib/rails/mailers_controller.rb @@ -3,7 +3,7 @@ require 'rails/application_controller' class Rails::MailersController < Rails::ApplicationController # :nodoc: prepend_view_path ActionDispatch::DebugExceptions::RESCUES_TEMPLATE_PATH - before_action :require_local! + before_action :require_local!, unless: :show_previews? before_action :find_preview, only: :preview def index @@ -31,7 +31,7 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc: raise AbstractController::ActionNotFound, "Email part '#{part_type}' not found in #{@preview.name}##{@email_action}" end else - @part = find_preferred_part(request.format, Mime::HTML, Mime::TEXT) + @part = find_preferred_part(request.format, Mime[:html], Mime[:text]) render action: 'email', layout: false, formats: %w[html] end else @@ -41,6 +41,10 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc: end protected + def show_previews? + ActionMailer::Base.show_previews + end + def find_preview candidates = [] params[:path].to_s.scan(%r{/|$}){ candidates << $` } diff --git a/railties/lib/rails/tasks/dev.rake b/railties/lib/rails/tasks/dev.rake index e949172d3f..4593100465 100644 --- a/railties/lib/rails/tasks/dev.rake +++ b/railties/lib/rails/tasks/dev.rake @@ -1,7 +1,6 @@ namespace :dev do + desc 'Toggle development mode caching on/off' task :cache do - desc 'Toggle development mode caching on/off' - if File.exist? 'tmp/caching-dev.txt' File.delete 'tmp/caching-dev.txt' puts 'Development mode is no longer being cached.' diff --git a/railties/lib/rails/tasks/statistics.rake b/railties/lib/rails/tasks/statistics.rake index 735c36eb3a..a919d36939 100644 --- a/railties/lib/rails/tasks/statistics.rake +++ b/railties/lib/rails/tasks/statistics.rake @@ -9,6 +9,7 @@ STATS_DIRECTORIES = [ %w(Mailers app/mailers), %w(Javascripts app/assets/javascripts), %w(Libraries lib/), + %w(Tasks lib/tasks), %w(APIs app/apis), %w(Controller\ tests test/controllers), %w(Helper\ tests test/helpers), diff --git a/railties/lib/rails/templates/rails/mailers/email.html.erb b/railties/lib/rails/templates/rails/mailers/email.html.erb index bb6e49966d..fed96fbc85 100644 --- a/railties/lib/rails/templates/rails/mailers/email.html.erb +++ b/railties/lib/rails/templates/rails/mailers/email.html.erb @@ -94,9 +94,9 @@ <% if @email.multipart? %> <dd> - <select onchange="document.getElementsByName('messageBody')[0].src=this.options[this.selectedIndex].value;"> - <option <%= request.format == Mime::HTML ? 'selected' : '' %> value="?part=text%2Fhtml">View as HTML email</option> - <option <%= request.format == Mime::TEXT ? 'selected' : '' %> value="?part=text%2Fplain">View as plain-text email</option> + <select onchange="formatChanged(this);"> + <option <%= request.format == Mime[:html] ? 'selected' : '' %> value="?part=text%2Fhtml">View as HTML email</option> + <option <%= request.format == Mime[:text] ? 'selected' : '' %> value="?part=text%2Fplain">View as plain-text email</option> </select> </dd> <% end %> @@ -112,5 +112,19 @@ </p> <% end %> +<script> + function formatChanged(form) { + var part_name = form.options[form.selectedIndex].value + var iframe =document.getElementsByName('messageBody')[0]; + iframe.contentWindow.location.replace(part_name); + + if (history.replaceState) { + var url = location.pathname.replace(/\.(txt|html)$/, ''); + var format = /html/.test(part_name) ? '.html' : '.txt'; + window.history.replaceState({}, '', url + format); + } + } +</script> + </body> </html> diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb index dacab08ec3..959c83b27c 100644 --- a/railties/lib/rails/test_unit/minitest_plugin.rb +++ b/railties/lib/rails/test_unit/minitest_plugin.rb @@ -3,16 +3,29 @@ require "rails/test_unit/reporter" require "rails/test_unit/test_requirer" module Minitest + mattr_accessor(:hide_aggregated_results) { false } + + module AggregatedResultSuppresion + def aggregated_results + super unless Minitest.hide_aggregated_results + end + end + + SummaryReporter.prepend AggregatedResultSuppresion + def self.plugin_rails_options(opts, options) + executable = Rails::TestUnitReporter.executable opts.separator "" - opts.separator "Usage: bin/rails test [options] [files or directories]" + opts.separator "Usage: #{executable} [options] [files or directories]" opts.separator "You can run a single test by appending a line number to a filename:" opts.separator "" - opts.separator " bin/rails test test/models/user_test.rb:27" + opts.separator " #{executable} test/models/user_test.rb:27" opts.separator "" opts.separator "You can run multiple files and directories at the same time:" opts.separator "" - opts.separator " bin/rails test test/controllers test/integration/login_test.rb" + opts.separator " #{executable} test/controllers test/integration/login_test.rb" + opts.separator "" + opts.separator "By default test failures and errors are reported inline during a run." opts.separator "" opts.separator "Rails options:" @@ -26,6 +39,17 @@ module Minitest options[:full_backtrace] = true end + opts.on("-d", "--defer-output", + "Output test failures and errors after the test run") do + options[:output_inline] = false + end + + opts.on("-f", "--fail-fast", + "Abort test run on first failure") do + options[:fail_fast] = true + end + + options[:output_inline] = true options[:patterns] = opts.order! end @@ -42,7 +66,8 @@ module Minitest ENV["RAILS_ENV"] = options[:environment] || "test" unless run_with_autorun - ::Rails::TestRequirer.require_files @rake_patterns || options[:patterns] + patterns = defined?(@rake_patterns) ? @rake_patterns : options[:patterns] + ::Rails::TestRequirer.require_files(patterns) end unless options[:full_backtrace] || ENV["BACKTRACE"] @@ -50,6 +75,9 @@ module Minitest Minitest.backtrace_filter = ::Rails.backtrace_cleaner if ::Rails.respond_to?(:backtrace_cleaner) end + # Disable the extra failure output after a run, unless output is deferred. + self.hide_aggregated_results = options[:output_inline] + self.reporter << ::Rails::TestUnitReporter.new(options[:io], options) end diff --git a/railties/lib/rails/test_unit/reporter.rb b/railties/lib/rails/test_unit/reporter.rb index 09b8675cf8..de4b002e55 100644 --- a/railties/lib/rails/test_unit/reporter.rb +++ b/railties/lib/rails/test_unit/reporter.rb @@ -6,8 +6,25 @@ module Rails class_attribute :executable self.executable = "bin/rails test" + def record(result) + super + + if output_inline? && result.failure && (!result.skipped? || options[:verbose]) + io.puts + io.puts + io.puts result.failures.map(&:message) + io.puts + io.puts format_rerun_snippet(result) + io.puts + end + + if fail_fast? && result.failure && !result.error? && !result.skipped? + raise Interrupt + end + end + def report - return if filtered_results.empty? + return if output_inline? || filtered_results.empty? io.puts io.puts "Failed tests:" io.puts @@ -15,10 +32,7 @@ module Rails end def aggregated_results # :nodoc: - filtered_results.map do |result| - location, line = result.method(result.name).source_location - "#{self.executable} #{relative_path_for(location)}:#{line}" - end.join "\n" + filtered_results.map { |result| format_rerun_snippet(result) }.join "\n" end def filtered_results @@ -32,5 +46,25 @@ module Rails def relative_path_for(file) file.sub(/^#{Rails.root}\/?/, '') end + + private + def output_inline? + options[:output_inline] + end + + def fail_fast? + options[:fail_fast] + end + + def format_rerun_snippet(result) + # Try to extract path to assertion from backtrace. + if result.location =~ /\[(.*)\]\z/ + assertion_path = $1 + else + assertion_path = result.method(result.name).source_location.join(':') + end + + "#{self.executable} #{relative_path_for(assertion_path)}" + end end end diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index fef65adda2..8b83784ed6 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -7,7 +7,10 @@ module ApplicationTests include Rack::Test::Methods def setup - build_app(initializers: true) + # FIXME: shush Sass warning spam, not relevant to testing Railties + Kernel.silence_warnings do + build_app(initializers: true) + end app_file "app/assets/javascripts/application.js", "//= require_tree ." app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }" @@ -33,12 +36,19 @@ 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/rake assets:precompile --trace 2>&1` } assert $?.success?, output - require "#{app_path}/config/environment" + + # Load app env + app "production" class ::PostsController < ActionController::Base ; end @@ -51,8 +61,8 @@ module ApplicationTests test "assets are served with sourcemaps when compile is true and debug_assets params is true" do add_to_env_config "production", "config.assets.compile = true" - ENV["RAILS_ENV"] = "production" - require "#{app_path}/config/environment" + # Load app env + app "production" class ::PostsController < ActionController::Base ; end diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index ddcd51f3fc..18882e1855 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -17,14 +17,23 @@ module ApplicationTests end def precompile!(env = nil) - quietly do - precompile_task = "bin/rake assets:precompile #{env} --trace 2>&1" - output = Dir.chdir(app_path) { %x[ #{precompile_task} ] } - assert $?.success?, output - output + with_env env.to_h do + quietly do + precompile_task = "bin/rake assets:precompile --trace 2>&1" + output = Dir.chdir(app_path) { %x[ #{precompile_task} ] } + assert $?.success?, output + output + end end end + def with_env(env) + env.each { |k, v| ENV[k.to_s] = v } + yield + ensure + env.each_key { |k| ENV.delete k.to_s } + end + def clean_assets! quietly do assert Dir.chdir(app_path) { system('bin/rake assets:clobber') } @@ -32,7 +41,8 @@ module ApplicationTests end def assert_file_exists(filename) - assert Dir[filename].first, "missing #{filename}" + globbed = Dir[filename] + assert globbed.one?, "Found #{globbed.size} files matching #{filename}. All files in the directory: #{Dir.entries(File.dirname(filename)).inspect}" end def assert_no_file_exists(filename) @@ -51,7 +61,10 @@ module ApplicationTests add_to_env_config "development", "config.assets.digest = false" - require "#{app_path}/config/environment" + # FIXME: shush Sass warning spam, not relevant to testing Railties + Kernel.silence_warnings do + require "#{app_path}/config/environment" + end get "/assets/demo.js" assert_equal 'a = "/assets/rails.png";', last_response.body.strip @@ -62,8 +75,8 @@ module ApplicationTests add_to_env_config "production", "config.assets.compile = true" add_to_env_config "production", "config.assets.precompile = []" - ENV["RAILS_ENV"] = "production" - require "#{app_path}/config/environment" + # Load app env + app "production" assert !defined?(Uglifier) get "/assets/demo.js" @@ -72,11 +85,10 @@ module ApplicationTests end test "precompile creates the file, gives it the original asset's content and run in production as default" do - app_file "app/assets/manifest.js", "//= link_tree ./javascripts" + app_file "app/assets/config/manifest.js", "//= link_tree ../javascripts" app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/javascripts/foo/application.js", "alert();" - ENV["RAILS_ENV"] = nil precompile! files = Dir["#{app_path}/public/assets/application-*.js"] @@ -88,7 +100,7 @@ module ApplicationTests end def test_precompile_does_not_hit_the_database - app_file "app/assets/manifest.js", "//= link_tree ./javascripts" + app_file "app/assets/config/manifest.js", "//= link_tree ../javascripts" app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/javascripts/foo/application.js", "alert();" app_file "app/controllers/users_controller.rb", <<-eoruby @@ -98,10 +110,9 @@ module ApplicationTests class User < ActiveRecord::Base; raise 'should not be reached'; end eoruby - ENV['RAILS_ENV'] = 'production' - ENV['DATABASE_URL'] = 'postgresql://baduser:badpass@127.0.0.1/dbname' - - precompile! + precompile! \ + RAILS_ENV: 'production', + DATABASE_URL: 'postgresql://baduser:badpass@127.0.0.1/dbname' files = Dir["#{app_path}/public/assets/application-*.js"] files << Dir["#{app_path}/public/assets/foo/application-*.js"].first @@ -109,9 +120,6 @@ module ApplicationTests assert_not_nil file, "Expected application.js asset to be generated, but none found" assert_equal "alert();".strip, File.read(file).strip end - ensure - ENV.delete 'RAILS_ENV' - ENV.delete 'DATABASE_URL' end test "precompile application.js and application.css and all other non JS/CSS files" do @@ -171,10 +179,9 @@ module ApplicationTests test 'precompile use assets defined in app env config' do add_to_env_config 'production', 'config.assets.precompile = [ "something.js" ]' - app_file 'app/assets/javascripts/something.js.erb', 'alert();' - precompile! 'RAILS_ENV=production' + precompile! RAILS_ENV: 'production' assert_file_exists("#{app_path}/public/assets/something-*.js") end @@ -183,15 +190,17 @@ module ApplicationTests add_to_config 'config.assets.precompile = [ "something_manifest.js" ]' add_to_env_config 'production', 'config.assets.precompile += [ "another_manifest.js" ]' - app_file 'app/assets/something_manifest.js', '//= link ./javascripts/something.js' - app_file 'app/assets/another_manifest.js', '//= link ./javascripts/another.js' + app_file 'app/assets/config/something_manifest.js', '//= link something.js' + app_file 'app/assets/config/another_manifest.js', '//= link another.js' app_file 'app/assets/javascripts/something.js.erb', 'alert();' app_file 'app/assets/javascripts/another.js.erb', 'alert();' - precompile! 'RAILS_ENV=production' + precompile! RAILS_ENV: 'production' + assert_file_exists("#{app_path}/public/assets/something_manifest-*.js") assert_file_exists("#{app_path}/public/assets/something-*.js") + assert_file_exists("#{app_path}/public/assets/another_manifest-*.js") assert_file_exists("#{app_path}/public/assets/another-*.js") end @@ -199,8 +208,8 @@ module ApplicationTests add_to_config "config.action_controller.perform_caching = false" add_to_env_config "production", "config.assets.compile = true" - ENV["RAILS_ENV"] = "production" - require "#{app_path}/config/environment" + # Load app env + app "production" assert_equal Sprockets::CachedEnvironment, Rails.application.assets.class end @@ -211,8 +220,8 @@ module ApplicationTests app_file "app/assets/javascripts/application.js", "alert();" precompile! - manifest = Dir["#{app_path}/public/assets/.sprockets-manifest-*.json"].first + manifest = Dir["#{app_path}/public/assets/.sprockets-manifest-*.json"].first assets = ActiveSupport::JSON.decode(File.read(manifest)) assert_match(/application-([0-z]+)\.js/, assets["assets"]["application.js"]) assert_match(/application-([0-z]+)\.css/, assets["assets"]["application.css"]) @@ -231,16 +240,16 @@ module ApplicationTests test "assets do not require any assets group gem when manifest file is present" do app_file "app/assets/javascripts/application.js", "alert();" - add_to_env_config "production", "config.serve_static_files = true" + add_to_env_config "production", "config.public_file_server.enabled = true" - ENV["RAILS_ENV"] = "production" - precompile! + precompile! RAILS_ENV: 'production' manifest = Dir["#{app_path}/public/assets/.sprockets-manifest-*.json"].first assets = ActiveSupport::JSON.decode(File.read(manifest)) asset_path = assets["assets"]["application.js"] - require "#{app_path}/config/environment" + # Load app env + app "production" # Checking if Uglifier is defined we can know if Sprockets was reached or not assert !defined?(Uglifier) @@ -249,12 +258,11 @@ module ApplicationTests assert !defined?(Uglifier) end - test "precompile properly refers files referenced with asset_path and runs in the provided RAILS_ENV" do + test "precompile properly refers files referenced with asset_path" do app_file "app/assets/images/rails.png", "notactuallyapng" app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }" - add_to_env_config "test", "config.assets.digest = true" - precompile!('RAILS_ENV=test') + precompile! file = Dir["#{app_path}/public/assets/application-*.css"].first assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file)) @@ -265,8 +273,7 @@ module ApplicationTests app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }" - ENV["RAILS_ENV"] = "production" - precompile! + precompile! RAILS_ENV: 'production' manifest = Dir["#{app_path}/public/assets/.sprockets-manifest-*.json"].first assets = ActiveSupport::JSON.decode(File.read(manifest)) @@ -275,8 +282,8 @@ module ApplicationTests app_file "app/assets/images/rails.png", "p { url: change }" precompile! - assets = ActiveSupport::JSON.decode(File.read(manifest)) + assets = ActiveSupport::JSON.decode(File.read(manifest)) assert_not_equal asset_path, assets["assets"]["application.css"] end @@ -284,8 +291,7 @@ module ApplicationTests app_file "app/assets/images/rails.png", "notactuallyapng" app_file "app/assets/stylesheets/application.css.erb", "p { background-image: url(<%= asset_path('rails.png') %>) }" - ENV["RAILS_ENV"] = "production" - precompile! + precompile! RAILS_ENV: 'production' file = Dir["#{app_path}/public/assets/application-*.css"].first assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file)) @@ -294,7 +300,7 @@ module ApplicationTests test "precompile should handle utf8 filenames" do filename = "レイルズ.png" app_file "app/assets/images/#{filename}", "not an image really" - app_file "app/assets/manifest.js", "//= link_tree ./images" + app_file "app/assets/config/manifest.js", "//= link_tree ../images" add_to_config "config.assets.precompile = %w(manifest.js)" precompile! @@ -303,7 +309,8 @@ module ApplicationTests assets = ActiveSupport::JSON.decode(File.read(manifest)) assert asset_path = assets["assets"].find { |(k, _)| k && k =~ /.png/ }[1] - require "#{app_path}/config/environment" + # Load app env + app "development" get "/assets/#{URI.parser.escape(asset_path)}" assert_match "not an image really", last_response.body @@ -326,8 +333,8 @@ module ApplicationTests app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" add_to_config "config.assets.compile = false" - ENV["RAILS_ENV"] = "production" - require "#{app_path}/config/environment" + # Load app env + app "production" get "/assets/demo.js" assert_equal 404, last_response.status @@ -344,7 +351,8 @@ module ApplicationTests add_to_env_config "development", "config.assets.digest = false" - require "#{app_path}/config/environment" + # Load app env + app "development" class ::OmgController < ActionController::Base def index @@ -370,7 +378,8 @@ module ApplicationTests add_to_env_config "development", "config.assets.digest = false" - require "#{app_path}/config/environment" + # Load app env + app "development" get "/assets/demo.js" assert_match "alert();", last_response.body @@ -381,10 +390,10 @@ module ApplicationTests app_with_assets_in_view # config.assets.debug and config.assets.compile are false for production environment - ENV["RAILS_ENV"] = "production" - precompile! + precompile! RAILS_ENV: 'production' - require "#{app_path}/config/environment" + # Load app env + app "production" class ::PostsController < ActionController::Base ; end @@ -400,6 +409,7 @@ module ApplicationTests app_file "app/assets/javascripts/xmlhr.js.erb", "<%= Post.name %>" precompile! + assert_equal "Post\n;\n", File.read(Dir["#{app_path}/public/assets/application-*.js"].first) end @@ -441,7 +451,10 @@ module ApplicationTests app_with_assets_in_view add_to_config "config.asset_host = 'example.com'" add_to_env_config "development", "config.assets.digest = false" - require "#{app_path}/config/environment" + + # Load app env + app "development" + class ::PostsController < ActionController::Base; end get '/posts', {}, {'HTTPS'=>'off'} @@ -456,6 +469,7 @@ module ApplicationTests add_to_config "config.assets.precompile = %w{rails.png image_loader.js}" add_to_config "config.asset_host = 'example.com'" add_to_env_config "development", "config.assets.digest = false" + precompile! assert_match "src='//example.com/assets/rails.png'", File.read(Dir["#{app_path}/public/assets/image_loader-*.js"].first) @@ -467,6 +481,7 @@ module ApplicationTests app_file "app/assets/javascripts/app.js.erb", "var src='<%= image_path('rails.png') %>';" add_to_config "config.assets.precompile = %w{rails.png app.js}" add_to_env_config "development", "config.assets.digest = false" + precompile! assert_match "src='/sub/uri/assets/rails.png'", File.read(Dir["#{app_path}/public/assets/app-*.js"].first) diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index f677a7c42a..5f3d1879eb 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -34,8 +34,19 @@ module ApplicationTests FileUtils.cp_r(app_path, new_app) end - def app - @app ||= Rails.application + def app(env = 'development') + @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 + + Rails.application + ensure + ENV.delete 'RAILS_ENV' + end end def setup @@ -78,7 +89,9 @@ module ApplicationTests require 'my_logger' config.logger = MyLogger.new STDOUT RUBY - require "#{app_path}/config/environment" + + app 'development' + assert_equal 'MyLogger', Rails.application.config.logger.class.name end @@ -97,7 +110,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' ActiveRecord::Migrator.migrations_paths = ["#{app_path}/db/migrate"] @@ -128,29 +141,29 @@ module ApplicationTests test "Rails.application is nil until app is initialized" do require 'rails' assert_nil Rails.application - require "#{app_path}/config/environment" + app 'development' assert_equal AppTemplate::Application.instance, Rails.application end test "Rails.application responds to all instance methods" do - require "#{app_path}/config/environment" + app 'development' assert_respond_to Rails.application, :routes_reloader assert_equal Rails.application.routes_reloader, AppTemplate::Application.routes_reloader end test "Rails::Application responds to paths" do - require "#{app_path}/config/environment" + app 'development' assert_respond_to AppTemplate::Application, :paths assert_equal ["#{app_path}/app/views"], AppTemplate::Application.paths["app/views"].expanded end test "the application root is set correctly" do - require "#{app_path}/config/environment" + app 'development' assert_equal Pathname.new(app_path), Rails.application.root end test "the application root can be seen from the application singleton" do - require "#{app_path}/config/environment" + app 'development' assert_equal Pathname.new(app_path), AppTemplate::Application.root end @@ -162,7 +175,8 @@ module ApplicationTests use_frameworks [] - require "#{app_path}/config/environment" + app 'development' + assert_equal Pathname.new(new_app), Rails.application.root end @@ -172,7 +186,7 @@ module ApplicationTests use_frameworks [] Dir.chdir("#{app_path}") do - require "#{app_path}/config/environment" + app 'development' assert_equal Pathname.new("#{app_path}"), Rails.application.root end end @@ -181,7 +195,9 @@ module ApplicationTests add_to_config <<-RUBY config.root = "#{app_path}" RUBY - require "#{app_path}/config/environment" + + app 'development' + assert_instance_of Pathname, Rails.root end @@ -189,7 +205,9 @@ module ApplicationTests add_to_config <<-RUBY config.paths["public"] = "somewhere" RUBY - require "#{app_path}/config/environment" + + app 'development' + assert_instance_of Pathname, Rails.public_path end @@ -199,12 +217,13 @@ module ApplicationTests config.cache_classes = true RUBY - require "#{app_path}/config/application" - assert Rails.application.initialize! + app 'development' + + assert_equal :require, ActiveSupport::Dependencies.mechanism end test "application is always added to eager_load namespaces" do - require "#{app_path}/config/application" + app 'development' assert_includes Rails.application.config.eager_load_namespaces, AppTemplate::Application end @@ -218,7 +237,7 @@ module ApplicationTests use_frameworks [] assert_nothing_raised do - require "#{app_path}/config/application" + app 'development' end end @@ -230,7 +249,7 @@ module ApplicationTests RUBY assert_nothing_raised do - require "#{app_path}/config/application" + app 'development' end end @@ -239,7 +258,7 @@ module ApplicationTests Rails.application.config.filter_parameters += [ :password, :foo, 'bar' ] RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal [:password, :foo, 'bar'], Rails.application.env_config['action_dispatch.parameter_filter'] end @@ -255,7 +274,7 @@ module ApplicationTests assert !$prepared - require "#{app_path}/config/environment" + app 'development' get "/" assert $prepared @@ -267,7 +286,7 @@ module ApplicationTests end test "skipping config.encoding still results in 'utf-8' as the default" do - require "#{app_path}/config/application" + app 'development' assert_utf8 end @@ -276,7 +295,7 @@ module ApplicationTests config.encoding = "utf-8" RUBY - require "#{app_path}/config/application" + app 'development' assert_utf8 end @@ -285,38 +304,58 @@ module ApplicationTests config.paths["public"] = "somewhere" RUBY - require "#{app_path}/config/application" + app 'development' assert_equal Pathname.new(app_path).join("somewhere"), Rails.public_path end - test "In production mode, config.serve_static_files is off by default" do + test "In production mode, config.public_file_server.enabled is off by default" do restore_default_config with_rails_env "production" do - require "#{app_path}/config/environment" - assert_not app.config.serve_static_files + app 'production' + assert_not app.config.public_file_server.enabled end end - test "In production mode, config.serve_static_files is enabled when RAILS_SERVE_STATIC_FILES is set" do + test "In production mode, config.public_file_server.enabled is enabled when RAILS_SERVE_STATIC_FILES is set" do restore_default_config with_rails_env "production" do switch_env "RAILS_SERVE_STATIC_FILES", "1" do - require "#{app_path}/config/environment" - assert app.config.serve_static_files + app 'production' + assert app.config.public_file_server.enabled end end end - test "In production mode, config.serve_static_files is disabled when RAILS_SERVE_STATIC_FILES is blank" do + test "In production mode, config.public_file_server.enabled is disabled when RAILS_SERVE_STATIC_FILES is blank" do restore_default_config with_rails_env "production" do switch_env "RAILS_SERVE_STATIC_FILES", " " do - require "#{app_path}/config/environment" - assert_not app.config.serve_static_files + app 'production' + assert_not app.config.public_file_server.enabled + end + end + end + + test "config.serve_static_files is deprecated" do + make_basic_app do |application| + assert_deprecated do + application.config.serve_static_files = true + end + + assert application.config.public_file_server.enabled + end + end + + test "config.static_cache_control is deprecated" do + make_basic_app do |application| + assert_deprecated do + application.config.static_cache_control = "public, max-age=60" end + + assert_equal application.config.static_cache_control, "public, max-age=60" end end @@ -363,8 +402,8 @@ module ApplicationTests development: secret_key_base: YAML - require "#{app_path}/config/environment" + app 'development' 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 @@ -380,13 +419,27 @@ module ApplicationTests development: secret_key_base: YAML - require "#{app_path}/config/environment" + + app 'development' assert_deprecated(/You didn't set `secret_key_base`./) do app.env_config end end + test "raise when secrets.secret_key_base is not a type of string" do + app_file 'config/secrets.yml', <<-YAML + development: + secret_key_base: 123 + YAML + + app 'development' + + assert_raise(ArgumentError) do + app.key_generator + end + end + test "prefer secrets.secret_token over config.secret_token" do app_file 'config/initializers/secret_token.rb', <<-RUBY Rails.application.config.secret_token = "" @@ -395,7 +448,8 @@ module ApplicationTests development: secret_token: 3b7cd727ee24e8444053437c36cc66c3 YAML - require "#{app_path}/config/environment" + + app 'development' assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_token end @@ -426,7 +480,7 @@ module ApplicationTests secret_key_base: 3b7cd727ee24e8444053437c36cc66c3 YAML - require "#{app_path}/config/environment" + app 'development' assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_key_base end @@ -436,7 +490,7 @@ module ApplicationTests Rails.application.config.secret_key_base = "3b7cd727ee24e8444053437c36cc66c3" RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal '3b7cd727ee24e8444053437c36cc66c3', app.secrets.secret_key_base end @@ -449,7 +503,8 @@ module ApplicationTests secret_key_base: secret_token: YAML - require "#{app_path}/config/environment" + + app 'development' assert_equal 'b3c631c314c0bbca50c1b2843150fe33', app.secrets.secret_token assert_equal 'b3c631c314c0bbca50c1b2843150fe33', app.config.secret_token @@ -463,7 +518,8 @@ module ApplicationTests aws_secret_access_key: myamazonsecretaccesskey YAML - require "#{app_path}/config/environment" + app 'development' + assert_equal 'myamazonaccesskeyid', app.secrets.aws_access_key_id assert_equal 'myamazonsecretaccesskey', app.secrets.aws_secret_access_key end @@ -471,7 +527,8 @@ module ApplicationTests test "blank config/secrets.yml does not crash the loading process" do app_file 'config/secrets.yml', <<-YAML YAML - require "#{app_path}/config/environment" + + app 'development' assert_nil app.secrets.not_defined end @@ -484,7 +541,8 @@ module ApplicationTests development: secret_key_base: YAML - require "#{app_path}/config/environment" + + app 'development' assert_equal "iaminallyoursecretkeybase", app.secrets.secret_key_base end @@ -497,7 +555,8 @@ module ApplicationTests development: secret_key_base: YAML - require "#{app_path}/config/environment" + + app 'development' assert_equal 'b3c631c314c0bbca50c1b2843150fe33', app.config.secret_token assert_equal nil, app.secrets.secret_key_base @@ -512,7 +571,8 @@ module ApplicationTests development: secret_key_base: YAML - require "#{app_path}/config/environment" + + app 'development' assert_equal '', app.config.secret_token assert_equal nil, app.secrets.secret_key_base @@ -535,7 +595,6 @@ module ApplicationTests end test "default form builder specified as a string" do - app_file 'config/initializers/form_builder.rb', <<-RUBY class CustomFormBuilder < ActionView::Helpers::FormBuilder def text_field(attribute, *args) @@ -567,7 +626,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' get "/posts" assert_match(/label/, last_response.body) @@ -606,9 +665,9 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' - params = {authenticity_token: token} + params = { authenticity_token: token } get "/posts/1" assert_match(/patch/, last_response.body) @@ -659,9 +718,9 @@ module ApplicationTests config.action_mailer.interceptors = MyMailInterceptor RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [::MyMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors") @@ -672,9 +731,9 @@ module ApplicationTests config.action_mailer.interceptors = [MyMailInterceptor, "MyOtherMailInterceptor"] RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [::MyMailInterceptor, ::MyOtherMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors") @@ -685,9 +744,9 @@ module ApplicationTests config.action_mailer.preview_interceptors = MyPreviewMailInterceptor RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [ActionMailer::InlinePreviewInterceptor, ::MyPreviewMailInterceptor], ActionMailer::Base.preview_interceptors @@ -698,9 +757,9 @@ module ApplicationTests config.action_mailer.preview_interceptors = [MyPreviewMailInterceptor, "MyOtherPreviewMailInterceptor"] RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [ActionMailer::InlinePreviewInterceptor, MyPreviewMailInterceptor, MyOtherPreviewMailInterceptor], ActionMailer::Base.preview_interceptors @@ -711,9 +770,9 @@ module ApplicationTests ActionMailer::Base.preview_interceptors.delete(ActionMailer::InlinePreviewInterceptor) RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [], ActionMailer::Base.preview_interceptors @@ -724,9 +783,9 @@ module ApplicationTests config.action_mailer.observers = MyMailObserver RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [::MyMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") @@ -737,9 +796,9 @@ module ApplicationTests config.action_mailer.observers = [MyMailObserver, "MyOtherMailObserver"] RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal [::MyMailObserver, ::MyOtherMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") @@ -750,9 +809,9 @@ module ApplicationTests config.action_mailer.deliver_later_queue_name = 'test_default' RUBY - require "#{app_path}/config/environment" - require "mail" + app 'development' + require "mail" _ = ActionMailer::Base assert_equal 'test_default', ActionMailer::Base.send(:class_variable_get, "@@deliver_later_queue_name") @@ -764,7 +823,7 @@ module ApplicationTests config.time_zone = "Wellington" RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal "Wellington", Rails.application.config.time_zone end @@ -776,7 +835,7 @@ module ApplicationTests RUBY assert_raise(ArgumentError) do - require "#{app_path}/config/environment" + app 'development' end end @@ -786,7 +845,7 @@ module ApplicationTests config.beginning_of_week = :wednesday RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal :wednesday, Rails.application.config.beginning_of_week end @@ -798,13 +857,14 @@ module ApplicationTests RUBY assert_raise(ArgumentError) do - require "#{app_path}/config/environment" + app 'development' end end test "config.action_view.cache_template_loading with cache_classes default" do add_to_config "config.cache_classes = true" - require "#{app_path}/config/environment" + + app 'development' require 'action_view/base' assert_equal true, ActionView::Resolver.caching? @@ -812,7 +872,8 @@ module ApplicationTests test "config.action_view.cache_template_loading without cache_classes default" do add_to_config "config.cache_classes = false" - require "#{app_path}/config/environment" + + app 'development' require 'action_view/base' assert_equal false, ActionView::Resolver.caching? @@ -823,7 +884,8 @@ module ApplicationTests config.cache_classes = true config.action_view.cache_template_loading = false RUBY - require "#{app_path}/config/environment" + + app 'development' require 'action_view/base' assert_equal false, ActionView::Resolver.caching? @@ -834,7 +896,8 @@ module ApplicationTests config.cache_classes = false config.action_view.cache_template_loading = true RUBY - require "#{app_path}/config/environment" + + app 'development' require 'action_view/base' assert_equal true, ActionView::Resolver.caching? @@ -849,7 +912,7 @@ module ApplicationTests require 'action_view/railtie' require 'action_view/base' - require "#{app_path}/config/environment" + app 'development' assert_equal false, ActionView::Resolver.caching? end @@ -902,7 +965,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' post "/posts.json", '{ "title": "foo", "name": "bar" }', "CONTENT_TYPE" => "application/json" assert_equal '{"title"=>"foo"}', last_response.body @@ -924,7 +987,7 @@ module ApplicationTests config.action_controller.permit_all_parameters = true RUBY - require "#{app_path}/config/environment" + app 'development' post "/posts", {post: {"title" =>"zomg"}} assert_equal 'permitted', last_response.body @@ -946,7 +1009,7 @@ module ApplicationTests config.action_controller.action_on_unpermitted_parameters = :raise RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters @@ -955,7 +1018,7 @@ module ApplicationTests end test "config.action_controller.always_permitted_parameters are: controller, action by default" do - require "#{app_path}/config/environment" + app 'development' assert_equal %w(controller action), ActionController::Parameters.always_permitted_parameters end @@ -963,7 +1026,9 @@ module ApplicationTests add_to_config <<-RUBY config.action_controller.always_permitted_parameters = %w( controller action format ) RUBY - require "#{app_path}/config/environment" + + app 'development' + assert_equal %w( controller action format ), ActionController::Parameters.always_permitted_parameters end @@ -984,7 +1049,7 @@ module ApplicationTests config.action_controller.action_on_unpermitted_parameters = :raise RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal :raise, ActionController::Parameters.action_on_unpermitted_parameters @@ -993,25 +1058,19 @@ module ApplicationTests end test "config.action_controller.action_on_unpermitted_parameters is :log by default on development" do - ENV["RAILS_ENV"] = "development" - - require "#{app_path}/config/environment" + app 'development' 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 - ENV["RAILS_ENV"] = "test" - - require "#{app_path}/config/environment" + app 'test' 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 - ENV["RAILS_ENV"] = "production" - - require "#{app_path}/config/environment" + app 'production' assert_equal false, ActionController::Parameters.action_on_unpermitted_parameters end @@ -1089,17 +1148,14 @@ module ApplicationTests test "config.active_record.dump_schema_after_migration is false on production" do build_app - ENV["RAILS_ENV"] = "production" - require "#{app_path}/config/environment" + app 'production' assert_not ActiveRecord::Base.dump_schema_after_migration end test "config.active_record.dump_schema_after_migration is true by default on development" do - ENV["RAILS_ENV"] = "development" - - require "#{app_path}/config/environment" + app 'development' assert ActiveRecord::Base.dump_schema_after_migration end @@ -1125,7 +1181,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' assert_not Rails.configuration.ran_block require 'rake' @@ -1147,7 +1203,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' assert_not Rails.configuration.ran_block Rails.application.load_generators @@ -1165,7 +1221,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' assert_not Rails.configuration.ran_block Rails.application.load_console @@ -1183,7 +1239,7 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' assert_not Rails.configuration.ran_block Rails.application.load_runner @@ -1199,14 +1255,14 @@ module ApplicationTests end RUBY - require "#{app_path}/config/environment" + app 'development' assert_kind_of Hash, Rails.application.config.database_configuration end test 'raises with proper error message if no database configuration found' do FileUtils.rm("#{app_path}/config/database.yml") - require "#{app_path}/config/environment" + app 'development' err = assert_raises RuntimeError do Rails.application.config.database_configuration end @@ -1214,25 +1270,23 @@ module ApplicationTests end test 'config.action_mailer.show_previews defaults to true in development' do - Rails.env = "development" - require "#{app_path}/config/environment" + app 'development' assert Rails.application.config.action_mailer.show_previews end test 'config.action_mailer.show_previews defaults to false in production' do - Rails.env = "production" - require "#{app_path}/config/environment" + app 'production' assert_equal false, Rails.application.config.action_mailer.show_previews end test 'config.action_mailer.show_previews can be set in the configuration file' do - Rails.env = "production" add_to_config <<-RUBY config.action_mailer.show_previews = true RUBY - require "#{app_path}/config/environment" + + app 'production' assert_equal true, Rails.application.config.action_mailer.show_previews end @@ -1247,7 +1301,7 @@ module ApplicationTests config.my_custom_config = config_for('custom') RUBY - require "#{app_path}/config/environment" + app 'development' assert_equal 'custom key', Rails.application.config.my_custom_config['key'] end @@ -1258,7 +1312,7 @@ module ApplicationTests RUBY exception = assert_raises(RuntimeError) do - require "#{app_path}/config/environment" + app 'development' end assert_equal "Could not load configuration. No such file - #{app_path}/config/custom.yml", exception.message @@ -1273,7 +1327,8 @@ module ApplicationTests add_to_config <<-RUBY config.my_custom_config = config_for('custom') RUBY - require "#{app_path}/config/environment" + + app 'development' assert_equal({}, Rails.application.config.my_custom_config) end @@ -1285,7 +1340,8 @@ module ApplicationTests add_to_config <<-RUBY config.my_custom_config = config_for('custom') RUBY - require "#{app_path}/config/environment" + + app 'development' assert_equal({}, Rails.application.config.my_custom_config) end @@ -1299,12 +1355,13 @@ module ApplicationTests add_to_config <<-RUBY config.my_custom_config = config_for('custom') RUBY - require "#{app_path}/config/environment" + + app 'development' assert_equal 'custom key', Rails.application.config.my_custom_config['key'] end - test "config_for with syntax error show a more descritive exception" do + test "config_for with syntax error show a more descriptive exception" do app_file 'config/custom.yml', <<-RUBY development: key: foo: @@ -1315,10 +1372,26 @@ module ApplicationTests RUBY exception = assert_raises(RuntimeError) do - require "#{app_path}/config/environment" + app 'development' end assert_match 'YAML syntax error occurred while parsing', exception.message end + + test "config_for allows overriding the environment" do + app_file 'config/custom.yml', <<-RUBY + test: + key: 'walrus' + production: + key: 'unicorn' + RUBY + + add_to_config <<-RUBY + config.my_custom_config = config_for('custom', env: 'production') + RUBY + require "#{app_path}/config/environment" + + assert_equal 'unicorn', Rails.application.config.my_custom_config['key'] + end end end diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index 6e3707cc27..13f3250f5b 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -49,6 +49,17 @@ module ApplicationTests assert_equal "test.rails", ActionMailer::Base.default_url_options[:host] end + test "Default to HTTPS for ActionMailer URLs when force_ssl is on" do + app_file "config/environments/development.rb", <<-RUBY + Rails.application.configure do + config.force_ssl = true + end + RUBY + + require "#{app_path}/config/environment" + assert_equal "https", ActionMailer::Base.default_url_options[:protocol] + end + test "includes url helpers as action methods" do app_file "config/routes.rb", <<-RUBY Rails.application.routes.draw do diff --git a/railties/test/application/mailer_previews_test.rb b/railties/test/application/mailer_previews_test.rb index e462d2c15e..643d876a26 100644 --- a/railties/test/application/mailer_previews_test.rb +++ b/railties/test/application/mailer_previews_test.rb @@ -31,7 +31,7 @@ module ApplicationTests test "/rails/mailers is accessible with correct configuraiton" do add_to_config "config.action_mailer.show_previews = true" app("production") - get "/rails/mailers" + get "/rails/mailers", {}, {"REMOTE_ADDR" => "4.2.42.42"} assert_equal 200, last_response.status end diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb index 4906f9a1e8..7b4babb13b 100644 --- a/railties/test/application/middleware/exceptions_test.rb +++ b/railties/test/application/middleware/exceptions_test.rb @@ -48,7 +48,7 @@ module ApplicationTests test "uses custom exceptions app" do add_to_config <<-RUBY config.exceptions_app = lambda do |env| - [404, { "Content-Type" => "text/plain" }, ["YOU FAILED BRO"]] + [404, { "Content-Type" => "text/plain" }, ["YOU FAILED"]] end RUBY @@ -56,7 +56,7 @@ module ApplicationTests get "/foo" assert_equal 404, last_response.status - assert_equal "YOU FAILED BRO", last_response.body + assert_equal "YOU FAILED", last_response.body end test "url generation error when action_dispatch.show_exceptions is set raises an exception" do @@ -67,7 +67,7 @@ module ApplicationTests end end RUBY - + app.config.action_dispatch.show_exceptions = true get '/foo' diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb index dc96480d6d..be86f1a3b8 100644 --- a/railties/test/application/middleware/sendfile_test.rb +++ b/railties/test/application/middleware/sendfile_test.rb @@ -61,7 +61,7 @@ module ApplicationTests test "files handled by ActionDispatch::Static are handled by Rack::Sendfile" do make_basic_app do |app| app.config.action_dispatch.x_sendfile_header = 'X-Sendfile' - app.config.serve_static_files = true + app.config.public_file_server.enabled = true app.paths["public"] = File.join(rails_root, "public") end diff --git a/railties/test/application/middleware/static_test.rb b/railties/test/application/middleware/static_test.rb index 1a46cd3568..1246e20d94 100644 --- a/railties/test/application/middleware/static_test.rb +++ b/railties/test/application/middleware/static_test.rb @@ -27,7 +27,24 @@ module ApplicationTests assert_not last_response.headers.has_key?('Cache-Control'), "Cache-Control should not be set" end - test "static_index defaults to 'index'" do + test "headers for static files are configurable" do + app_file "public/about.html", 'static' + add_to_config <<-CONFIG + config.public_file_server.headers = { + "Access-Control-Allow-Origin" => "http://rubyonrails.org", + "Cache-Control" => "public, max-age=60" + } + CONFIG + + require "#{app_path}/config/environment" + + get '/about.html' + + assert_equal 'http://rubyonrails.org', last_response.headers["Access-Control-Allow-Origin"] + assert_equal 'public, max-age=60', last_response.headers["Cache-Control"] + end + + test "public_file_server.index_name defaults to 'index'" do app_file "public/index.html", "/index.html" require "#{app_path}/config/environment" @@ -37,10 +54,10 @@ module ApplicationTests assert_equal "/index.html\n", last_response.body end - test "static_index configurable" do + test "public_file_server.index_name configurable" do app_file "public/other-index.html", "/other-index.html" - add_to_config "config.static_index = 'other-index'" - + add_to_config "config.public_file_server.index_name = 'other-index'" + require "#{app_path}/config/environment" get '/' diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index d298e8d632..1434522cce 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -43,7 +43,6 @@ module ApplicationTests "ActionDispatch::Cookies", "ActionDispatch::Session::CookieStore", "ActionDispatch::Flash", - "ActionDispatch::ParamsParser", "Rack::Head", "Rack::ConditionalGet", "Rack::ETag" @@ -70,7 +69,6 @@ module ApplicationTests "ActionDispatch::Callbacks", "ActiveRecord::ConnectionAdapters::ConnectionManagement", "ActiveRecord::QueryCache", - "ActionDispatch::ParamsParser", "Rack::Head", "Rack::ConditionalGet", "Rack::ETag" @@ -157,8 +155,8 @@ module ApplicationTests assert_not_includes middleware, "ActionDispatch::LoadInterlock" end - test "removes static asset server if serve_static_files is disabled" do - add_to_config "config.serve_static_files = false" + test "removes static asset server if public_file_server.enabled is disabled" do + add_to_config "config.public_file_server.enabled = false" boot! assert !middleware.include?("ActionDispatch::Static") end diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index e7beab8b5e..f94d08673a 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -49,6 +49,58 @@ module ApplicationTests db_create_and_drop database_url_db_name end + def with_database_existing + Dir.chdir(app_path) do + set_database_url + `bin/rake db:create` + yield + `bin/rake db:drop` + end + end + + test 'db:create failure because database exists' do + with_database_existing do + output = `bin/rake db:create 2>&1` + assert_match /already exists/, output + assert_equal 0, $?.exitstatus + end + end + + def with_bad_permissions + Dir.chdir(app_path) do + set_database_url + FileUtils.chmod("-w", "db") + yield + FileUtils.chmod("+w", "db") + end + end + + test 'db:create failure because bad permissions' do + with_bad_permissions do + output = `bin/rake db:create 2>&1` + 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/rake db:drop 2>&1` + assert_match /does not exist/, output + assert_equal 0, $?.exitstatus + end + end + + test 'db:drop failure because bad permissions' do + with_database_existing do + with_bad_permissions do + output = `bin/rake db:drop 2>&1` + assert_match /Couldn't drop/, output + assert_equal 1, $?.exitstatus + end + end + end + def db_migrate_and_status(expected_database) Dir.chdir(app_path) do `bin/rails generate model book title:string; diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index 2d8bd7c571..6b74707959 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -154,6 +154,28 @@ module ApplicationTests end 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 + end + MIGRATION + + app_file "db/migrate/02_two_migration.rb", <<-MIGRATION + class TwoMigration < ActiveRecord::Migration + end + MIGRATION + + `bin/rake db:migrate` + + output = `bin/rake db:migrate:status` + + assert_match(/up\s+001\s+One migration/, output) + assert_match(/up\s+002\s+Two migration/, output) + end + end + test 'schema generation when dump_schema_after_migration is set' do add_to_config('config.active_record.dump_schema_after_migration = false') diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index a040dd4cf6..0da0928b48 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -1,4 +1,3 @@ -# coding:utf-8 require "isolation/abstract_unit" require "active_support/core_ext/string/strip" diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index cbada6be97..0777714d35 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -21,6 +21,12 @@ module ApplicationTests assert_equal 200, last_response.status end + test "rails/info in development" do + app("development") + get "/rails/info" + assert_equal 302, last_response.status + end + test "rails/info/routes in development" do app("development") get "/rails/info/routes" @@ -63,6 +69,12 @@ module ApplicationTests assert_equal 404, last_response.status end + test "rails/info in production" do + app("production") + get "/rails/info" + assert_equal 404, last_response.status + end + test "rails/info/routes in production" do app("production") get "/rails/info/routes" diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index 2d47a31826..4965ab7da0 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -340,6 +340,27 @@ module ApplicationTests assert_match '0 runs, 0 assertions', run_test_command('') end + def test_output_inline_by_default + create_test_file :models, 'post', pass: false + + output = run_test_command('test/models/post_test.rb') + assert_match %r{Running:\n\nPostTest\nF\n\nwups!\n\nbin/rails test test/models/post_test.rb:6}, output + end + + def test_only_inline_failure_output + 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 + 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') }) + end + def test_raise_error_when_specified_file_does_not_exist error = capture(:stderr) { run_test_command('test/not_exists.rb') } assert_match(%r{cannot load such file.+test/not_exists\.rb}, error) @@ -396,14 +417,14 @@ module ApplicationTests app_file 'db/schema.rb', '' end - def create_test_file(path = :unit, name = 'test') + def create_test_file(path = :unit, name = 'test', pass: 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" - assert true + assert #{pass}, 'wups!' end end RUBY diff --git a/railties/test/code_statistics_calculator_test.rb b/railties/test/code_statistics_calculator_test.rb index 46445a001a..cecc3908b3 100644 --- a/railties/test/code_statistics_calculator_test.rb +++ b/railties/test/code_statistics_calculator_test.rb @@ -299,6 +299,22 @@ class Animal assert_equal 0, @code_statistics_calculator.methods end + test 'count rake tasks' do + code = <<-'CODE' + task :test_task do + puts 'foo' + end + + CODE + + @code_statistics_calculator.add_by_io(StringIO.new(code), :rake) + + assert_equal 4, @code_statistics_calculator.lines + assert_equal 3, @code_statistics_calculator.code_lines + assert_equal 0, @code_statistics_calculator.classes + assert_equal 0, @code_statistics_calculator.methods + end + private def temp_file(name, content) dir = File.expand_path '../fixtures/tmp', __FILE__ diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index fabba555ef..b4fbea4af4 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -235,6 +235,21 @@ class ActionsTest < Rails::Generators::TestCase assert_file 'config/routes.rb', /#{Regexp.escape(route_command)}/ end + def test_route_should_be_idempotent + run_generator + route_path = File.expand_path('config/routes.rb', destination_root) + + # runs first time, not asserting + action :route, "root 'welcome#index'" + content_1 = File.read(route_path) + + # runs second time + action :route, "root 'welcome#index'" + content_2 = File.read(route_path) + + assert_equal content_1, content_2 + end + def test_route_should_add_data_with_an_new_line run_generator action :route, "root 'welcome#index'" diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index daf362357c..446fef562b 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -1,7 +1,6 @@ require 'generators/generators_test_helper' require 'rails/generators/rails/app/app_generator' require 'generators/shared_generator_tests' -require 'mocha/setup' # FIXME: stop using mocha DEFAULT_APP_FILES = %w( .gitignore @@ -117,35 +116,33 @@ class AppGeneratorTest < Rails::Generators::TestCase run_generator [app_root] - Rails.application.config.root = app_moved_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) + stub_rails_application(app_moved_root) do + Rails.application.stub(:is_a?, -> *args { Rails::Application }) do + FileUtils.mv(app_root, app_moved_root) - FileUtils.mv(app_root, app_moved_root) + # make sure we are in correct dir + FileUtils.cd(app_moved_root) - # make sure we are in correct dir - FileUtils.cd(app_moved_root) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, - destination_root: app_moved_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_file "myapp_moved/config/environment.rb", /Rails\.application\.initialize!/ - assert_file "myapp_moved/config/initializers/session_store.rb", /_myapp_session/ + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, + destination_root: app_moved_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_file "myapp_moved/config/environment.rb", /Rails\.application\.initialize!/ + assert_file "myapp_moved/config/initializers/session_store.rb", /_myapp_session/ + end + end end def test_rails_update_generates_correct_session_key app_root = File.join(destination_root, 'myapp') run_generator [app_root] - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_file "myapp/config/initializers/session_store.rb", /_myapp_session/ + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_file "myapp/config/initializers/session_store.rb", /_myapp_session/ + end end def test_new_application_use_json_serialzier @@ -158,14 +155,12 @@ class AppGeneratorTest < Rails::Generators::TestCase app_root = File.join(destination_root, 'myapp') run_generator [app_root] - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_file("#{app_root}/config/initializers/cookies_serializer.rb", /Rails\.application\.config\.action_dispatch\.cookies_serializer = :json/) + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_file("#{app_root}/config/initializers/cookies_serializer.rb", /Rails\.application\.config\.action_dispatch\.cookies_serializer = :json/) + end end def test_rails_update_does_not_create_callback_terminator_initializer @@ -174,14 +169,12 @@ class AppGeneratorTest < Rails::Generators::TestCase FileUtils.rm("#{app_root}/config/initializers/callback_terminator.rb") - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_no_file "#{app_root}/config/initializers/callback_terminator.rb" + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_no_file "#{app_root}/config/initializers/callback_terminator.rb" + end end def test_rails_update_does_not_remove_callback_terminator_initializer_if_already_present @@ -190,14 +183,12 @@ class AppGeneratorTest < Rails::Generators::TestCase FileUtils.touch("#{app_root}/config/initializers/callback_terminator.rb") - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_file "#{app_root}/config/initializers/callback_terminator.rb" + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_file "#{app_root}/config/initializers/callback_terminator.rb" + end end def test_rails_update_set_the_cookie_serializer_to_marchal_if_it_is_not_already_configured @@ -206,14 +197,12 @@ class AppGeneratorTest < Rails::Generators::TestCase FileUtils.rm("#{app_root}/config/initializers/cookies_serializer.rb") - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_file("#{app_root}/config/initializers/cookies_serializer.rb", /Rails\.application\.config\.action_dispatch\.cookies_serializer = :marshal/) + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_file("#{app_root}/config/initializers/cookies_serializer.rb", /Rails\.application\.config\.action_dispatch\.cookies_serializer = :marshal/) + end end def test_rails_update_does_not_create_active_record_belongs_to_required_by_default @@ -222,14 +211,12 @@ class AppGeneratorTest < Rails::Generators::TestCase FileUtils.rm("#{app_root}/config/initializers/active_record_belongs_to_required_by_default.rb") - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_no_file "#{app_root}/config/initializers/active_record_belongs_to_required_by_default.rb" + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_no_file "#{app_root}/config/initializers/active_record_belongs_to_required_by_default.rb" + end end def test_rails_update_does_not_remove_active_record_belongs_to_required_by_default_if_already_present @@ -238,14 +225,12 @@ class AppGeneratorTest < Rails::Generators::TestCase FileUtils.touch("#{app_root}/config/initializers/active_record_belongs_to_required_by_default.rb") - Rails.application.config.root = app_root - Rails.application.class.stubs(:name).returns("Myapp") - Rails.application.stubs(:is_a?).returns(Rails::Application) - - generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell - generator.send(:app_const) - quietly { generator.send(:update_config_files) } - assert_file "#{app_root}/config/initializers/active_record_belongs_to_required_by_default.rb" + stub_rails_application(app_root) do + generator = Rails::Generators::AppGenerator.new ["rails"], { with_dispatchers: true }, destination_root: app_root, shell: @shell + generator.send(:app_const) + quietly { generator.send(:update_config_files) } + assert_file "#{app_root}/config/initializers/active_record_belongs_to_required_by_default.rb" + end end def test_application_names_are_not_singularized @@ -279,7 +264,7 @@ class AppGeneratorTest < Rails::Generators::TestCase if defined?(JRUBY_VERSION) assert_gem "activerecord-jdbcmysql-adapter" else - assert_gem "mysql2" + assert_gem "mysql2", "'>= 0.3.18', '< 0.5'" end end @@ -294,7 +279,7 @@ class AppGeneratorTest < Rails::Generators::TestCase if defined?(JRUBY_VERSION) assert_gem "activerecord-jdbcpostgresql-adapter" else - assert_gem "pg" + assert_gem "pg", "'~> 0.18'" end end @@ -456,13 +441,15 @@ class AppGeneratorTest < Rails::Generators::TestCase end def test_usage_read_from_file - File.expects(:read).returns("USAGE FROM FILE") - assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc + assert_called(File, :read, returns: "USAGE FROM FILE") do + assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc + end end def test_default_usage - Rails::Generators::AppGenerator.expects(:usage_path).returns(nil) - assert_match(/Create rails files for app generator/, Rails::Generators::AppGenerator.desc) + assert_called(Rails::Generators::AppGenerator, :usage_path, returns: nil) do + assert_match(/Create rails files for app generator/, Rails::Generators::AppGenerator.desc) + end end def test_default_namespace @@ -538,18 +525,31 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_spring_binstubs jruby_skip "spring doesn't run on JRuby" - generator.stubs(:bundle_command).with('install') - generator.expects(:bundle_command).with('exec spring binstub --all').once - quietly { generator.invoke_all } + command_check = -> command do + @binstub_called ||= 0 + + case command + when 'install' + # Called when running bundle, we just want to stub it so nothing to do here. + when 'exec spring binstub --all' + @binstub_called += 1 + assert_equal 1, @binstub_called, "exec spring binstub --all expected to be called once, but was called #{@install_called} times." + end + end + + generator.stub :bundle_command, command_check do + quietly { generator.invoke_all } + end end def test_spring_no_fork jruby_skip "spring doesn't run on JRuby" - Process.stubs(:respond_to?).with(:fork).returns(false) - run_generator + assert_called_with(Process, :respond_to?, [:fork], returns: false) do + run_generator - assert_file "Gemfile" do |content| - assert_no_match(/spring/, content) + assert_file "Gemfile" do |content| + assert_no_match(/spring/, content) + end end end @@ -651,23 +651,46 @@ class AppGeneratorTest < Rails::Generators::TestCase template = %{ after_bundle { run 'echo ran after_bundle' } } template.instance_eval "def read; self; end" # Make the string respond to read - generator([destination_root], template: path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + check_open = -> *args do + assert_equal [ path, 'Accept' => 'application/x-thor-template' ], args + template + end - bundler_first = sequence('bundle, binstubs, after_bundle') - generator.expects(:bundle_command).with('install').once.in_sequence(bundler_first) - generator.expects(:bundle_command).with('exec spring binstub --all').in_sequence(bundler_first) - generator.expects(:run).with('echo ran after_bundle').in_sequence(bundler_first) + sequence = ['install', 'exec spring binstub --all', 'echo ran after_bundle'] + ensure_bundler_first = -> command do + @sequence_step ||= 0 - quietly { generator.invoke_all } + assert_equal sequence[@sequence_step], command, "commands should be called in sequence #{sequence}" + @sequence_step += 1 + end + + 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 } + end + end + end end protected + def stub_rails_application(root) + Rails.application.config.root = root + Rails.application.class.stub(:name, "Myapp") do + yield + end + end + def action(*args, &block) capture(:stdout) { generator.send(*args, &block) } end - def assert_gem(gem) - assert_file "Gemfile", /^\s*gem\s+["']#{gem}["']$*/ + def assert_gem(gem, constraint = nil) + if constraint + assert_file "Gemfile", /^\s*gem\s+["']#{gem}["'], #{constraint}$*/ + else + assert_file "Gemfile", /^\s*gem\s+["']#{gem}["']$*/ + end end end diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index 57bc220558..199743a396 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -221,6 +221,15 @@ class MigrationGeneratorTest < Rails::Generators::TestCase end end + def test_add_uuid_to_create_table_migration + run_generator ["create_books", "--primary_key_type=uuid"] + assert_migration "db/migrate/create_books.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :books, id: :uuid/, change) + end + end + end + def test_should_create_empty_migrations_if_name_not_start_with_add_or_remove_or_create migration = "delete_books" run_generator [migration, "title:string", "content:text"] diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index abd3ff50a4..64b9a480f3 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -374,6 +374,15 @@ class ModelGeneratorTest < Rails::Generators::TestCase end end + def test_add_uuid_to_create_table_migration + run_generator ["account", "--primary_key_type=uuid"] + assert_migration "db/migrate/create_accounts.rb" do |content| + assert_method :change, content do |change| + assert_match(/create_table :accounts, id: :uuid/, change) + end + end + end + def test_required_belongs_to_adds_required_association run_generator ["account", "supplier:references{required}"] diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb index e839b67960..590f06e19a 100644 --- a/railties/test/generators/namespaced_generators_test.rb +++ b/railties/test/generators/namespaced_generators_test.rb @@ -281,6 +281,7 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase # Controller assert_file "app/controllers/test_app/admin/roles_controller.rb" do |content| assert_match(/module TestApp\n class Admin::RolesController < ApplicationController/, content) + assert_match(%r(require_dependency "test_app/application_controller"), content) end assert_file "test/controllers/test_app/admin/roles_controller_test.rb", @@ -395,4 +396,28 @@ class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase # Stylesheets (should not be removed) assert_file "app/assets/stylesheets/scaffold.css" end + + def test_api_scaffold_with_namespace_on_invoke + run_generator [ "admin/role", "name:string", "description:string", "--api" ] + + # Model + assert_file "app/models/test_app/admin.rb", /module TestApp\n module Admin/ + assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ActiveRecord::Base/ + assert_file "test/models/test_app/admin/role_test.rb", /module TestApp\n class Admin::RoleTest < ActiveSupport::TestCase/ + assert_file "test/fixtures/test_app/admin/roles.yml" + assert_migration "db/migrate/create_test_app_admin_roles.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_match(/^ namespace :admin do\n resources :roles\n end$/, route) + end + + # Controller + assert_file "app/controllers/test_app/admin/roles_controller.rb" do |content| + assert_match(/module TestApp\n class Admin::RolesController < ApplicationController/, content) + assert_match(%r(require_dependency "test_app/application_controller"), content) + end + assert_file "test/controllers/test_app/admin/roles_controller_test.rb", + /module TestApp\n class Admin::RolesControllerTest < ActionController::TestCase/ + end end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index afccf9d885..67c744b529 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -1,7 +1,6 @@ require 'generators/generators_test_helper' require 'rails/generators/rails/plugin/plugin_generator' require 'generators/shared_generator_tests' -require 'mocha/setup' # FIXME: stop using mocha DEFAULT_PLUGIN_FILES = %w( .gitignore @@ -61,12 +60,16 @@ class PluginGeneratorTest < Rails::Generators::TestCase run_generator assert_file "README.rdoc", /Bukkits/ assert_no_file "config/routes.rb" + assert_no_file "app/assets/config/bukkits_manifest.js" assert_file "test/test_helper.rb" do |content| assert_match(/require.+test\/dummy\/config\/environment/, content) assert_match(/ActiveRecord::Migrator\.migrations_paths.+test\/dummy\/db\/migrate/, content) assert_match(/Minitest\.backtrace_filter = Minitest::BacktraceFilter\.new/, content) + assert_match(/Rails::TestUnitReporter\.executable = 'bin\/test'/, content) end assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/ + assert_file 'bin/test' + assert_no_file 'bin/rails' end def test_generating_test_files_in_full_mode @@ -223,7 +226,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase run_generator FileUtils.cd destination_root quietly { system 'bundle install' } - assert_match(/1 runs, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test 2>&1`) + assert_match(/1 runs, 1 assertions, 0 failures, 0 errors/, `bin/test 2>&1`) end def test_ensure_that_tests_works_in_full_mode @@ -304,6 +307,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "lib/bukkits/engine.rb", /isolate_namespace Bukkits/ assert_file "test/dummy/config/routes.rb", /mount Bukkits::Engine => "\/bukkits"/ assert_file "app/controllers/bukkits/application_controller.rb", /module Bukkits\n class ApplicationController < ActionController::Base/ + assert_file "app/jobs/bukkits/application_job.rb", /module Bukkits\n class ApplicationJob < ActiveJob::Base/ 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 @@ -314,7 +318,9 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_match(/ActiveRecord::Migrator\.migrations_paths.+\.\.\/test\/dummy\/db\/migrate/, content) assert_match(/ActiveRecord::Migrator\.migrations_paths.+<<.+\.\.\/db\/migrate/, content) assert_match(/ActionDispatch::IntegrationTest\.fixture_path = ActiveSupport::TestCase\.fixture_pat/, content) + assert_no_match(/Rails::TestUnitReporter\.executable = 'bin\/test'/, content) end + assert_no_file 'bin/test' end def test_create_mountable_application_with_mountable_option_and_hypenated_name @@ -328,6 +334,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "hyphenated-name/lib/hyphenated/name.rb", /require "hyphenated\/name\/engine"/ assert_file "hyphenated-name/test/dummy/config/routes.rb", /mount Hyphenated::Name::Engine => "\/hyphenated-name"/ assert_file "hyphenated-name/app/controllers/hyphenated/name/application_controller.rb", /module Hyphenated\n module Name\n class ApplicationController < ActionController::Base\n end\n end\nend/ + assert_file "hyphenated-name/app/jobs/hyphenated/name/application_job.rb", /module Hyphenated\n module Name\n class ApplicationJob < ActiveJob::Base/ assert_file "hyphenated-name/app/helpers/hyphenated/name/application_helper.rb", /module Hyphenated\n module Name\n module ApplicationHelper\n end\n end\nend/ assert_file "hyphenated-name/app/views/layouts/hyphenated/name/application.html.erb" do |contents| assert_match "<title>Hyphenated name</title>", contents @@ -347,6 +354,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "my_hyphenated-name/lib/my_hyphenated/name.rb", /require "my_hyphenated\/name\/engine"/ assert_file "my_hyphenated-name/test/dummy/config/routes.rb", /mount MyHyphenated::Name::Engine => "\/my_hyphenated-name"/ assert_file "my_hyphenated-name/app/controllers/my_hyphenated/name/application_controller.rb", /module MyHyphenated\n module Name\n class ApplicationController < ActionController::Base\n end\n end\nend/ + assert_file "my_hyphenated-name/app/jobs/my_hyphenated/name/application_job.rb", /module MyHyphenated\n module Name\n class ApplicationJob < ActiveJob::Base/ assert_file "my_hyphenated-name/app/helpers/my_hyphenated/name/application_helper.rb", /module MyHyphenated\n module Name\n module ApplicationHelper\n end\n end\nend/ assert_file "my_hyphenated-name/app/views/layouts/my_hyphenated/name/application.html.erb" do |contents| assert_match "<title>My hyphenated name</title>", contents @@ -366,6 +374,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase assert_file "deep-hyphenated-name/lib/deep/hyphenated/name.rb", /require "deep\/hyphenated\/name\/engine"/ assert_file "deep-hyphenated-name/test/dummy/config/routes.rb", /mount Deep::Hyphenated::Name::Engine => "\/deep-hyphenated-name"/ assert_file "deep-hyphenated-name/app/controllers/deep/hyphenated/name/application_controller.rb", /module Deep\n module Hyphenated\n module Name\n class ApplicationController < ActionController::Base\n end\n end\n end\nend/ + assert_file "deep-hyphenated-name/app/jobs/deep/hyphenated/name/application_job.rb", /module Deep\n module Hyphenated\n module Name\n class ApplicationJob < ActiveJob::Base/ assert_file "deep-hyphenated-name/app/helpers/deep/hyphenated/name/application_helper.rb", /module Deep\n module Hyphenated\n module Name\n module ApplicationHelper\n end\n end\n end\nend/ assert_file "deep-hyphenated-name/app/views/layouts/deep/hyphenated/name/application.html.erb" do |contents| assert_match "<title>Deep hyphenated name</title>", contents @@ -436,6 +445,19 @@ class PluginGeneratorTest < Rails::Generators::TestCase end end + def test_unnecessary_files_are_not_generated_in_dummy_application + run_generator + assert_no_file 'test/dummy/.gitignore' + assert_no_file 'test/dummy/db/seeds.rb' + assert_no_file 'test/dummy/Gemfile' + assert_no_file 'test/dummy/public/robots.txt' + assert_no_file 'test/dummy/README.md' + 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' + end + def test_skipping_test_files run_generator [destination_root, "--skip-test"] assert_no_file "test" diff --git a/railties/test/generators/plugin_test_runner_test.rb b/railties/test/generators/plugin_test_runner_test.rb new file mode 100644 index 0000000000..0887afd0db --- /dev/null +++ b/railties/test/generators/plugin_test_runner_test.rb @@ -0,0 +1,123 @@ +require 'tmpdir' +require 'abstract_unit' + +class PluginTestRunnerTest < ActiveSupport::TestCase + def setup + @destination_root = Dir.mktmpdir('bukkits') + Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --skip-bundle` } + plugin_file 'test/dummy/db/schema.rb', '' + end + + def teardown + FileUtils.rm_rf(@destination_root) + end + + def test_run_single_file + create_test_file 'foo' + create_test_file 'bar' + assert_match "1 runs, 1 assertions, 0 failures", run_test_command("test/foo_test.rb") + end + + def test_run_multiple_files + create_test_file 'foo' + create_test_file 'bar' + assert_match "2 runs, 2 assertions, 0 failures", run_test_command("test/foo_test.rb test/bar_test.rb") + end + + def test_mix_files_and_line_filters + create_test_file 'account' + plugin_file 'test/post_test.rb', <<-RUBY + require 'test_helper' + + class PostTest < ActiveSupport::TestCase + def test_post + puts 'PostTest' + assert true + end + + def test_line_filter_does_not_run_this + assert true + end + end + RUBY + + run_test_command('test/account_test.rb test/post_test.rb:4').tap do |output| + assert_match 'AccountTest', output + assert_match 'PostTest', output + assert_match '2 runs, 2 assertions', output + end + end + + def test_multiple_line_filters + create_test_file 'account' + create_test_file 'post' + + run_test_command('test/account_test.rb:4 test/post_test.rb:4').tap do |output| + assert_match 'AccountTest', output + assert_match 'PostTest', output + end + end + + def test_line_filter_without_line_runs_all_tests + create_test_file 'account' + + run_test_command('test/account_test.rb:').tap do |output| + assert_match 'AccountTest', output + end + end + + def test_output_inline_by_default + create_test_file 'post', pass: false + + output = run_test_command('test/post_test.rb') + assert_match %r{Running:\n\nPostTest\nF\n\nwups!\n\nbin/test #{plugin_path}/test/post_test.rb:6}, output + end + + def test_only_inline_failure_output + 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 + end + + def test_fail_fast + create_test_file 'post', pass: false + + assert_match(/Interrupt/, + capture(:stderr) { run_test_command('test/post_test.rb --fail-fast') }) + end + + def test_raise_error_when_specified_file_does_not_exist + error = capture(:stderr) { run_test_command('test/not_exists.rb') } + assert_match(%r{cannot load such file.+test/not_exists\.rb}, error) + end + + private + def plugin_path + "#{@destination_root}/bukkits" + end + + def run_test_command(arguments) + Dir.chdir(plugin_path) { `bin/test #{arguments}` } + end + + def create_test_file(name, pass: true) + plugin_file "test/#{name}_test.rb", <<-RUBY + require 'test_helper' + + class #{name.camelize}Test < ActiveSupport::TestCase + def test_truth + puts "#{name.camelize}Test" + assert #{pass}, 'wups!' + end + end + RUBY + end + + def plugin_file(path, contents, mode: 'w') + FileUtils.mkdir_p File.dirname("#{plugin_path}/#{path}") + File.open("#{plugin_path}/#{path}", mode) do |f| + f.puts contents + end + end +end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 77372fb514..acb78ec888 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -28,9 +28,22 @@ module SharedGeneratorTests def assert_generates_with_bundler(options = {}) generator([destination_root], options) - generator.expects(:bundle_command).with('install').once - generator.stubs(:bundle_command).with('exec spring binstub --all') - quietly { generator.invoke_all } + + command_check = -> command do + @install_called ||= 0 + + case command + when 'install' + @install_called += 1 + assert_equal 1, @install_called, "install expected to be called once, but was called #{@install_called} times" + when 'exec spring binstub --all' + # Called when running tests with spring, let through unscathed. + end + end + + generator.stub :bundle_command, command_check do + quietly { generator.invoke_all } + end end def test_generation_runs_bundle_install @@ -91,8 +104,14 @@ module SharedGeneratorTests template = %{ say "It works!" } template.instance_eval "def read; self; end" # Make the string respond to read - generator([destination_root], template: path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) - quietly { assert_match(/It works!/, capture(:stdout) { generator.invoke_all }) } + check_open = -> *args do + assert_equal [ path, 'Accept' => 'application/x-thor-template' ], args + template + end + + generator([destination_root], template: path).stub(:open, check_open, template) do + quietly { assert_match(/It works!/, capture(:stdout) { generator.invoke_all }) } + end end def test_dev_option @@ -107,18 +126,19 @@ module SharedGeneratorTests end def test_skip_gemfile - generator([destination_root], skip_gemfile: true).expects(:bundle_command).never - quietly { generator.invoke_all } - assert_no_file 'Gemfile' + assert_not_called(generator([destination_root], skip_gemfile: true), :bundle_command) do + quietly { generator.invoke_all } + assert_no_file 'Gemfile' + end end def test_skip_bundle - generator([destination_root], skip_bundle: true).expects(:bundle_command).never - quietly { generator.invoke_all } - - # skip_bundle is only about running bundle install, ensure the Gemfile is still - # generated. - assert_file 'Gemfile' + 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 diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 65d8a55421..df3c2ca66d 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -51,7 +51,12 @@ module TestHelpers old_env = ENV["RAILS_ENV"] @app ||= begin ENV["RAILS_ENV"] = env - require "#{app_path}/config/environment" + + # FIXME: shush Sass warning spam, not relevant to testing Railties + Kernel.silence_warnings do + require "#{app_path}/config/environment" + end + Rails.application end ensure @@ -159,19 +164,20 @@ module TestHelpers require "rails" require "action_controller/railtie" require "action_view/railtie" + require 'action_dispatch/middleware/flash' - app = Class.new(Rails::Application) - 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 - app.config.log_level = :info + @app = Class.new(Rails::Application) + @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 + @app.config.log_level = :info - yield app if block_given? - app.initialize! + yield @app if block_given? + @app.initialize! - app.routes.draw do + @app.routes.draw do get "/" => "omg#index" end @@ -296,7 +302,10 @@ module TestHelpers end def boot_rails - require File.expand_path('../../../../load_paths', __FILE__) + # FIXME: shush Sass warning spam, not relevant to testing Railties + Kernel.silence_warnings do + require File.expand_path('../../../../load_paths', __FILE__) + end end end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 79bd7a8241..24386de82a 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -1205,7 +1205,7 @@ YAML test "engine can be properly mounted at root" do add_to_config("config.action_dispatch.show_exceptions = false") - add_to_config("config.serve_static_files = false") + add_to_config("config.public_file_server.enabled = false") @plugin.write "lib/bukkits.rb", <<-RUBY module Bukkits @@ -1304,6 +1304,55 @@ YAML assert_equal '/foo/bukkits/bukkit', last_response.body end + test "paths are properly generated when application is mounted at sub-path and relative_url_root is set" do + add_to_config "config.relative_url_root = '/foo'" + + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + isolate_namespace Bukkits + end + end + RUBY + + app_file "app/controllers/bar_controller.rb", <<-RUBY + class BarController < ApplicationController + def index + render text: bukkits.bukkit_path + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + get '/bar' => 'bar#index', :as => 'bar' + mount Bukkits::Engine => "/bukkits", :as => "bukkits" + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + get '/bukkit' => 'bukkit#index' + end + RUBY + + @plugin.write "app/controllers/bukkits/bukkit_controller.rb", <<-RUBY + class Bukkits::BukkitController < ActionController::Base + def index + render text: main_app.bar_path + end + end + RUBY + + boot_rails + + get("/bukkits/bukkit", {}, {'SCRIPT_NAME' => '/foo'}) + assert_equal '/foo/bar', last_response.body + + get("/bar", {}, {'SCRIPT_NAME' => '/foo'}) + assert_equal '/foo/bukkits/bukkit', last_response.body + end + private def app Rails.application diff --git a/railties/test/test_unit/reporter_test.rb b/railties/test/test_unit/reporter_test.rb index 3066ba82d6..e517d8dd0b 100644 --- a/railties/test/test_unit/reporter_test.rb +++ b/railties/test/test_unit/reporter_test.rb @@ -8,14 +8,14 @@ class TestUnitReporterTest < ActiveSupport::TestCase setup do @output = StringIO.new - @reporter = Rails::TestUnitReporter.new @output + @reporter = Rails::TestUnitReporter.new @output, output_inline: true end test "prints rerun snippet to run a single failed test" do @reporter.record(failed_test) @reporter.report - assert_match %r{^bin/rails test .*test/test_unit/reporter_test.rb:6$}, @output.string + assert_match %r{^bin/rails test .*test/test_unit/reporter_test.rb:\d+$}, @output.string assert_rerun_snippet_count 1 end @@ -51,12 +51,65 @@ class TestUnitReporterTest < ActiveSupport::TestCase @reporter.record(failed_test) @reporter.report - assert_match %r{^bin/test .*test/test_unit/reporter_test.rb:6$}, @output.string + assert_match %r{^bin/test .*test/test_unit/reporter_test.rb:\d+$}, @output.string ensure Rails::TestUnitReporter.executable = original_executable end end + test "outputs failures inline" do + @reporter.record(failed_test) + @reporter.report + + assert_match %r{\A\n\nboo\n\nbin/rails test .*test/test_unit/reporter_test.rb:\d+\n\n\z}, @output.string + end + + test "outputs errors inline" do + @reporter.record(errored_test) + @reporter.report + + assert_match %r{\A\n\nArgumentError: wups\n No backtrace\n\nbin/rails test .*test/test_unit/reporter_test.rb:6\n\n\z}, @output.string + end + + test "outputs skipped tests inline if verbose" do + verbose = Rails::TestUnitReporter.new @output, verbose: true, output_inline: true + verbose.record(skipped_test) + verbose.report + + assert_match %r{\A\n\nskipchurches, misstemples\n\nbin/rails test .*test/test_unit/reporter_test.rb:\d+\n\n\z}, @output.string + end + + test "does not output rerun snippets after run" do + @reporter.record(failed_test) + @reporter.report + + assert_no_match 'Failed tests:', @output.string + end + + test "fail fast interrupts run on failure" do + fail_fast = Rails::TestUnitReporter.new @output, fail_fast: true + interrupt_raised = false + + # Minitest passes through Interrupt, catch it manually. + begin + fail_fast.record(failed_test) + rescue Interrupt + interrupt_raised = true + ensure + assert interrupt_raised, 'Expected Interrupt to be raised.' + end + end + + test "fail fast does not interrupt run errors or skips" do + fail_fast = Rails::TestUnitReporter.new @output, fail_fast: true + + fail_fast.record(errored_test) + assert_no_match 'Failed tests:', @output.string + + fail_fast.record(skipped_test) + assert_no_match 'Failed tests:', @output.string + end + private def assert_rerun_snippet_count(snippet_count) assert_equal snippet_count, @output.string.scan(%r{^bin/rails test }).size @@ -72,6 +125,12 @@ class TestUnitReporterTest < ActiveSupport::TestCase ft end + def errored_test + et = ExampleTest.new(:woot) + et.failures << Minitest::UnexpectedError.new(ArgumentError.new("wups")) + et + end + def passing_test ExampleTest.new(:woot) end @@ -79,7 +138,7 @@ class TestUnitReporterTest < ActiveSupport::TestCase def skipped_test st = ExampleTest.new(:woot) st.failures << begin - raise Minitest::Skip + raise Minitest::Skip, "skipchurches, misstemples" rescue Minitest::Assertion => e e end |