aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG.md67
-rw-r--r--railties/Rakefile2
-rw-r--r--railties/lib/rails/application.rb8
-rw-r--r--railties/lib/rails/commands.rb11
-rw-r--r--railties/lib/rails/commands/console.rb4
-rw-r--r--railties/lib/rails/commands/server.rb6
-rw-r--r--railties/lib/rails/commands/test_runner.rb146
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb9
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/index.html.erb4
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/show.html.erb2
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb4
-rw-r--r--railties/lib/rails/generators/named_base.rb1
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config.ru2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/test_helper.rb7
-rw-r--r--railties/lib/rails/generators/test_unit/model/templates/fixtures.yml16
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb6
-rw-r--r--railties/lib/rails/test_unit/testing.rake79
-rw-r--r--railties/test/application/console_test.rb80
-rw-r--r--railties/test/application/rake_test.rb23
-rw-r--r--railties/test/application/test_runner_test.rb312
-rw-r--r--railties/test/commands/console_test.rb21
-rw-r--r--railties/test/generators/scaffold_generator_test.rb41
-rw-r--r--railties/test/railties/engine_test.rb2
26 files changed, 742 insertions, 119 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 4f7cb8254f..60a823de15 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,21 +1,66 @@
## Rails 4.0.0 (unreleased) ##
+* Add support for generate scaffold password:digest
+
+ * adds password_digest attribute to the migration
+ * adds has_secure_password to the model
+ * adds password and password_confirmation password_fields to _form.html
+ * omits password from index.html and show.html
+ * adds password and password_confirmation to the controller
+ * adds unencrypted password and password_confirmation to the controller test
+ * adds encrypted password_digest to the fixture
+
+ *Sam Ruby*
+
+* Rails now generates a `test/test_helper.rb` file with `fixtures :all` commented out by default,
+ since we don't want to force loading all fixtures for user when a single test is run. However,
+ fixtures are still going to be loaded automatically for test suites.
+
+ To force all fixtures to be create in your database, use `rails test -f` to run your test.
+
+ *Prem Sichanugrist*
+
+* Add `rails test` command for running tests
+
+ To run all tests:
+
+ $ rails test
+
+ To run a test suite
+
+ $ rails test [models,helpers,units,controllers,mailers,...]
+
+ To run a selected test file(s):
+
+ $ rails test test/unit/foo_test.rb [test/unit/bar_test.rb ...]
+
+ To run a single test from a test file
+
+ $ rails test test/unit/foo_test.rb -n test_the_truth
+
+ For more information, see `rails test --help`.
+
+ This command will eventually replace `rake test:*` and `rake test` tasks.
+
+ *Prem Sichanugrist and Chris Toomey*
+
+* Improve service pages with new layout (404, etc). *Stanislav Sobolev*
+
## Rails 4.0.0.beta1 (February 25, 2013) ##
-* Change Service pages(404, etc). *Stanislav Sobolev*
* Improve `rake stats` for JavaScript and CoffeeScript: ignore block comments
and calculates number of functions.
*Hendy Tanata*
-* Ability to use a custom builder by passing `--builder` (or `-b`) has been removed. Consider
- using application template instead. See this guide for more detail:
+* Ability to use a custom builder by passing `--builder` (or `-b`) has been removed.
+ Consider using application template instead. See this guide for more detail:
http://guides.rubyonrails.org/rails_application_templates.html
*Prem Sichanugrist*
-* fix rake db:* tasks to work with DATABASE_URL and without config/database.yml
+* Fix `rake db:*` tasks to work with `DATABASE_URL` and without `config/database.yml`.
*Terence Lee*
@@ -39,13 +84,13 @@
*Amparo Luna*
* Fixes database.yml when creating a new rails application with '.'
- Fix #8304
+ Fixes #8304.
*Jeremy W. Rowe*
* Restore Rails::Engine::Railties#engines with deprecation to ensure
compatibility with gems such as Thinking Sphinx
- Fix #8551
+ Fixes #8551.
*Tim Raymond*
@@ -119,7 +164,7 @@
* Environment name can be a start substring of the default environment names
(production, development, test). For example: tes, pro, prod, dev, devel.
- Fix #8628.
+ Fixes #8628.
*Mykola Kyryk*
@@ -129,7 +174,7 @@
* Quote column names in generates fixture files. This prevents
conflicts with reserved YAML keywords such as 'yes' and 'no'
- Fix #8612.
+ Fixes #8612.
*Yves Senn*
@@ -162,19 +207,19 @@
* Add `db` to list of folders included by `rake notes` and `rake notes:custom`. *Antonio Cangiano*
* Engines with a dummy app include the rake tasks of dependencies in the app namespace.
- Fix #8229
+ Fixes #8229.
*Yves Senn*
* Add `sqlserver.yml` template file to satisfy `-d sqlserver` being passed to `rails new`.
- Fix #6882
+ Fixes #6882.
*Robert Nesius*
* Rake test:uncommitted finds git directory in ancestors *Nicolas Despres*
* Add dummy app Rake tasks when `--skip-test-unit` and `--dummy-path` is passed to the plugin generator.
- Fix #8121
+ Fixes #8121.
*Yves Senn*
diff --git a/railties/Rakefile b/railties/Rakefile
index 8576275aea..eb068fc526 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -6,6 +6,8 @@ require 'rbconfig'
task :default => :test
+
+desc "Run all unit tests"
task :test => 'test:isolated'
namespace :test do
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 25cc36ff5d..2417bdca21 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -46,10 +46,10 @@ module Rails
# 6) Run config.before_initialize callbacks
# 7) Run Railtie#initializer defined by railties, engines and application.
# One by one, each engine sets up its load paths, routes and runs its config/initializers/* files.
- # 9) Custom Railtie#initializers added by railties, engines and applications are executed
- # 10) Build the middleware stack and run to_prepare callbacks
- # 11) Run config.before_eager_load and eager_load! if eager_load is true
- # 12) Run config.after_initialize callbacks
+ # 8) Custom Railtie#initializers added by railties, engines and applications are executed
+ # 9) Build the middleware stack and run to_prepare callbacks
+ # 10) Run config.before_eager_load and eager_load! if eager_load is true
+ # 11) Run config.after_initialize callbacks
#
class Application < Engine
autoload :Bootstrap, 'rails/application/bootstrap'
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index aacde52cfc..41d3722c18 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -5,6 +5,7 @@ aliases = {
"d" => "destroy",
"c" => "console",
"s" => "server",
+ "t" => "test",
"db" => "dbconsole",
"r" => "runner"
}
@@ -16,6 +17,7 @@ The most common rails commands are:
generate Generate new code (short-cut alias: "g")
console Start the Rails console (short-cut alias: "c")
server Start the Rails server (short-cut alias: "s")
+ test Running the test file (short-cut alias: "t")
dbconsole Start a console for the database specified in config/database.yml
(short-cut alias: "db")
new Create a new Rails application. "rails new my_app" creates a
@@ -78,6 +80,15 @@ when 'server'
server.start
end
+when 'test'
+ $LOAD_PATH.unshift("./test")
+ require 'rails/commands/test_runner'
+ options = Rails::TestRunner.parse_arguments(ARGV)
+ ENV['RAILS_ENV'] ||= options[:environment] || 'test'
+
+ require APP_PATH
+ Rails::TestRunner.start(ARGV, options)
+
when 'dbconsole'
require 'rails/commands/dbconsole'
Rails::DBConsole.start
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index 86ab1aabbf..96229bb4f6 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -46,7 +46,10 @@ module Rails
def initialize(app, options={})
@app = app
@options = options
+
+ app.sandbox = sandbox?
app.load_console
+
@console = app.config.console || IRB
end
@@ -71,7 +74,6 @@ module Rails
end
def start
- app.sandbox = sandbox?
require_debugger if debugger?
set_environment! if environment?
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index cdb29a8156..876d457359 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -42,8 +42,12 @@ module Rails
set_environment
end
+ # TODO: this is no longer required but we keep it for the moment to support older config.ru files.
def app
- @app ||= super.respond_to?(:to_app) ? super.to_app : super
+ @app ||= begin
+ app = super
+ app.respond_to?(:to_app) ? app.to_app : app
+ end
end
def opt_parser
diff --git a/railties/lib/rails/commands/test_runner.rb b/railties/lib/rails/commands/test_runner.rb
new file mode 100644
index 0000000000..d8857bd183
--- /dev/null
+++ b/railties/lib/rails/commands/test_runner.rb
@@ -0,0 +1,146 @@
+require 'optparse'
+require 'minitest/unit'
+
+module Rails
+ # Handles all logic behind +rails test+ command.
+ class TestRunner
+ class << self
+ # Creates a new +TestRunner+ object with an array of test files to run
+ # based on the arguments. When no arguments are provided, it runs all test
+ # files. When a suite argument is provided, it runs only the test files in
+ # that suite. Otherwise, it runs the specified test file(s).
+ def start(files, options = {})
+ original_fixtures_options = options.delete(:fixtures)
+ options[:fixtures] = true
+
+ case files.first
+ when nil
+ new(Dir['test/**/*_test.rb'], options).run
+ when 'models'
+ new(Dir['test/models/**/*_test.rb'], options).run
+ when 'helpers'
+ new(Dir['test/helpers/**/*_test.rb'], options).run
+ when 'units'
+ new(Dir['test/{models,helpers,unit}/**/*_test.rb'], options).run
+ when 'controllers'
+ new(Dir['test/controllers/**/*_test.rb'], options).run
+ when 'mailers'
+ new(Dir['test/mailers/**/*_test.rb'], options).run
+ when 'functionals'
+ new(Dir['test/{controllers,mailers,functional}/**/*_test.rb'], options).run
+ when 'integration'
+ new(Dir['test/integration/**/*_test.rb'], options).run
+ else
+ options[:fixtures] = original_fixtures_options
+ new(files, options).run
+ end
+ end
+
+ # Parses arguments and sets them as option flags
+ def parse_arguments(arguments)
+ options = {}
+ orig_arguments = arguments.dup
+
+ OptionParser.new do |opts|
+ opts.banner = "Usage: rails test [path to test file(s) or test suite]"
+
+ opts.separator ""
+ opts.separator "Run a specific test file(s) or a test suite, under Rails'"
+ opts.separator "environment. If the file name(s) or suit name is omitted,"
+ opts.separator "Rails will run all tests."
+ opts.separator ""
+ opts.separator "Specific options:"
+
+ opts.on '-h', '--help', 'Display this help.' do
+ puts opts
+ exit
+ end
+
+ opts.on '-e', '--environment NAME', String, 'Specifies the environment to run this test under' do |e|
+ options[:environment] = e
+ end
+
+ opts.on '-f', '--fixtures', 'Load fixtures in test/fixtures/ before running the tests' do
+ options[:fixtures] = true
+ end
+
+ opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
+ options[:seed] = m.to_i
+ end
+
+ opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
+ options[:verbose] = true
+ end
+
+ opts.on '-n', '--name PATTERN', "Filter test names on pattern (e.g. /foo/)" do |n|
+ options[:filter] = n
+ end
+
+ opts.separator ""
+ opts.separator "Support types of test suites:"
+ opts.separator "-------------------------------------------------------------"
+ opts.separator "* models (test/models/**/*)"
+ opts.separator "* helpers (test/helpers/**/*)"
+ opts.separator "* units (test/{models,helpers,unit}/**/*"
+ opts.separator "* controllers (test/controllers/**/*)"
+ opts.separator "* mailers (test/mailers/**/*)"
+ opts.separator "* functionals (test/{controllers,mailers,functional}/**/*)"
+ opts.separator "* integration (test/integration/**/*)"
+ opts.separator "-------------------------------------------------------------"
+
+ opts.parse! arguments
+ orig_arguments -= arguments
+ end
+ options
+ end
+ end
+
+ # Creates a new +TestRunner+ object with a list of test file paths.
+ def initialize(files, options)
+ @files = files
+
+ Rails.application.load_tasks
+ Rake::Task['db:test:load'].invoke
+
+ if options.delete(:fixtures)
+ if defined?(ActiveRecord::Base)
+ ActiveSupport::TestCase.send :include, ActiveRecord::TestFixtures
+ ActiveSupport::TestCase.fixture_path = "#{Rails.root}/test/fixtures/"
+ ActiveSupport::TestCase.fixtures :all
+ end
+ end
+
+ MiniTest::Unit.runner.options = options
+ MiniTest::Unit.output = SilentUntilSyncStream.new(MiniTest::Unit.output)
+ end
+
+ # Runs test files by evaluating each of them.
+ def run
+ @files.each { |filename| load(filename) }
+ end
+
+ # A null stream object which ignores everything until +sync+ has been set
+ # to true. This is only used to silence unnecessary output from MiniTest,
+ # as MiniTest calls +output.sync = true+ right before it outputs the first
+ # test result.
+ class SilentUntilSyncStream < File
+ # Creates a +SilentUntilSyncStream+ object by giving it a target stream
+ # object that will be assigned to +MiniTest::Unit.output+ after +sync+ is
+ # set to true.
+ def initialize(target_stream)
+ @target_stream = target_stream
+ super(File::NULL, 'w')
+ end
+
+ # Swaps +MiniTest::Unit.output+ to another stream when +sync+ is true.
+ def sync=(sync)
+ if sync
+ @target_stream.sync = true
+ MiniTest::Unit.output = @target_stream
+ end
+
+ super
+ end
+ end
+ end
+end
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 32546936e3..85a1b01cc6 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb
@@ -13,8 +13,17 @@
<% attributes.each do |attribute| -%>
<div class="field">
+<% if attribute.password_digest? -%>
+ <%%= f.label :password %><br />
+ <%%= f.password_field :password %>
+ </div>
+ <div>
+ <%%= f.label :password_confirmation %><br />
+ <%%= f.password_field :password_confirmation %>
+<% else -%>
<%%= f.label :<%= attribute.name %> %><br />
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
+<% end -%>
</div>
<% end -%>
<div class="actions">
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
index 90d8db1df5..d2fd99fdcb 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
@@ -3,7 +3,7 @@
<table>
<thead>
<tr>
-<% attributes.each do |attribute| -%>
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
<th><%= attribute.human_name %></th>
<% end -%>
<th></th>
@@ -15,7 +15,7 @@
<tbody>
<%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
<tr>
-<% attributes.each do |attribute| -%>
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
<td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
<% end -%>
<td><%%= link_to 'Show', <%= singular_table_name %> %></td>
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
index daae72270f..5e634153be 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb
@@ -1,6 +1,6 @@
<p id="notice"><%%= notice %></p>
-<% attributes.each do |attribute| -%>
+<% attributes.reject(&:password_digest?).each do |attribute| -%>
<p>
<strong><%= attribute.human_name %>:</strong>
<%%= @<%= singular_table_name %>.<%= attribute.name %> %>
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index 4ae8756ed0..5e2784c4b0 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -130,6 +130,10 @@ module Rails
@has_uniq_index
end
+ def password_digest?
+ name == 'password' && type == :digest
+ end
+
def inject_options
"".tap { |s| @attr_options.each { |k,v| s << ", #{k}: #{v.inspect}" } }
end
diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb
index 9965db98de..8b4f52bb3b 100644
--- a/railties/lib/rails/generators/named_base.rb
+++ b/railties/lib/rails/generators/named_base.rb
@@ -163,6 +163,7 @@ module Rails
def attributes_names
@attributes_names ||= attributes.each_with_object([]) do |a, names|
names << a.column_name
+ names << 'password_confirmation' if a.password_digest?
names << "#{a.name}_type" if a.polymorphic?
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index b5db3d2187..f6bd107eba 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -23,5 +23,5 @@ gem 'jbuilder', '~> 1.0.1'
<% unless defined?(JRUBY_VERSION) -%>
# To use debugger
-# gem 'debugger'
+# gem 'debugger', group: [:development, :test]
<% end -%>
diff --git a/railties/lib/rails/generators/rails/app/templates/config.ru b/railties/lib/rails/generators/rails/app/templates/config.ru
index fcfbc6b07a..5bc2a619e8 100644
--- a/railties/lib/rails/generators/rails/app/templates/config.ru
+++ b/railties/lib/rails/generators/rails/app/templates/config.ru
@@ -1,4 +1,4 @@
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
-run <%= app_const %>
+run Rails.application
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 d0e62d09cc..8b64881dbc 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
@@ -26,6 +26,8 @@
<%- unless options.skip_sprockets? -%>
# Debug mode disables concatenation and preprocessing of assets.
+ # This option may cause significant delays in view rendering with a large
+ # number of complex assets.
config.assets.debug = true
<%- end -%>
end
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 5669fe6d64..c40eef145f 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
@@ -24,10 +24,10 @@
<%- unless options.skip_sprockets? -%>
# Compress JavaScripts and CSS.
- config.assets.js_compressor = :uglifier
+ config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
- # Whether to fallback to assets pipeline if a precompiled asset is missed.
+ # Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Generate digests for assets URLs.
diff --git a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb
index 9afda2d0df..ca40914d3b 100644
--- a/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb
+++ b/railties/lib/rails/generators/rails/app/templates/test/test_helper.rb
@@ -1,4 +1,4 @@
-ENV["RAILS_ENV"] = "test"
+ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
@@ -6,11 +6,12 @@ class ActiveSupport::TestCase
<% unless options[:skip_active_record] -%>
ActiveRecord::Migration.check_pending!
- # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
+ # Uncomment the `fixtures :all` line below to setup all fixtures in test/fixtures/*.yml
+ # for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
- fixtures :all
+ # fixtures :all
<% end -%>
# Add more helper methods to be used by all tests here...
diff --git a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml
index c9d505c84a..90a92e6982 100644
--- a/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml
+++ b/railties/lib/rails/generators/test_unit/model/templates/fixtures.yml
@@ -1,22 +1,20 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
-
<% unless attributes.empty? -%>
-one:
+<% %w(one two).each do |name| %>
+<%= name %>:
<% attributes.each do |attribute| -%>
+ <%- if attribute.password_digest? -%>
+ password_digest: <%%= BCrypt::Password.create('secret') %>
+ <%- else -%>
<%= yaml_key_value(attribute.column_name, attribute.default) %>
- <%- if attribute.polymorphic? -%>
- <%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %>
<%- end -%>
-<% end -%>
-
-two:
-<% attributes.each do |attribute| -%>
- <%= yaml_key_value(attribute.column_name, attribute.default) %>
<%- if attribute.polymorphic? -%>
<%= yaml_key_value("#{attribute.name}_type", attribute.human_name) %>
<%- end -%>
<% end -%>
+<% end -%>
<% else -%>
+
# This model initially had no columns defined. If you add columns to the
# model remove the '{}' from the fixture names and add the columns immediately
# below each fixture, per the syntax in the comments below
diff --git a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
index 8f3ecaadea..2e1f55f2a6 100644
--- a/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb
@@ -21,7 +21,11 @@ module TestUnit # :nodoc:
return if attributes_names.empty?
attributes_names.map do |name|
- "#{name}: @#{singular_table_name}.#{name}"
+ if %w(password password_confirmation).include?(name) && attributes.any?(&:password_digest?)
+ "#{name}: 'secret'"
+ else
+ "#{name}: @#{singular_table_name}.#{name}"
+ end
end.sort.join(', ')
end
end
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index 44485d9b14..3c247f32c0 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -1,6 +1,7 @@
require 'rbconfig'
require 'rake/testtask'
require 'rails/test_unit/sub_test_task'
+require 'active_support/deprecation'
TEST_CHANGES_SINCE = Time.now - 600
@@ -47,7 +48,11 @@ task default: :test
desc 'Runs test:units, test:functionals, test:integration together'
task :test do
- Rake::Task[ENV['TEST'] ? 'test:single' : 'test:run'].invoke
+ if ENV['TEST']
+ exec "bundle exec rails test #{ENV['TEST'].inspect}"
+ else
+ exec 'bundle exec rails test'
+ end
end
namespace :test do
@@ -56,19 +61,8 @@ namespace :test do
end
task :run do
- errors = %w(test:units test:functionals test:integration).collect do |task|
- begin
- Rake::Task[task].invoke
- nil
- rescue => e
- { task: task, exception: e }
- end
- end.compact
-
- if errors.any?
- puts errors.map { |e| "Errors running #{e[:task]}! #{e[:exception].inspect}" }.join("\n")
- abort
- end
+ ActiveSupport::Deprecation.warn "`rake test:run` is deprecated. Please use `rails test`."
+ exec 'bundle exec rails test'
end
# Inspired by: http://ngauthier.com/2012/02/quick-tests-with-bash.html
@@ -83,7 +77,12 @@ namespace :test do
task :db => %w[db:test:prepare test:all]
end
- Rake::TestTask.new(recent: "test:prepare") do |t|
+ # Display deprecation message
+ task :deprecated do
+ ActiveSupport::Deprecation.warn "`rake #{ARGV.first}` is deprecated with no replacement."
+ end
+
+ Rake::TestTask.new(recent: ["test:deprecated", "test:prepare"]) do |t|
since = TEST_CHANGES_SINCE
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
recent_tests('app/models/**/*.rb', 'test/models', since) +
@@ -94,9 +93,9 @@ namespace :test do
t.libs << 'test'
t.test_files = touched.uniq
end
- Rake::Task['test:recent'].comment = "Test recent changes"
+ Rake::Task['test:recent'].comment = "Deprecated; Test recent changes"
- Rake::TestTask.new(uncommitted: "test:prepare") do |t|
+ Rake::TestTask.new(uncommitted: ["test:deprecated", "test:prepare"]) do |t|
def t.file_list
if File.directory?(".svn")
changed_since_checkin = silence_stderr { `svn status` }.split.map { |path| path.chomp[7 .. -1] }
@@ -118,44 +117,20 @@ namespace :test do
t.libs << 'test'
end
- Rake::Task['test:uncommitted'].comment = "Test changes since last checkin (only Subversion and Git)"
-
- Rake::TestTask.new(single: "test:prepare") do |t|
- t.libs << "test"
- end
-
- Rails::SubTestTask.new(models: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/models/**/*_test.rb'
- end
-
- Rails::SubTestTask.new(helpers: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/helpers/**/*_test.rb'
- end
+ Rake::Task['test:uncommitted'].comment = "Deprecated; Test changes since last checkin (only Subversion and Git)"
- Rails::SubTestTask.new(units: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/{models,helpers,unit}/**/*_test.rb'
+ desc "Deprecated; Please use `rails test \"#{ENV['TEST']}\"`"
+ task :single do
+ ActiveSupport::Deprecation.warn "`rake test:single` is deprecated. Please use `rails test \"#{ENV['TEST']}\"`."
+ exec "bundle exec rails test #{test_suit_name}"
end
- Rails::SubTestTask.new(controllers: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/controllers/**/*_test.rb'
- end
+ [:models, :helpers, :units, :controllers, :functionals, :integration].each do |test_suit_name|
+ desc "Deprecated; Please use `rails test #{test_suit_name}`"
+ task test_suit_name do
+ ActiveSupport::Deprecation.warn "`rake test:#{test_suit_name}` is deprecated. Please use `rails test #{test_suit_name}`."
- Rails::SubTestTask.new(mailers: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/mailers/**/*_test.rb'
- end
-
- Rails::SubTestTask.new(functionals: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/{controllers,mailers,functional}/**/*_test.rb'
- end
-
- Rails::SubTestTask.new(integration: "test:prepare") do |t|
- t.libs << "test"
- t.pattern = 'test/integration/**/*_test.rb'
+ exec "bundle exec rails test #{test_suit_name}"
+ end
end
end
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index 3cb3643e3a..af495bb450 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -81,18 +81,82 @@ class ConsoleTest < ActiveSupport::TestCase
assert_equal 'Once upon a time in a world...',
helper.truncate('Once upon a time in a world far far away')
end
+end
+
+begin
+ require "pty"
+rescue LoadError
+end
+
+class FullStackConsoleTest < ActiveSupport::TestCase
+ def setup
+ skip "PTY unavailable" unless defined?(PTY) && PTY.respond_to?(:open)
+
+ build_app
+ app_file 'app/models/post.rb', <<-CODE
+ class Post < ActiveRecord::Base
+ end
+ CODE
+ system "#{app_path}/bin/rails runner 'Post.connection.create_table :posts'"
+
+ @master, @slave = PTY.open
+ end
+
+ def teardown
+ teardown_app
+ end
- def test_with_sandbox
- require 'rails/all'
- value = false
+ def assert_output(expected, timeout = 1)
+ timeout = Time.now + timeout
- Class.new(Rails::Railtie) do
- console do |app|
- value = app.sandbox?
+ output = ""
+ until output.include?(expected) || Time.now > timeout
+ if IO.select([@master], [], [], 0.1)
+ output << @master.read(1)
end
end
- load_environment(true)
- assert value
+ assert output.include?(expected), "#{expected.inspect} expected, but got:\n\n#{output}"
+ end
+
+ def write_prompt(command, expected_output = nil)
+ @master.puts command
+ assert_output command
+ assert_output expected_output if expected_output
+ assert_output "> "
+ end
+
+ def kill(pid)
+ Process.kill('QUIT', pid)
+ Process.wait(pid)
+ rescue Errno::ESRCH
+ end
+
+ def spawn_console
+ pid = Process.spawn(
+ "#{app_path}/bin/rails console --sandbox",
+ in: @slave, out: @slave, err: @slave
+ )
+
+ assert_output "> ", 30
+ pid
+ end
+
+ def test_sandbox
+ pid = spawn_console
+
+ write_prompt "Post.count", "=> 0"
+ write_prompt "Post.create"
+ write_prompt "Post.count", "=> 1"
+
+ kill pid
+
+ pid = spawn_console
+
+ write_prompt "Post.count", "=> 0"
+ write_prompt "Post.transaction { Post.create; raise }"
+ write_prompt "Post.count", "=> 0"
+ ensure
+ kill pid if pid
end
end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index 09f2ad1209..a9e0e1bcb7 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -91,19 +91,9 @@ module ApplicationTests
raise 'models'
RUBY
- app_file "test/controllers/one_controller_test.rb", <<-RUBY
- raise 'controllers'
- RUBY
-
- app_file "test/integration/one_integration_test.rb", <<-RUBY
- raise 'integration'
- RUBY
-
silence_stderr do
output = Dir.chdir(app_path) { `rake test 2>&1` }
assert_match 'models', output
- assert_match 'controllers', output
- assert_match 'integration', output
end
end
@@ -135,6 +125,19 @@ module ApplicationTests
end
end
+ def test_rake_test_deprecation_messages
+ Dir.chdir(app_path){ `rails generate scaffold user name:string` }
+ Dir.chdir(app_path){ `rake db:migrate` }
+
+ %w(run recent uncommitted models helpers units controllers functionals integration).each do |test_suit_name|
+ output = Dir.chdir(app_path) { `rake test:#{test_suit_name} 2>&1` }
+ assert_match /DEPRECATION WARNING: `rake test:#{test_suit_name}` is deprecated/, output
+ end
+
+ assert_match /DEPRECATION WARNING: `rake test:single` is deprecated/,
+ Dir.chdir(app_path) { `rake test:single TEST=test/models/user_test.rb 2>&1` }
+ end
+
def test_rake_routes_calls_the_route_inspector
app_file "config/routes.rb", <<-RUBY
AppTemplate::Application.routes.draw do
diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb
new file mode 100644
index 0000000000..56ca3bc1a9
--- /dev/null
+++ b/railties/test/application/test_runner_test.rb
@@ -0,0 +1,312 @@
+require 'isolation/abstract_unit'
+require 'active_support/core_ext/string/strip'
+
+module ApplicationTests
+ class TestRunnerTest < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ ENV['RAILS_ENV'] = nil
+ create_schema
+ end
+
+ def teardown
+ teardown_app
+ end
+
+ def test_should_not_display_heading
+ create_test_file
+ run_test_command.tap do |output|
+ assert_no_match "Run options:", output
+ assert_no_match "Running tests:", output
+ end
+ end
+
+ def test_run_in_test_environment
+ app_file 'test/unit/env_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class EnvTest < ActiveSupport::TestCase
+ def test_env
+ puts "Current Environment: \#{Rails.env}"
+ end
+ end
+ RUBY
+
+ assert_match "Current Environment: test", run_test_command('test/unit/env_test.rb')
+ end
+
+ def test_run_shortcut
+ create_test_file :models, 'foo'
+ output = Dir.chdir(app_path) { `bundle exec rails t test/models/foo_test.rb` }
+ assert_match "1 tests, 1 assertions, 0 failures", output
+ end
+
+ def test_run_single_file
+ create_test_file :models, 'foo'
+ assert_match "1 tests, 1 assertions, 0 failures", run_test_command("test/models/foo_test.rb")
+ end
+
+ def test_run_multiple_files
+ create_test_file :models, 'foo'
+ create_test_file :models, 'bar'
+ assert_match "2 tests, 2 assertions, 0 failures", run_test_command("test/models/foo_test.rb test/models/bar_test.rb")
+ end
+
+ def test_run_file_with_syntax_error
+ app_file 'test/models/error_test.rb', <<-RUBY
+ require 'test_helper'
+ def; end
+ RUBY
+
+ error_stream = Tempfile.new('error')
+ redirect_stderr(error_stream) { run_test_command('test/models/error_test.rb') }
+ assert_match "SyntaxError", error_stream.read
+ end
+
+ def test_invoke_rake_db_test_load
+ app_file "lib/tasks/test.rake", <<-RUBY
+ task 'db:test:load' do
+ puts "Hello World"
+ end
+ RUBY
+ create_test_file
+ assert_match "Hello World", run_test_command
+ end
+
+ def test_run_models
+ create_test_file :models, 'foo'
+ create_test_file :models, 'bar'
+ create_test_file :controllers, 'foobar_controller'
+ run_test_command("models").tap do |output|
+ assert_match "FooTest", output
+ assert_match "BarTest", output
+ assert_match "2 tests, 2 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_helpers
+ create_test_file :helpers, 'foo_helper'
+ create_test_file :helpers, 'bar_helper'
+ create_test_file :controllers, 'foobar_controller'
+ run_test_command('helpers').tap do |output|
+ assert_match "FooHelperTest", output
+ assert_match "BarHelperTest", output
+ assert_match "2 tests, 2 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_units
+ create_test_file :models, 'foo'
+ create_test_file :helpers, 'bar_helper'
+ create_test_file :unit, 'baz_unit'
+ create_test_file :controllers, 'foobar_controller'
+ run_test_command('units').tap do |output|
+ assert_match "FooTest", output
+ assert_match "BarHelperTest", output
+ assert_match "BazUnitTest", output
+ assert_match "3 tests, 3 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_controllers
+ create_test_file :controllers, 'foo_controller'
+ create_test_file :controllers, 'bar_controller'
+ create_test_file :models, 'foo'
+ run_test_command('controllers').tap do |output|
+ assert_match "FooControllerTest", output
+ assert_match "BarControllerTest", output
+ assert_match "2 tests, 2 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_mailers
+ create_test_file :mailers, 'foo_mailer'
+ create_test_file :mailers, 'bar_mailer'
+ create_test_file :models, 'foo'
+ run_test_command('mailers').tap do |output|
+ assert_match "FooMailerTest", output
+ assert_match "BarMailerTest", output
+ assert_match "2 tests, 2 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_functionals
+ create_test_file :mailers, 'foo_mailer'
+ create_test_file :controllers, 'bar_controller'
+ create_test_file :functional, 'baz_functional'
+ create_test_file :models, 'foo'
+ run_test_command('functionals').tap do |output|
+ assert_match "FooMailerTest", output
+ assert_match "BarControllerTest", output
+ assert_match "BazFunctionalTest", output
+ assert_match "3 tests, 3 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_integration
+ create_test_file :integration, 'foo_integration'
+ create_test_file :models, 'foo'
+ run_test_command('integration').tap do |output|
+ assert_match "FooIntegration", output
+ assert_match "1 tests, 1 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_all_suites
+ suites = [:models, :helpers, :unit, :controllers, :mailers, :functional, :integration]
+ suites.each { |suite| create_test_file suite, "foo_#{suite}" }
+ run_test_command('') .tap do |output|
+ suites.each { |suite| assert_match "Foo#{suite.to_s.camelize}Test", output }
+ assert_match "7 tests, 7 assertions, 0 failures", output
+ end
+ end
+
+ def test_run_named_test
+ app_file 'test/unit/chu_2_koi_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class Chu2KoiTest < ActiveSupport::TestCase
+ def test_rikka
+ puts 'Rikka'
+ end
+
+ def test_sanae
+ puts 'Sanae'
+ end
+ end
+ RUBY
+
+ run_test_command('test/unit/chu_2_koi_test.rb -n test_rikka').tap do |output|
+ assert_match "Rikka", output
+ assert_no_match "Sanae", output
+ end
+ end
+
+ def test_not_load_fixtures_when_running_single_test
+ create_model_with_fixture
+ create_fixture_test :models, 'user'
+ assert_match "0 users", run_test_command('test/models/user_test.rb')
+ assert_match "3 users", run_test_command('test/models/user_test.rb -f')
+ end
+
+ def test_load_fixtures_when_running_test_suites
+ create_model_with_fixture
+ suites = [:models, :helpers, [:units, :unit], :controllers, :mailers,
+ [:functionals, :functional], :integration]
+
+ suites.each do |suite, directory|
+ directory ||= suite
+ create_fixture_test directory
+ assert_match "3 users", run_test_command(suite)
+ Dir.chdir(app_path) { FileUtils.rm_f "test/#{directory}" }
+ end
+ end
+
+ def test_run_different_environment_using_env_var
+ app_file 'test/unit/env_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class EnvTest < ActiveSupport::TestCase
+ def test_env
+ puts Rails.env
+ end
+ end
+ RUBY
+
+ ENV['RAILS_ENV'] = 'development'
+ assert_match "development", run_test_command('test/unit/env_test.rb')
+ end
+
+ def test_run_different_environment_using_e_tag
+ app_file 'test/unit/env_test.rb', <<-RUBY
+ require 'test_helper'
+
+ class EnvTest < ActiveSupport::TestCase
+ def test_env
+ puts Rails.env
+ end
+ end
+ RUBY
+
+ assert_match "development", run_test_command('-e development test/unit/env_test.rb')
+ end
+
+ def test_generated_scaffold_works_with_rails_test
+ create_scaffold
+ assert_match "0 failures, 0 errors, 0 skips", run_test_command('')
+ end
+
+ private
+ def run_test_command(arguments = 'test/unit/test_test.rb')
+ Dir.chdir(app_path) { `bundle exec rails test #{arguments}` }
+ end
+
+ def create_model_with_fixture
+ script 'generate model user name:string'
+
+ app_file 'test/fixtures/users.yml', <<-YAML.strip_heredoc
+ vampire:
+ id: 1
+ name: Koyomi Araragi
+ crab:
+ id: 2
+ name: Senjougahara Hitagi
+ cat:
+ id: 3
+ name: Tsubasa Hanekawa
+ YAML
+
+ run_migration
+ end
+
+ def create_fixture_test(path = :unit, name = 'test')
+ app_file "test/#{path}/#{name}_test.rb", <<-RUBY
+ require 'test_helper'
+
+ class #{name.camelize}Test < ActiveSupport::TestCase
+ def test_fixture
+ puts "\#{User.count} users (\#{__FILE__})"
+ end
+ end
+ RUBY
+ end
+
+ def create_schema
+ app_file 'db/schema.rb', ''
+ end
+
+ def redirect_stderr(target_stream)
+ previous_stderr = STDERR.dup
+ $stderr.reopen(target_stream)
+ yield
+ target_stream.rewind
+ ensure
+ $stderr = previous_stderr
+ end
+
+ def create_test_file(path = :unit, name = 'test')
+ 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
+ end
+ end
+ RUBY
+ end
+
+ def create_scaffold
+ script 'generate scaffold user name:string'
+ Dir.chdir(app_path) { File.exist?('app/models/user.rb') }
+ run_migration
+ end
+
+ def run_migration
+ Dir.chdir(app_path) { `bundle exec rake db:migrate` }
+ end
+ end
+end
diff --git a/railties/test/commands/console_test.rb b/railties/test/commands/console_test.rb
index 6be4a5fe89..3c784b43be 100644
--- a/railties/test/commands/console_test.rb
+++ b/railties/test/commands/console_test.rb
@@ -58,10 +58,7 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end
def test_console_defaults_to_IRB
- config = mock("config", console: nil)
- app = mock("app", config: config)
- app.expects(:load_console).returns(nil)
-
+ app = build_app(console: nil)
assert_equal IRB, Rails::Console.new(app).console
end
@@ -127,13 +124,15 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
end
def app
- @app ||= begin
- config = mock("config", console: FakeConsole)
- app = mock("app", config: config)
- app.stubs(:sandbox=).returns(nil)
- app.expects(:load_console)
- app
- end
+ @app ||= build_app(console: FakeConsole)
+ end
+
+ def build_app(config)
+ config = mock("config", config)
+ app = mock("app", config: config)
+ app.stubs(:sandbox=).returns(nil)
+ app.expects(:load_console)
+ app
end
def parse_arguments(args)
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index 357f472a3f..b29d1e018e 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -271,4 +271,45 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
end
end
end
+
+ def test_scaffold_generator_password_digest
+ run_generator ["user", "name", "password:digest"]
+
+ assert_file "app/models/user.rb", /has_secure_password/
+
+ assert_migration "db/migrate/create_users.rb" do |m|
+ assert_method :change, m do |up|
+ assert_match(/t\.string :name/, up)
+ assert_match(/t\.string :password_digest/, up)
+ end
+ end
+
+ assert_file "app/controllers/users_controller.rb" do |content|
+ assert_instance_method :user_params, content do |m|
+ assert_match(/permit\(:name, :password, :password_confirmation\)/, m)
+ end
+ end
+
+ assert_file "app/views/users/_form.html.erb" do |content|
+ assert_match(/<%= f\.password_field :password %>/, content)
+ assert_match(/<%= f\.password_field :password_confirmation %>/, content)
+ end
+
+ assert_file "app/views/users/index.html.erb" do |content|
+ assert_no_match(/password/, content)
+ end
+
+ assert_file "app/views/users/show.html.erb" do |content|
+ assert_no_match(/password/, content)
+ end
+
+ assert_file "test/controllers/users_controller_test.rb" do |content|
+ assert_match(/password: 'secret'/, content)
+ assert_match(/password_confirmation: 'secret'/, content)
+ end
+
+ assert_file "test/fixtures/users.yml" do |content|
+ assert_match(/password_digest: <%= BCrypt::Password.create\('secret'\) %>/, content)
+ end
+ end
end
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 37d0be107c..26b388b6f9 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -105,7 +105,7 @@ module RailtiesTest
assert_not_nil bukkits_migration_order, "Expected migration to be skipped"
migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length
- output = `bundle exec rake railties:install:migrations`
+ `bundle exec rake railties:install:migrations`
assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length
end