diff options
Diffstat (limited to 'railties/test')
54 files changed, 3212 insertions, 628 deletions
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb index a05bae5dcc..8b38081667 100644 --- a/railties/test/abstract_unit.rb +++ b/railties/test/abstract_unit.rb @@ -11,7 +11,8 @@ require 'action_controller' require 'rails/all' # TODO: Remove these hacks -class TestApp < Rails::Application - config.root = File.dirname(__FILE__) +module TestApp + class Application < Rails::Application + config.root = File.dirname(__FILE__) + end end -Rails.application = TestApp diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 9928ee2c52..044fd2a278 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -26,24 +26,23 @@ module ApplicationTests FileUtils.rm_rf(new_app) if File.directory?(new_app) end - test "Rails::Application.instance is nil until app is initialized" do + test "Rails.application is nil until app is initialized" do require 'rails' - assert_nil Rails::Application.instance + assert_nil Rails.application require "#{app_path}/config/environment" - assert_equal AppTemplate::Application.instance, Rails::Application.instance + assert_equal AppTemplate::Application.instance, Rails.application end - test "Rails::Application responds to all instance methods" do + test "Rails.application responds to all instance methods" do require "#{app_path}/config/environment" - assert_respond_to Rails::Application, :routes_reloader - assert_equal Rails::Application.routes_reloader, Rails.application.routes_reloader - assert_equal Rails::Application.routes_reloader, AppTemplate::Application.routes_reloader + 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" assert_respond_to AppTemplate::Application, :paths - assert_equal AppTemplate::Application.paths.app.views.to_a, ["#{app_path}/app/views"] + assert_equal AppTemplate::Application.paths["app/views"].expanded, ["#{app_path}/app/views"] end test "the application root is set correctly" do @@ -96,6 +95,11 @@ module ApplicationTests assert AppTemplate::Application.config.allow_concurrency end + test "asset_path defaults to nil for application" do + require "#{app_path}/config/environment" + assert_equal nil, AppTemplate::Application.config.asset_path + end + test "the application can be marked as threadsafe when there are no frameworks" do FileUtils.rm_rf("#{app_path}/config/environments") add_to_config <<-RUBY @@ -125,22 +129,6 @@ module ApplicationTests assert !ActionController.autoload?(:RecordIdentifier) end - test "runtime error is raised if config.frameworks= is used" do - add_to_config "config.frameworks = []" - - assert_raises RuntimeError do - require "#{app_path}/config/environment" - end - end - - test "runtime error is raised if config.frameworks is used" do - add_to_config "config.frameworks -= []" - - assert_raises RuntimeError do - require "#{app_path}/config/environment" - end - end - test "filter_parameters should be able to set via config.filter_parameters" do add_to_config <<-RUBY config.filter_parameters += [ :foo, 'bar', lambda { |key, value| @@ -172,22 +160,32 @@ module ApplicationTests assert $prepared end + def assert_utf8 + if RUBY_VERSION < '1.9' + assert_equal "UTF8", $KCODE + else + assert_equal Encoding::UTF_8, Encoding.default_external + assert_equal Encoding::UTF_8, Encoding.default_internal + end + end + + test "skipping config.encoding still results in 'utf-8' as the default" do + require "#{app_path}/config/application" + assert_utf8 + end + test "config.encoding sets the default encoding" do add_to_config <<-RUBY config.encoding = "utf-8" RUBY require "#{app_path}/config/application" - - unless RUBY_VERSION < '1.9' - assert_equal Encoding::UTF_8, Encoding.default_external - assert_equal Encoding::UTF_8, Encoding.default_internal - end + assert_utf8 end test "config.paths.public sets Rails.public_path" do add_to_config <<-RUBY - config.paths.public = "somewhere" + config.paths["public"] = "somewhere" RUBY require "#{app_path}/config/application" @@ -218,7 +216,7 @@ module ApplicationTests protect_from_forgery def index - render :inline => "<%= csrf_meta_tag %>" + render :inline => "<%= csrf_meta_tags %>" end end @@ -267,5 +265,73 @@ module ApplicationTests get "/" assert_not_equal res, last_response.body end + + test "config.asset_path is not passed through env" do + make_basic_app do |app| + app.config.asset_path = "/omg%s" + end + + class ::OmgController < ActionController::Base + def index + render :inline => "<%= image_path('foo.jpg') %>" + end + end + + get "/" + assert_equal "/omg/images/foo.jpg", last_response.body + 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" + require 'action_view/base' + + assert ActionView::Resolver.caching? + end + + test "config.action_view.cache_template_loading without cache_classes default" do + add_to_config "config.cache_classes = false" + require "#{app_path}/config/environment" + require 'action_view/base' + + assert !ActionView::Resolver.caching? + end + + test "config.action_view.cache_template_loading = false" do + add_to_config <<-RUBY + config.cache_classes = true + config.action_view.cache_template_loading = false + RUBY + require "#{app_path}/config/environment" + require 'action_view/base' + + assert !ActionView::Resolver.caching? + end + + test "config.action_view.cache_template_loading = true" do + add_to_config <<-RUBY + config.cache_classes = false + config.action_view.cache_template_loading = true + RUBY + require "#{app_path}/config/environment" + require 'action_view/base' + + assert ActionView::Resolver.caching? + end + + test "config.action_dispatch.show_exceptions is sent in env" do + make_basic_app do |app| + app.config.action_dispatch.show_exceptions = true + end + + class ::OmgController < ActionController::Base + def index + render :text => env["action_dispatch.show_exceptions"] + end + end + + get "/" + assert_equal 'true', last_response.body + end end end diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index a72e6916dd..793e73556c 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -1,7 +1,7 @@ require 'isolation/abstract_unit' class ConsoleTest < Test::Unit::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation def setup build_app @@ -14,27 +14,26 @@ class ConsoleTest < Test::Unit::TestCase end def test_app_method_should_return_integration_session + TestHelpers::Rack.send :remove_method, :app load_environment console_session = app - assert_not_nil console_session - assert_instance_of ActionController::Integration::Session, console_session + assert_instance_of ActionDispatch::Integration::Session, console_session end def test_new_session_should_return_integration_session load_environment session = new_session - assert_not_nil session - assert_instance_of ActionController::Integration::Session, session + assert_instance_of ActionDispatch::Integration::Session, session end - def test_reload_should_fire_preparation_callbacks + def test_reload_should_fire_preparation_and_cleanup_callbacks load_environment a = b = c = nil # TODO: These should be defined on the initializer - ActionDispatch::Callbacks.to_prepare { a = b = c = 1 } - ActionDispatch::Callbacks.to_prepare { b = c = 2 } - ActionDispatch::Callbacks.to_prepare { c = 3 } + ActionDispatch::Reloader.to_cleanup { a = b = c = 1 } + ActionDispatch::Reloader.to_cleanup { b = c = 2 } + ActionDispatch::Reloader.to_prepare { c = 3 } # Hide Reloading... output silence_stream(STDOUT) { reload! } diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index d258625f42..8b840fffd0 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -25,6 +25,11 @@ module ApplicationTests yield app_const.config end + test "allow running plugin new generator inside Rails app directory" do + FileUtils.cd(rails_root){ `ruby script/rails plugin new vendor/plugins/bukkits` } + assert File.exist?(File.join(rails_root, "vendor/plugins/bukkits/test/dummy/config/application.rb")) + end + test "generators default values" do with_bare_config do |c| assert_equal(true, c.generators.colorize_logging) @@ -69,7 +74,7 @@ module ApplicationTests assert_equal :rspec, Rails::Generators.options[:rails][:test_framework] assert_equal "-w", Rails::Generators.aliases[:rails][:test_framework] assert_equal Hash[:shoulda => :test_unit], Rails::Generators.fallbacks - assert_equal ["#{app_path}/lib/templates", "some/where"], Rails::Generators.templates_path + assert_equal ["some/where"], Rails::Generators.templates_path end test "generators no color on initialization" do diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index d8e916f45f..19311a7fa0 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -1,7 +1,7 @@ require "isolation/abstract_unit" module ApplicationTests - class FrameworlsTest < Test::Unit::TestCase + class FrameworksTest < Test::Unit::TestCase include ActiveSupport::Testing::Isolation def setup @@ -61,9 +61,77 @@ module ApplicationTests require "#{app_path}/config/environment" assert Foo.method_defined?(:foo_path) + assert Foo.method_defined?(:main_app) assert_equal ["notify"], Foo.action_methods end + test "allows to not load all helpers for controllers" do + add_to_config "config.action_controller.include_all_helpers = false" + + app_file "app/controllers/application_controller.rb", <<-RUBY + class ApplicationController < ActionController::Base + end + RUBY + + app_file "app/controllers/foo_controller.rb", <<-RUBY + class FooController < ApplicationController + def included_helpers + render :inline => "<%= from_app_helper -%> <%= from_foo_helper %>" + end + + def not_included_helper + render :inline => "<%= respond_to?(:from_bar_helper) -%>" + end + end + RUBY + + app_file "app/helpers/application_helper.rb", <<-RUBY + module ApplicationHelper + def from_app_helper + "from_app_helper" + end + end + RUBY + + app_file "app/helpers/foo_helper.rb", <<-RUBY + module FooHelper + def from_foo_helper + "from_foo_helper" + end + end + RUBY + + app_file "app/helpers/bar_helper.rb", <<-RUBY + module BarHelper + def from_bar_helper + "from_bar_helper" + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + match "/:controller(/:action)" + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + + get "/foo/included_helpers" + assert_equal "from_app_helper from_foo_helper", last_response.body + + get "/foo/not_included_helper" + assert_equal "false", last_response.body + end + + # AD + test "action_dispatch extensions are applied to ActionDispatch" do + add_to_config "config.action_dispatch.tld_length = 2" + require "#{app_path}/config/environment" + assert_equal 2, ActionDispatch::Http::URL.tld_length + end + # AS test "if there's no config.active_support.bare, all of ActiveSupport is required" do use_frameworks [] @@ -98,17 +166,7 @@ module ApplicationTests require "#{app_path}/config/environment" - expects = [ActiveRecord::QueryCache, ActiveRecord::SessionStore] - middleware = Rails.application.config.middleware.map { |m| m.klass } - assert_equal expects, middleware & expects - end - - test "database middleware initializes when allow concurrency is true" do - add_to_config "config.threadsafe!" - - require "#{app_path}/config/environment" - - expects = [ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache] + expects = [ActiveRecord::IdentityMap::Middleware, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActiveRecord::SessionStore] middleware = Rails.application.config.middleware.map { |m| m.klass } assert_equal expects, middleware & expects end diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb index 4baa8a8170..390f65ab5c 100644 --- a/railties/test/application/initializers/i18n_test.rb +++ b/railties/test/application/initializers/i18n_test.rb @@ -63,6 +63,36 @@ module ApplicationTests assert I18n.load_path.include?("#{app_path}/config/another_locale.yml") end + test "load_path is populated before eager loaded models" do + add_to_config <<-RUBY + config.cache_classes = true + RUBY + + app_file "config/locales/en.yml", <<-YAML +en: + foo: "1" + YAML + + app_file 'app/models/foo.rb', <<-RUBY + class Foo < ActiveRecord::Base + @foo = I18n.t(:foo) + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match '/i18n', :to => lambda { |env| [200, {}, [Foo.instance_variable_get('@foo')]] } + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + load_app + + get "/i18n" + assert_equal "1", last_response.body + end + test "locales are reloaded if they change between requests" do add_to_config <<-RUBY config.cache_classes = false @@ -74,7 +104,7 @@ en: YAML app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match '/i18n', :to => lambda { |env| [200, {}, [I18n.t(:foo)]] } end RUBY @@ -147,4 +177,4 @@ en: assert_fallbacks :ca => [:ca, :"es-ES", :es, :'en-US', :en] end end -end
\ No newline at end of file +end diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index 340ce67511..c340465e87 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -18,10 +18,10 @@ class LoadingTest < Test::Unit::TestCase validates_acceptance_of :title, :accept => "omg" end MODEL - + require "#{rails_root}/config/environment" setup_ar! - + p = Post.create(:title => 'omg') assert_equal 1, Post.count assert_equal 'omg', p.title @@ -42,6 +42,23 @@ class LoadingTest < Test::Unit::TestCase User end + test "load config/environments/environment before Bootstrap initializers" do + app_file "config/environments/development.rb", <<-RUBY + AppTemplate::Application.configure do + config.development_environment_loaded = true + end + RUBY + + add_to_config <<-RUBY + config.before_initialize do + config.loaded = config.development_environment_loaded + end + RUBY + + require "#{app_path}/config/environment" + assert ::AppTemplate::Application.config.loaded + end + def test_descendants_are_cleaned_on_each_request_without_cache_classes add_to_config <<-RUBY config.cache_classes = false @@ -53,7 +70,7 @@ class LoadingTest < Test::Unit::TestCase MODEL app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match '/load', :to => lambda { |env| [200, {}, Post.all] } match '/unload', :to => lambda { |env| [200, {}, []] } end @@ -72,8 +89,13 @@ class LoadingTest < Test::Unit::TestCase assert_equal [], ActiveRecord::Base.descendants end + test "initialize_cant_be_called_twice" do + require "#{app_path}/config/environment" + assert_raise(RuntimeError) { ::AppTemplate::Application.initialize! } + end + protected - + def setup_ar! ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:") ActiveRecord::Migration.verbose = false diff --git a/railties/test/application/middleware/best_practices_test.rb b/railties/test/application/middleware/best_practices_test.rb new file mode 100644 index 0000000000..5b722e7510 --- /dev/null +++ b/railties/test/application/middleware/best_practices_test.rb @@ -0,0 +1,26 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class BestPracticesTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + require 'rack/test' + extend Rack::Test::Methods + simple_controller + end + + test "simple controller in production mode returns best standards" do + get '/foo' + assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"] + end + + test "simple controller in development mode leaves out Chrome" do + app("development") + get "/foo" + assert_equal "IE=Edge", last_response.headers["X-UA-Compatible"] + end + end +end diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb new file mode 100644 index 0000000000..f582ed0e42 --- /dev/null +++ b/railties/test/application/middleware/cache_test.rb @@ -0,0 +1,150 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class RoutingTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + require 'rack/test' + extend Rack::Test::Methods + end + + def simple_controller + controller :expires, <<-RUBY + class ExpiresController < ApplicationController + def expires_header + expires_in 10, :public => !params[:private] + render :text => ActiveSupport::SecureRandom.hex(16) + end + + def expires_etag + render_conditionally(:etag => "1") + end + + def expires_last_modified + $last_modified ||= Time.now.utc + render_conditionally(:last_modified => $last_modified) + end + private + def render_conditionally(headers) + if stale?(headers.merge(:public => !params[:private])) + render :text => ActiveSupport::SecureRandom.hex(16) + end + end + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match ':controller(/:action)' + end + RUBY + end + + def test_cache_is_disabled_in_dev_mode + simple_controller + app("development") + + get "/expires/expires_header" + assert_nil last_response.headers['X-Rack-Cache'] + + body = last_response.body + + get "/expires/expires_header" + assert_nil last_response.headers['X-Rack-Cache'] + assert_not_equal body, last_response.body + end + + def test_cache_works_with_expires + simple_controller + + get "/expires/expires_header" + assert_equal "miss, store", last_response.headers["X-Rack-Cache"] + assert_equal "max-age=10, public", last_response.headers["Cache-Control"] + + body = last_response.body + + get "/expires/expires_header" + + assert_equal "fresh", last_response.headers["X-Rack-Cache"] + + assert_equal body, last_response.body + end + + def test_cache_works_with_expires_private + simple_controller + + get "/expires/expires_header", :private => true + assert_equal "miss", last_response.headers["X-Rack-Cache"] + assert_equal "private, max-age=10", last_response.headers["Cache-Control"] + + body = last_response.body + + get "/expires/expires_header", :private => true + assert_equal "miss", last_response.headers["X-Rack-Cache"] + assert_not_equal body, last_response.body + end + + def test_cache_works_with_etags + simple_controller + + get "/expires/expires_etag" + assert_equal "miss, store", last_response.headers["X-Rack-Cache"] + assert_equal "public", last_response.headers["Cache-Control"] + + body = last_response.body + etag = last_response.headers["ETag"] + + get "/expires/expires_etag", {}, "If-None-Match" => etag + assert_equal "stale, valid, store", last_response.headers["X-Rack-Cache"] + assert_equal body, last_response.body + end + + def test_cache_works_with_etags_private + simple_controller + + get "/expires/expires_etag", :private => true + assert_equal "miss", last_response.headers["X-Rack-Cache"] + assert_equal "must-revalidate, private, max-age=0", last_response.headers["Cache-Control"] + + body = last_response.body + etag = last_response.headers["ETag"] + + get "/expires/expires_etag", {:private => true}, "If-None-Match" => etag + assert_equal "miss", last_response.headers["X-Rack-Cache"] + assert_not_equal body, last_response.body + end + + def test_cache_works_with_last_modified + simple_controller + + get "/expires/expires_last_modified" + assert_equal "miss, store", last_response.headers["X-Rack-Cache"] + assert_equal "public", last_response.headers["Cache-Control"] + + body = last_response.body + last = last_response.headers["Last-Modified"] + + get "/expires/expires_last_modified", {}, "If-Modified-Since" => last + assert_equal "stale, valid, store", last_response.headers["X-Rack-Cache"] + assert_equal body, last_response.body + end + + def test_cache_works_with_last_modified_private + simple_controller + + get "/expires/expires_last_modified", :private => true + assert_equal "miss", last_response.headers["X-Rack-Cache"] + assert_equal "must-revalidate, private, max-age=0", last_response.headers["Cache-Control"] + + body = last_response.body + last = last_response.headers["Last-Modified"] + + get "/expires/expires_last_modified", {:private => true}, "If-Modified-Since" => last + assert_equal "miss", last_response.headers["X-Rack-Cache"] + assert_not_equal body, last_response.body + end + end +end diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb new file mode 100644 index 0000000000..f28302d70a --- /dev/null +++ b/railties/test/application/middleware/remote_ip_test.rb @@ -0,0 +1,63 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class RemoteIpTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + def app + @app ||= Rails.application + end + + def remote_ip(env = {}) + remote_ip = nil + env = Rack::MockRequest.env_for("/").merge(env).merge!( + 'action_dispatch.show_exceptions' => false, + 'action_dispatch.secret_token' => 'b3c631c314c0bbca50c1b2843150fe33' + ) + + endpoint = Proc.new do |e| + remote_ip = ActionDispatch::Request.new(e).remote_ip + [200, {}, ["Hello"]] + end + + Rails.application.middleware.build(endpoint).call(env) + remote_ip + end + + test "remote_ip works" do + make_basic_app + assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1") + end + + test "checks IP spoofing by default" do + make_basic_app + assert_raises(ActionDispatch::RemoteIp::IpSpoofAttackError) do + remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") + end + end + + test "can disable IP spoofing check" do + make_basic_app do |app| + app.config.action_dispatch.ip_spoofing_check = false + end + + assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do + assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") + end + end + + test "the user can set trusted proxies" do + make_basic_app do |app| + app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/ + end + + assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1") + end + end +end diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb new file mode 100644 index 0000000000..0128261cd4 --- /dev/null +++ b/railties/test/application/middleware/sendfile_test.rb @@ -0,0 +1,56 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class SendfileTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + def app + @app ||= Rails.application + end + + define_method :simple_controller do + class ::OmgController < ActionController::Base + def index + send_file __FILE__ + end + end + end + + # x_sendfile_header middleware + test "config.action_dispatch.x_sendfile_header defaults to ''" do + make_basic_app + simple_controller + + get "/" + assert_equal File.read(__FILE__), last_response.body + end + + test "config.action_dispatch.x_sendfile_header can be set" do + make_basic_app do |app| + app.config.action_dispatch.x_sendfile_header = "X-Sendfile" + end + + simple_controller + + get "/" + assert_equal File.expand_path(__FILE__), last_response.headers["X-Sendfile"] + end + + test "config.action_dispatch.x_sendfile_header is sent to Rack::Sendfile" do + make_basic_app do |app| + app.config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File' + end + + simple_controller + + get "/" + assert_equal File.expand_path(__FILE__), last_response.headers["X-Lighttpd-Send-File"] + end + end +end diff --git a/railties/test/application/middleware/show_exceptions_test.rb b/railties/test/application/middleware/show_exceptions_test.rb new file mode 100644 index 0000000000..5487e41e0a --- /dev/null +++ b/railties/test/application/middleware/show_exceptions_test.rb @@ -0,0 +1,37 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class ShowExceptionsTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + FileUtils.rm_rf "#{app_path}/config/environments" + end + + def app + @app ||= Rails.application + end + + test "unspecified route when set action_dispatch.show_exceptions to false" do + make_basic_app do |app| + app.config.action_dispatch.show_exceptions = false + end + + assert_raise(ActionController::RoutingError) do + get '/foo' + end + end + + test "unspecified route when set action_dispatch.show_exceptions to true" do + make_basic_app do |app| + app.config.action_dispatch.show_exceptions = true + end + + assert_nothing_raised(ActionController::RoutingError) do + get '/foo' + end + end + end +end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 1f127cee78..b314832685 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -27,7 +27,10 @@ module ApplicationTests "ActionDispatch::ShowExceptions", "ActionDispatch::RemoteIp", "Rack::Sendfile", + "ActionDispatch::Reloader", "ActionDispatch::Callbacks", + "ActiveRecord::IdentityMap::Middleware", + "ActiveRecord::ConnectionAdapters::ConnectionManagement", "ActiveRecord::QueryCache", "ActionDispatch::Cookies", "ActionDispatch::Session::CookieStore", @@ -35,15 +38,26 @@ module ApplicationTests "ActionDispatch::ParamsParser", "Rack::MethodOverride", "ActionDispatch::Head", + "Rack::ConditionalGet", + "Rack::ETag", "ActionDispatch::BestStandardsSupport" ], middleware end + test "Rack::Cache is present when action_controller.perform_caching is set" do + add_to_config "config.action_controller.perform_caching = true" + + boot! + + assert_equal "Rack::Cache", middleware.first + end + test "removing Active Record omits its middleware" do use_frameworks [] boot! assert !middleware.include?("ActiveRecord::ConnectionAdapters::ConnectionManagement") assert !middleware.include?("ActiveRecord::QueryCache") + assert !middleware.include?("ActiveRecord::IdentityMap::Middleware") end test "removes lock if allow concurrency is set" do @@ -64,10 +78,16 @@ module ApplicationTests assert !middleware.include?("ActionDispatch::Static") end - test "removes show exceptions if action_dispatch.show_exceptions is disabled" do + test "includes show exceptions even action_dispatch.show_exceptions is disabled" do add_to_config "config.action_dispatch.show_exceptions = false" boot! - assert !middleware.include?("ActionDispatch::ShowExceptions") + assert middleware.include?("ActionDispatch::ShowExceptions") + end + + test "removes ActionDispatch::Reloader if cache_classes is true" do + add_to_config "config.cache_classes = true" + boot! + assert !middleware.include?("ActionDispatch::Reloader") end test "use middleware" do @@ -94,87 +114,57 @@ module ApplicationTests assert_equal "Rack::Runtime", middleware.fourth end + test "identity map is inserted" do + boot! + assert middleware.include?("ActiveRecord::IdentityMap::Middleware") + end + test "insert middleware before" do add_to_config "config.middleware.insert_before ActionDispatch::Static, Rack::Config" boot! assert_equal "Rack::Config", middleware.first end - # x_sendfile_header middleware - test "config.action_dispatch.x_sendfile_header defaults to ''" do + # ConditionalGet + Etag + test "conditional get + etag middlewares handle http caching based on body" do make_basic_app class ::OmgController < ActionController::Base def index - send_file __FILE__ + if params[:nothing] + render :text => "" + else + render :text => "OMG" + end end end - get "/" - assert_equal File.read(__FILE__), last_response.body - end - - test "config.action_dispatch.x_sendfile_header can be set" do - make_basic_app do |app| - app.config.action_dispatch.x_sendfile_header = "X-Sendfile" - end - - class ::OmgController < ActionController::Base - def index - send_file __FILE__ - end - end + etag = "5af83e3196bf99f440f31f2e1a6c9afe".inspect get "/" - assert_equal File.expand_path(__FILE__), last_response.headers["X-Sendfile"] - end - - test "config.action_dispatch.x_sendfile_header is sent to Rack::Sendfile" do - make_basic_app do |app| - app.config.action_dispatch.x_sendfile_header = 'X-Lighttpd-Send-File' - end - - class ::OmgController < ActionController::Base - def index - send_file __FILE__ - end - end - - get "/" - assert_equal File.expand_path(__FILE__), last_response.headers["X-Lighttpd-Send-File"] - end - - # remote_ip tests - test "remote_ip works" do - make_basic_app - assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "1.1.1.1") - end - - test "checks IP spoofing by default" do - make_basic_app - assert_raises(ActionDispatch::RemoteIp::IpSpoofAttackError) do - remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") - end - end - - test "can disable IP spoofing check" do - make_basic_app do |app| - app.config.action_dispatch.ip_spoofing_check = false - end - - assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do - assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2") - end - end - - test "the user can set trusted proxies" do - make_basic_app do |app| - app.config.action_dispatch.trusted_proxies = /^4\.2\.42\.42$/ - end - - assert_equal "1.1.1.1", remote_ip("REMOTE_ADDR" => "4.2.42.42,1.1.1.1") - end - + assert_equal 200, last_response.status + assert_equal "OMG", last_response.body + assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"] + assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"] + assert_equal etag, last_response.headers["Etag"] + + get "/", {}, "HTTP_IF_NONE_MATCH" => etag + assert_equal 304, last_response.status + assert_equal "", last_response.body + assert_equal nil, last_response.headers["Content-Type"] + assert_equal "max-age=0, private, must-revalidate", last_response.headers["Cache-Control"] + assert_equal etag, last_response.headers["Etag"] + + get "/?nothing=true" + puts last_response.body + assert_equal 200, last_response.status + assert_equal "", last_response.body + assert_equal "text/html; charset=utf-8", last_response.headers["Content-Type"] + assert_equal "no-cache", last_response.headers["Cache-Control"] + assert_equal nil, last_response.headers["Etag"] + end + + # Show exceptions middleware test "show exceptions middleware filter backtrace before logging" do my_middleware = Struct.new(:app) do def call(env) @@ -203,21 +193,5 @@ module ApplicationTests def middleware AppTemplate::Application.middleware.map(&:klass).map(&:name) end - - def remote_ip(env = {}) - remote_ip = nil - env = Rack::MockRequest.env_for("/").merge(env).merge!( - 'action_dispatch.show_exceptions' => false, - 'action_dispatch.secret_token' => 'b3c631c314c0bbca50c1b2843150fe33' - ) - - endpoint = Proc.new do |e| - remote_ip = ActionDispatch::Request.new(e).remote_ip - [200, {}, ["Hello"]] - end - - Rails.application.middleware.build(endpoint).call(env) - remote_ip - end end end diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb index c98b11556b..b1ff6e9cb1 100644 --- a/railties/test/application/paths_test.rb +++ b/railties/test/application/paths_test.rb @@ -25,7 +25,7 @@ module ApplicationTests end def assert_path(paths, *dir) - assert_equal [root(*dir)], paths.paths + assert_equal [root(*dir)], paths.expanded end def assert_in_load_path(*path) @@ -37,20 +37,20 @@ module ApplicationTests end test "booting up Rails yields a valid paths object" do - assert_path @paths.app.models, "app", "models" - assert_path @paths.app.helpers, "app", "helpers" - assert_path @paths.app.views, "app", "views" - assert_path @paths.lib, "lib" - assert_path @paths.vendor, "vendor" - assert_path @paths.vendor.plugins, "vendor", "plugins" - assert_path @paths.tmp, "tmp" - assert_path @paths.tmp.cache, "tmp", "cache" - assert_path @paths.config, "config" - assert_path @paths.config.locales, "config", "locales", "en.yml" - assert_path @paths.config.environment, "config", "environment.rb" - assert_path @paths.config.environments, "config", "environments", "development.rb" + assert_path @paths["app/models"], "app/models" + assert_path @paths["app/helpers"], "app/helpers" + assert_path @paths["app/views"], "app/views" + assert_path @paths["lib"], "lib" + assert_path @paths["vendor"], "vendor" + assert_path @paths["vendor/plugins"], "vendor/plugins" + assert_path @paths["tmp"], "tmp" + assert_path @paths["tmp/cache"], "tmp/cache" + assert_path @paths["config"], "config" + assert_path @paths["config/locales"], "config/locales/en.yml" + assert_path @paths["config/environment"], "config/environment.rb" + assert_path @paths["config/environments"], "config/environments/development.rb" - assert_equal root("app", "controllers"), @paths.app.controllers.to_a.first + assert_equal root("app", "controllers"), @paths["app/controllers"].expanded.first end test "booting up Rails yields a list of paths that are eager" do diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb index 863950c04f..b0a9925890 100644 --- a/railties/test/application/rackup_test.rb +++ b/railties/test/application/rackup_test.rb @@ -31,13 +31,6 @@ module ApplicationTests assert_kind_of Rails::Application, Rails.application end - # Passenger still uses AC::Dispatcher, so we need to - # keep it working for now - test "deprecated ActionController::Dispatcher still works" do - rackup - assert_kind_of Rails::Application, ActionController::Dispatcher.new - end - test "the config object is available on the application object" do rackup assert_equal 'UTC', Rails.application.config.time_zone diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index d6e100ffe3..59e5ef4dee 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -14,7 +14,7 @@ module ApplicationTests app_file "lib/tasks/app.rake", <<-RUBY $task_loaded = Rake::Task.task_defined?("db:create:all") RUBY - + require "#{app_path}/config/environment" ::Rails.application.load_tasks assert $task_loaded @@ -33,5 +33,71 @@ module ApplicationTests assert_match "SuperMiddleware", Dir.chdir(app_path){ `rake middleware` } end + + def test_initializers_are_executed_in_rake_tasks + add_to_config <<-RUBY + initializer "do_something" do + puts "Doing something..." + end + + rake_tasks do + task :do_nothing => :environment do + end + end + RUBY + + output = Dir.chdir(app_path){ `rake do_nothing` } + assert_match "Doing something...", output + end + + def test_code_statistics_sanity + assert_match "Code LOC: 5 Test LOC: 0 Code to Test Ratio: 1:0.0", + Dir.chdir(app_path){ `rake stats` } + end + + def test_rake_routes_output_strips_anchors_from_http_verbs + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + get '/cart', :to => 'cart#show' + end + RUBY + assert_match 'cart GET /cart(.:format)', Dir.chdir(app_path){ `rake routes` } + end + + def test_model_and_migration_generator_with_change_syntax + Dir.chdir(app_path) do + `rails generate model user username:string password:string` + `rails generate migration add_email_to_users email:string` + end + + output = Dir.chdir(app_path){ `rake db:migrate` } + assert_match /create_table\(:users\)/, output + assert_match /CreateUsers: migrated/, output + assert_match /add_column\(:users, :email, :string\)/, output + assert_match /AddEmailToUsers: migrated/, output + + output = Dir.chdir(app_path){ `rake db:rollback STEP=2` } + assert_match /drop_table\("users"\)/, output + assert_match /CreateUsers: reverted/, output + assert_match /remove_column\("users", :email\)/, output + assert_match /AddEmailToUsers: reverted/, output + end + + def test_loading_specific_fixtures + Dir.chdir(app_path) do + `rails generate model user username:string password:string` + `rails generate model product name:string` + `rake db:migrate` + end + + require "#{rails_root}/config/environment" + + # loading a specific fixture + errormsg = Dir.chdir(app_path) { `rake db:fixtures:load FIXTURES=products` } + assert $?.success?, errormsg + + assert_equal 2, ::AppTemplate::Application::Product.count + assert_equal 0, ::AppTemplate::Application::User.count + end end -end
\ No newline at end of file +end diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index febc53bac9..62589c998d 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -11,34 +11,6 @@ module ApplicationTests extend Rack::Test::Methods end - def app(env = "production") - old_env = ENV["RAILS_ENV"] - - @app ||= begin - ENV["RAILS_ENV"] = env - require "#{app_path}/config/environment" - Rails.application - end - ensure - ENV["RAILS_ENV"] = old_env - end - - def simple_controller - controller :foo, <<-RUBY - class FooController < ApplicationController - def index - render :text => "foo" - end - end - RUBY - - app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| - match ':controller(/:action)' - end - RUBY - end - test "rails/info/properties in development" do app("development") get "/rails/info/properties" @@ -58,21 +30,6 @@ module ApplicationTests assert_equal 'foo', last_response.body end - test "simple controller in production mode returns best standards" do - simple_controller - - get '/foo' - assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"] - end - - test "simple controller in development mode leaves out Chrome" do - simple_controller - app("development") - - get "/foo" - assert_equal "IE=Edge", last_response.headers["X-UA-Compatible"] - end - test "simple controller with helper" do controller :foo, <<-RUBY class FooController < ApplicationController @@ -91,7 +48,7 @@ module ApplicationTests RUBY app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match ':controller(/:action)' end RUBY @@ -102,7 +59,7 @@ module ApplicationTests test "mount rack app" do app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do mount lambda { |env| [200, {}, [env["PATH_INFO"]]] }, :at => "/blog" # The line below is required because mount sometimes # fails when a resource route is added. @@ -132,7 +89,7 @@ module ApplicationTests RUBY app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match ':controller(/:action)' end RUBY @@ -164,7 +121,7 @@ module ApplicationTests RUBY app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match 'admin/foo', :to => 'admin/foo#index' match 'foo', :to => 'foo#index' end @@ -177,6 +134,34 @@ module ApplicationTests assert_equal 'admin::foo', last_response.body end + test "routes appending blocks" do + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match ':controller#:action' + end + RUBY + + add_to_config <<-R + routes.append do + match '/win' => lambda { |e| [200, {'Content-Type'=>'text/plain'}, ['WIN']] } + end + R + + app 'development' + + get '/win' + assert_equal 'WIN', last_response.body + + app_file 'config/routes.rb', <<-R + AppTemplate::Application.routes.draw do + match 'lol' => 'hello#index' + end + R + + get '/win' + assert_equal 'WIN', last_response.body + end + {"development" => "baz", "production" => "bar"}.each do |mode, expected| test "reloads routes when configuration is changed in #{mode}" do controller :foo, <<-RUBY @@ -192,7 +177,7 @@ module ApplicationTests RUBY app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match 'foo', :to => 'foo#bar' end RUBY @@ -203,7 +188,7 @@ module ApplicationTests assert_equal 'bar', last_response.body app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match 'foo', :to => 'foo#baz' end RUBY @@ -215,7 +200,32 @@ module ApplicationTests end end - test 'resource routing with irrigular inflection' do + test 'routes are loaded just after initialization' do + require "#{app_path}/config/application" + + # Create the rack app just inside after initialize callback + ActiveSupport.on_load(:after_initialize) do + ::InitializeRackApp = lambda { |env| [200, {}, ["InitializeRackApp"]] } + end + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match 'foo', :to => ::InitializeRackApp + end + RUBY + + get '/foo' + assert_equal "InitializeRackApp", last_response.body + end + + test 'reload_routes! is part of Rails.application API' do + app("development") + assert_nothing_raised do + Rails.application.reload_routes! + end + end + + test 'resource routing with irregular inflection' do app_file 'config/initializers/inflection.rb', <<-RUBY ActiveSupport::Inflector.inflections do |inflect| inflect.irregular 'yazi', 'yazilar' @@ -223,7 +233,7 @@ module ApplicationTests RUBY app_file 'config/routes.rb', <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do resources :yazilar end RUBY diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb index 07a3d94120..292d1e247f 100644 --- a/railties/test/application/runner_test.rb +++ b/railties/test/application/runner_test.rb @@ -18,6 +18,10 @@ module ApplicationTests MODEL end + def test_should_include_runner_in_shebang_line_in_help + assert_match "/rails runner", Dir.chdir(app_path) { `bundle exec rails runner --help` } + end + def test_should_run_ruby_statement assert_match "42", Dir.chdir(app_path) { `bundle exec rails runner "puts User.count"` } end diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index de316a6fd0..1fbbb40132 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -53,7 +53,7 @@ module ApplicationTests app_file 'test/integration/posts_test.rb', <<-RUBY require 'test_helper' - class PostsTest < ActionController::IntegrationTest + class PostsTest < ActionDispatch::IntegrationTest def test_index get '/posts' assert_response :success diff --git a/railties/test/fixtures/lib/empty_builder.rb b/railties/test/fixtures/lib/app_builders/empty_builder.rb index babd9c2461..babd9c2461 100644 --- a/railties/test/fixtures/lib/empty_builder.rb +++ b/railties/test/fixtures/lib/app_builders/empty_builder.rb diff --git a/railties/test/fixtures/lib/app_builders/simple_builder.rb b/railties/test/fixtures/lib/app_builders/simple_builder.rb new file mode 100644 index 0000000000..993d3a2aa2 --- /dev/null +++ b/railties/test/fixtures/lib/app_builders/simple_builder.rb @@ -0,0 +1,7 @@ +class AppBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/app_builders/tweak_builder.rb b/railties/test/fixtures/lib/app_builders/tweak_builder.rb new file mode 100644 index 0000000000..cb50be01cb --- /dev/null +++ b/railties/test/fixtures/lib/app_builders/tweak_builder.rb @@ -0,0 +1,7 @@ +class AppBuilder < Rails::AppBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/create_test_dummy_template.rb b/railties/test/fixtures/lib/create_test_dummy_template.rb new file mode 100644 index 0000000000..e4378bbd1a --- /dev/null +++ b/railties/test/fixtures/lib/create_test_dummy_template.rb @@ -0,0 +1 @@ +create_dummy_app("spec/dummy") diff --git a/railties/test/fixtures/lib/plugin_builders/empty_builder.rb b/railties/test/fixtures/lib/plugin_builders/empty_builder.rb new file mode 100644 index 0000000000..5c5607621c --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/empty_builder.rb @@ -0,0 +1,2 @@ +class PluginBuilder +end diff --git a/railties/test/fixtures/lib/plugin_builders/simple_builder.rb b/railties/test/fixtures/lib/plugin_builders/simple_builder.rb new file mode 100644 index 0000000000..08f6c5535d --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/simple_builder.rb @@ -0,0 +1,7 @@ +class PluginBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/plugin_builders/spec_builder.rb b/railties/test/fixtures/lib/plugin_builders/spec_builder.rb new file mode 100644 index 0000000000..aa18c7ddaa --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/spec_builder.rb @@ -0,0 +1,19 @@ +class PluginBuilder < Rails::PluginBuilder + def test + create_file "spec/spec_helper.rb" + append_file "Rakefile", <<-EOF +# spec tasks in rakefile + +task :default => :spec + EOF + end + + def generate_test_dummy + dummy_path("spec/dummy") + super + end + + def skip_test_unit? + true + end +end diff --git a/railties/test/fixtures/lib/plugin_builders/tweak_builder.rb b/railties/test/fixtures/lib/plugin_builders/tweak_builder.rb new file mode 100644 index 0000000000..1e801409a4 --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/tweak_builder.rb @@ -0,0 +1,7 @@ +class PluginBuilder < Rails::PluginBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/simple_builder.rb b/railties/test/fixtures/lib/simple_builder.rb deleted file mode 100644 index 47dcdc0d96..0000000000 --- a/railties/test/fixtures/lib/simple_builder.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AppBuilder - def configru - create_file "config.ru", <<-R.strip -run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] } - R - end -end
\ No newline at end of file diff --git a/railties/test/fixtures/lib/tweak_builder.rb b/railties/test/fixtures/lib/tweak_builder.rb deleted file mode 100644 index eed20ecc9b..0000000000 --- a/railties/test/fixtures/lib/tweak_builder.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AppBuilder < Rails::AppBuilder - def configru - create_file "config.ru", <<-R.strip -run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] } - R - end -end
\ No newline at end of file diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb index 0472ca73a8..68d4c17623 100644 --- a/railties/test/generators/actions_test.rb +++ b/railties/test/generators/actions_test.rb @@ -7,11 +7,16 @@ class ActionsTest < Rails::Generators::TestCase arguments [destination_root] def setup + Rails.application = TestApp::Application super @git_plugin_uri = 'git://github.com/technoweenie/restful-authentication.git' @svn_plugin_uri = 'svn://svnhub.com/technoweenie/restful-authentication/trunk' end + def teardown + Rails.application = TestApp::Application.instance + end + def test_invoke_other_generator_with_shortcut action :invoke, 'model', ['my_model'] assert_file 'app/models/my_model.rb', /MyModel/ @@ -79,37 +84,6 @@ class ActionsTest < Rails::Generators::TestCase assert_file 'Gemfile', /gem "will\-paginate"/ end - def test_gem_with_options_should_include_all_options_in_gemfile - run_generator - - assert_deprecated do - action :gem, 'mislav-will-paginate', :lib => 'will-paginate', :source => 'http://gems.github.com' - end - - assert_deprecated do - action :gem, 'thoughtbot-factory_girl', :require_as => 'factory_girl', :source => 'http://gems.github.com' - end - - assert_file 'Gemfile', /gem "mislav\-will\-paginate", :require => "will\-paginate"/ - assert_file 'Gemfile', /source "http:\/\/gems\.github\.com"/ - assert_file 'Gemfile', /gem "thoughtbot-factory_girl", :require => "factory_girl"/ - end - - def test_gem_with_env_should_include_all_dependencies_in_gemfile - run_generator - - assert_deprecated do - action :gem, 'rspec', :env => %w(development test) - end - - assert_deprecated do - action :gem, 'rspec-rails', :only => %w(development test) - end - - assert_file 'Gemfile', /gem "rspec", :group => \["development", "test"\]/ - assert_file 'Gemfile', /gem "rspec-rails", :group => \["development", "test"\]/ - end - def test_gem_with_version_should_include_version_in_gemfile run_generator @@ -204,12 +178,6 @@ class ActionsTest < Rails::Generators::TestCase action :capify! end - def test_freeze_is_deprecated - assert_deprecated do - action :freeze! - end - end - def test_route_should_add_data_to_the_routes_block_in_config_routes run_generator route_command = "route '/login', :controller => 'sessions', :action => 'new'" @@ -223,6 +191,31 @@ class ActionsTest < Rails::Generators::TestCase assert_match(/Welcome to Rails/, action(:readme, "README")) end + def test_readme_with_quiet + generator(default_arguments, :quiet => true) + run_generator + Rails::Generators::AppGenerator.expects(:source_root).times(2).returns(destination_root) + assert_no_match(/Welcome to Rails/, action(:readme, "README")) + end + + def test_log + assert_equal("YES\n", action(:log, "YES")) + end + + def test_log_with_status + assert_equal(" yes YES\n", action(:log, :yes, "YES")) + end + + def test_log_with_quiet + generator(default_arguments, :quiet => true) + assert_equal("", action(:log, "YES")) + end + + def test_log_with_status_with_quiet + generator(default_arguments, :quiet => true) + assert_equal("", action(:log, :yes, "YES")) + end + protected def action(*args, &block) diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 08cfb585f9..018c2fa6bf 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'generators/generators_test_helper' require 'rails/generators/rails/app/app_generator' +require 'generators/shared_generator_tests.rb' DEFAULT_APP_FILES = %w( .gitignore @@ -40,28 +41,10 @@ DEFAULT_APP_FILES = %w( class AppGeneratorTest < Rails::Generators::TestCase include GeneratorsTestHelper arguments [destination_root] + include SharedGeneratorTests - def setup - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - end - - def teardown - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - end - - def test_application_skeleton_is_created - run_generator - - DEFAULT_APP_FILES.each{ |path| assert_file path } - end - - def test_application_generate_pretend - run_generator ["testapp", "--pretend"] - - DEFAULT_APP_FILES.each{ |path| assert_no_file path } + def default_files + ::DEFAULT_APP_FILES end def test_application_controller_and_layout_files @@ -70,42 +53,34 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_no_file "public/stylesheets/application.css" end - def test_options_before_application_name_raises_an_error - content = capture(:stderr){ run_generator(["--skip-active-record", destination_root]) } - assert_equal "Options should be given after the application name. For details run: rails --help\n", content - end - - def test_name_collision_raises_an_error - reserved_words = %w[application destroy plugin runner test] - reserved_words.each do |reserved| - content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } - assert_equal "Invalid application name #{reserved}. Please give a name which does not match one of the reserved rails words.\n", content - end - end - - def test_invalid_database_option_raises_an_error - content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) } - assert_match /Invalid value for \-\-database option/, content - end - def test_invalid_application_name_raises_an_error content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] } assert_equal "Invalid application name 43-things. Please give a name which does not start with numbers.\n", content end - def test_application_name_raises_an_error_if_name_already_used_constant - %w{ String Hash Class Module Set Symbol }.each do |ruby_class| - content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] } - assert_equal "Invalid application name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another application name.\n", content - end - end - def test_invalid_application_name_is_fixed run_generator [File.join(destination_root, "things-43")] assert_file "things-43/config/environment.rb", /Things43::Application\.initialize!/ assert_file "things-43/config/application.rb", /^module Things43$/ end + def test_application_new_exits_with_non_zero_code_on_invalid_application_name + # TODO: Suppress the output of this (it's because of a Thor::Error) + `rails new test` + assert_equal false, $?.success? + end + + def test_application_new_exits_with_message_and_non_zero_code_when_generating_inside_existing_rails_directory + app_root = File.join(destination_root, 'myfirstapp') + run_generator [app_root] + output = nil + Dir.chdir(app_root) do + output = `rails new mysecondapp` + end + assert_equal "Can't initialize a new Rails application within the directory of another, please change to a non-Rails directory first.\nType 'rails' for help.\n", output + assert_equal false, $?.success? + end + def test_application_name_is_detected_if_it_exists_and_app_folder_renamed app_root = File.join(destination_root, "myapp") app_moved_root = File.join(destination_root, "myapp_moved") @@ -118,16 +93,26 @@ class AppGeneratorTest < Rails::Generators::TestCase FileUtils.mv(app_root, app_moved_root) - # forces the shell to automatically overwrite all files - Thor::Base.shell.send(:attr_accessor, :always_force) - shell = Thor::Base.shell.new - shell.send(:always_force=, true) - generator = Rails::Generators::AppGenerator.new ["rails"], { :with_dispatchers => true }, - :destination_root => app_moved_root, :shell => shell + :destination_root => app_moved_root, :shell => @shell generator.send(:app_const) silence(:stdout){ generator.send(:create_config_files) } assert_file "myapp_moved/config/environment.rb", /Myapp::Application\.initialize!/ + assert_file "myapp_moved/config/initializers/session_store.rb", /_myapp_session/ + 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) + silence(:stdout){ generator.send(:create_config_files) } + assert_file "myapp/config/initializers/session_store.rb", /_myapp_session/ end def test_application_names_are_not_singularized @@ -138,18 +123,22 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_config_database_is_added_by_default run_generator assert_file "config/database.yml", /sqlite3/ - assert_file "Gemfile", /^gem\s+["']sqlite3-ruby["'],\s+:require\s+=>\s+["']sqlite3["']$/ + assert_file "Gemfile", /^gem\s+["']sqlite3["']$/ end def test_config_another_database run_generator([destination_root, "-d", "mysql"]) assert_file "config/database.yml", /mysql/ - assert_file "Gemfile", /^gem\s+["']mysql["']$/ + assert_file "Gemfile", /^gem\s+["']mysql2["']$/ end - def test_config_database_is_not_added_if_skip_active_record_is_given + def test_generator_if_skip_active_record_is_given run_generator [destination_root, "--skip-active-record"] assert_no_file "config/database.yml" + assert_file "test/test_helper.rb" do |helper_content| + assert_no_match /fixtures :all/, helper_content + end + assert_file "test/performance/browsing_test.rb" end def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given @@ -163,26 +152,37 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "public/javascripts/application.js" assert_file "public/javascripts/prototype.js" assert_file "public/javascripts/rails.js" + assert_file "public/javascripts/controls.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/effects.js" assert_file "test" end - def test_prototype_and_test_unit_are_skipped_if_required - run_generator [destination_root, "--skip-prototype", "--skip-test-unit"] + def test_javascript_is_skipped_if_required + run_generator [destination_root, "--skip-javascript"] assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(\)/ assert_file "public/javascripts/application.js" assert_no_file "public/javascripts/prototype.js" assert_no_file "public/javascripts/rails.js" - assert_no_file "test" end - def test_shebang_is_added_to_rails_file - run_generator [destination_root, "--ruby", "foo/bar/baz"] - assert_file "script/rails", /#!foo\/bar\/baz/ + def test_config_prototype_javascript_library + run_generator [destination_root, "-j", "prototype"] + assert_file "config/application.rb", /#\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(jquery rails\)/ + assert_file "public/javascripts/application.js" + assert_file "public/javascripts/prototype.js" + assert_file "public/javascripts/controls.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/effects.js" + assert_file "public/javascripts/rails.js", /prototype/ end - def test_shebang_when_is_the_same_as_default_use_env - run_generator [destination_root, "--ruby", Thor::Util.ruby_command] - assert_file "script/rails", /#!\/usr\/bin\/env/ + def test_config_jquery_javascript_library + run_generator [destination_root, "-j", "jquery"] + assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(jquery rails\)/ + assert_file "public/javascripts/application.js" + assert_file "public/javascripts/jquery.js" + assert_file "public/javascripts/rails.js", /jQuery/ end def test_template_from_dir_pwd @@ -190,21 +190,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]) end - def test_template_raises_an_error_with_invalid_path - content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } - assert_match /The template \[.*\] could not be loaded/, content - assert_match /non\/existant\/path/, content - end - - def test_template_is_executed_when_supplied - path = "http://gist.github.com/103208.txt" - 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) - assert_match /It works!/, silence(:stdout){ generator.invoke_all } - end - def test_usage_read_from_file File.expects(:read).returns("USAGE FROM FILE") assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc @@ -224,17 +209,11 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file 'lib/test_file.rb', 'heres test data' end - def test_dev_option - generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") - silence(:stdout){ generator.invoke_all } - rails_path = File.expand_path('../../..', Rails.root) - assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ - end - - def test_edge_option - generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") - silence(:stdout){ generator.invoke_all } - assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/ + def test_test_unit_is_removed_from_frameworks_if_skip_test_unit_is_given + run_generator [destination_root, "--skip-test-unit"] + assert_file "config/application.rb" do |file| + assert_match /config.generators.test_framework = false/, file + end end protected @@ -250,60 +229,21 @@ class CustomAppGeneratorTest < Rails::Generators::TestCase tests Rails::Generators::AppGenerator arguments [destination_root] + include SharedCustomGeneratorTests - def setup - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - end - - def teardown - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - Object.class_eval { remove_const :AppBuilder if const_defined?(:AppBuilder) } - end - - def test_builder_option_with_empty_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/empty_builder.rb"]) - DEFAULT_APP_FILES.each{ |path| assert_no_file path } - end - - def test_builder_option_with_simple_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/simple_builder.rb"]) - (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_relative_path - here = File.expand_path(File.dirname(__FILE__)) - FileUtils.cd(here) - run_generator([destination_root, "-b", "../fixtures/lib/simple_builder.rb"]) - (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] +protected + def default_files + ::DEFAULT_APP_FILES end - def test_builder_option_with_tweak_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/tweak_builder.rb"]) - DEFAULT_APP_FILES.each{ |path| assert_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] + def builders_dir + "app_builders" end - def test_builder_option_with_http - path = "http://gist.github.com/103208.txt" - template = "class AppBuilder; end" - template.instance_eval "def read; self; end" # Make the string respond to read - - generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) - capture(:stdout) { generator.invoke_all } - - DEFAULT_APP_FILES.each{ |path| assert_no_file path } + def builder_class + :AppBuilder end -protected - def action(*args, &block) silence(:stdout){ generator.send(*args, &block) } end diff --git a/railties/test/generators/generated_attribute_test.rb b/railties/test/generators/generated_attribute_test.rb index de7e4de2a6..064546a3f3 100644 --- a/railties/test/generators/generated_attribute_test.rb +++ b/railties/test/generators/generated_attribute_test.rb @@ -108,4 +108,16 @@ class GeneratedAttributeTest < Rails::Generators::TestCase ) end end + + def test_nil_type_raises_exception + assert_raise Thor::Error do + create_generated_attribute(nil, 'title') + end + end + + def test_missing_type_raises_exception + assert_raise Thor::Error do + create_generated_attribute('', 'title') + end + end end diff --git a/railties/test/generators/generator_generator_test.rb b/railties/test/generators/generator_generator_test.rb index 26f975a191..f4c975fc18 100644 --- a/railties/test/generators/generator_generator_test.rb +++ b/railties/test/generators/generator_generator_test.rb @@ -17,4 +17,43 @@ class GeneratorGeneratorTest < Rails::Generators::TestCase assert_file "lib/generators/awesome/awesome_generator.rb", /class AwesomeGenerator < Rails::Generators::NamedBase/ end + + def test_namespaced_generator_skeleton + run_generator ["rails/awesome"] + + %w( + lib/generators/rails/awesome + lib/generators/rails/awesome/USAGE + lib/generators/rails/awesome/templates + ).each{ |path| assert_file path } + + assert_file "lib/generators/rails/awesome/awesome_generator.rb", + /class Rails::AwesomeGenerator < Rails::Generators::NamedBase/ + end + + def test_generator_skeleton_is_created_without_file_name_namespace + run_generator ["awesome", "--namespace", "false"] + + %w( + lib/generators/ + lib/generators/USAGE + lib/generators/templates + ).each{ |path| assert_file path } + + assert_file "lib/generators/awesome_generator.rb", + /class AwesomeGenerator < Rails::Generators::NamedBase/ + end + + def test_namespaced_generator_skeleton_without_file_name_namespace + run_generator ["rails/awesome", "--namespace", "false"] + + %w( + lib/generators/rails + lib/generators/rails/USAGE + lib/generators/rails/templates + ).each{ |path| assert_file path } + + assert_file "lib/generators/rails/awesome_generator.rb", + /class Rails::AwesomeGenerator < Rails::Generators::NamedBase/ + end end diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index 4a5a9b2932..1b9a8fd8a7 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -34,6 +34,6 @@ module GeneratorsTestHelper routes = File.expand_path("../../../lib/rails/generators/rails/app/templates/config/routes.rb", __FILE__) destination = File.join(destination_root, "config") FileUtils.mkdir_p(destination) - FileUtils.cp File.expand_path(routes), destination + FileUtils.cp routes, destination end -end
\ No newline at end of file +end diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb index 450dec7716..f4fdc46328 100644 --- a/railties/test/generators/mailer_generator_test.rb +++ b/railties/test/generators/mailer_generator_test.rb @@ -59,6 +59,15 @@ class MailerGeneratorTest < Rails::Generators::TestCase assert_match /haml \[not found\]/, content end + def test_mailer_with_namedspaced_mailer + run_generator ["Farm::Animal", "moos"] + assert_file "app/mailers/farm/animal.rb" do |mailer| + assert_match /class Farm::Animal < ActionMailer::Base/, mailer + assert_match /en\.farm\.animal\.moos\.subject/, mailer + end + assert_file "app/views/farm/animal/moos.text.erb" + end + def test_actions_are_turned_into_methods run_generator diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb index f9d1e42d24..6eecfc8e2e 100644 --- a/railties/test/generators/migration_generator_test.rb +++ b/railties/test/generators/migration_generator_test.rb @@ -34,15 +34,10 @@ class MigrationGeneratorTest < Rails::Generators::TestCase run_generator [migration, "title:string", "body:text"] assert_migration "db/migrate/#{migration}.rb" do |content| - assert_class_method :up, content do |up| + assert_method :change, content do |up| assert_match /add_column :posts, :title, :string/, up assert_match /add_column :posts, :body, :text/, up end - - assert_class_method :down, content do |down| - assert_match /remove_column :posts, :title/, down - assert_match /remove_column :posts, :body/, down - end end end @@ -51,12 +46,12 @@ class MigrationGeneratorTest < Rails::Generators::TestCase run_generator [migration, "title:string", "body:text"] assert_migration "db/migrate/#{migration}.rb" do |content| - assert_class_method :up, content do |up| + assert_method :up, content do |up| assert_match /remove_column :posts, :title/, up assert_match /remove_column :posts, :body/, up end - assert_class_method :down, content do |down| + assert_method :down, content do |down| assert_match /add_column :posts, :title, :string/, down assert_match /add_column :posts, :body, :text/, down end @@ -68,11 +63,11 @@ class MigrationGeneratorTest < Rails::Generators::TestCase run_generator [migration, "title:string", "content:text"] assert_migration "db/migrate/#{migration}.rb" do |content| - assert_class_method :up, content do |up| + assert_method :up, content do |up| assert_match /^\s*$/, up end - assert_class_method :down, content do |down| + assert_method :down, content do |down| assert_match /^\s*$/, down end end diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index ef415a4fed..3d773b4134 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -11,6 +11,12 @@ class ModelGeneratorTest < Rails::Generators::TestCase assert_match /TestUnit options:/, content end + def test_model_with_missing_attribute_type + content = capture(:stderr) { run_generator ["post", "title:string", "body"] } + assert_match /Missing type for attribute 'body'/, content + assert_match /Example: 'body:string' where string is the type/, content + end + def test_invokes_default_orm run_generator assert_file "app/models/account.rb", /class Account < ActiveRecord::Base/ @@ -93,15 +99,11 @@ class ModelGeneratorTest < Rails::Generators::TestCase run_generator ["product", "name:string", "supplier_id:integer"] assert_migration "db/migrate/create_products.rb" do |m| - assert_class_method :up, m do |up| + assert_method :change, m do |up| assert_match /create_table :products/, up assert_match /t\.string :name/, up assert_match /t\.integer :supplier_id/, up end - - assert_class_method :down, m do |down| - assert_match /drop_table :products/, down - end end end @@ -135,16 +137,28 @@ class ModelGeneratorTest < Rails::Generators::TestCase run_generator ["account", "--no-timestamps"] assert_migration "db/migrate/create_accounts.rb" do |m| - assert_class_method :up, m do |up| + assert_method :change, m do |up| assert_no_match /t.timestamps/, up end end end - def test_migration_already_exists_error_message + def test_migration_is_skipped_with_skip_option + run_generator + output = run_generator ["Account", "--skip"] + assert_match %r{skip\s+db/migrate/\d+_create_accounts.rb}, output + end + + def test_migration_is_ignored_as_identical_with_skip_option + run_generator ["Account"] + output = run_generator ["Account", "--skip"] + assert_match %r{identical\s+db/migrate/\d+_create_accounts.rb}, output + end + + def test_migration_is_skipped_on_skip_behavior run_generator - error = capture(:stderr){ run_generator ["Account"], :behavior => :skip } - assert_match /Another migration is already named create_accounts/, error + output = run_generator ["Account"], :behavior => :skip + assert_match %r{skip\s+db/migrate/\d+_create_accounts.rb}, output end def test_migration_error_is_not_shown_on_revoke @@ -159,6 +173,15 @@ class ModelGeneratorTest < Rails::Generators::TestCase assert_no_migration "db/migrate/create_accounts.rb" end + def test_existing_migration_is_removed_on_force + run_generator + old_migration = Dir["#{destination_root}/db/migrate/*_create_accounts.rb"].first + error = capture(:stderr) { run_generator ["Account", "--force"] } + assert_no_match /Another migration is already named create_accounts/, error + assert_no_file old_migration + assert_migration 'db/migrate/create_accounts.rb' + end + def test_invokes_default_test_framework run_generator assert_file "test/unit/account_test.rb", /class AccountTest < ActiveSupport::TestCase/ @@ -180,4 +203,45 @@ class ModelGeneratorTest < Rails::Generators::TestCase content = capture(:stderr){ run_generator ["object"] } assert_match /The name 'Object' is either already used in your application or reserved/, content end + + def test_index_is_added_for_belongs_to_association + run_generator ["account", "supplier:belongs_to"] + + assert_migration "db/migrate/create_accounts.rb" do |m| + assert_method :change, m do |up| + assert_match /add_index/, up + end + end + end + + def test_index_is_added_for_references_association + run_generator ["account", "supplier:references"] + + assert_migration "db/migrate/create_accounts.rb" do |m| + assert_method :change, m do |up| + assert_match /add_index/, up + end + end + end + + def test_index_is_skipped_for_belongs_to_association + run_generator ["account", "supplier:belongs_to", "--no-indexes"] + + assert_migration "db/migrate/create_accounts.rb" do |m| + assert_method :change, m do |up| + assert_no_match /add_index/, up + end + end + end + + def test_index_is_skipped_for_references_association + run_generator ["account", "supplier:references", "--no-indexes"] + + assert_migration "db/migrate/create_accounts.rb" do |m| + assert_method :change, m do |up| + assert_no_match /add_index/, up + end + end + end + end diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index 1badae0713..f23701e99e 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -98,6 +98,11 @@ class NamedBaseTest < Rails::Generators::TestCase assert_name g, 'posts', :index_helper end + def test_index_helper_to_pluralize_once + g = generator ['Stadium'] + assert_name g, 'stadia', :index_helper + end + def test_index_helper_with_uncountable g = generator ['Sheep'] assert_name g, 'sheep_index', :index_helper diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb new file mode 100644 index 0000000000..d61a02d32f --- /dev/null +++ b/railties/test/generators/namespaced_generators_test.rb @@ -0,0 +1,357 @@ +require 'generators/generators_test_helper' +require 'rails/generators/rails/controller/controller_generator' +require 'rails/generators/rails/model/model_generator' +require 'rails/generators/rails/observer/observer_generator' +require 'rails/generators/mailer/mailer_generator' +require 'rails/generators/rails/scaffold/scaffold_generator' + +class NamespacedGeneratorTestCase < Rails::Generators::TestCase + def setup + TestApp::Application.isolate_namespace(TestApp) + end + + def teardown + if TestApp.respond_to?(:_railtie) + TestApp.singleton_class.send(:undef_method, :_railtie) + TestApp.singleton_class.send(:undef_method, :table_name_prefix) + TestApp::Application.isolated = false + end + end +end + +class NamespacedControllerGeneratorTest < NamespacedGeneratorTestCase + include GeneratorsTestHelper + arguments %w(Account foo bar) + tests Rails::Generators::ControllerGenerator + + setup :copy_routes + + def test_namespaced_controller_skeleton_is_created + run_generator + assert_file "app/controllers/test_app/account_controller.rb", /module TestApp/, / class AccountController < ApplicationController/ + assert_file "test/functional/test_app/account_controller_test.rb", /module TestApp/, / class AccountControllerTest/ + end + + def test_skipping_namespace + run_generator ["Account", "--skip-namespace"] + assert_file "app/controllers/account_controller.rb", /class AccountController < ApplicationController/ + assert_file "app/helpers/account_helper.rb", /module AccountHelper/ + end + + def test_namespaced_controller_with_additional_namespace + run_generator ["admin/account"] + assert_file "app/controllers/test_app/admin/account_controller.rb", /module TestApp/, / class Admin::AccountController < ApplicationController/ + end + + def test_helpr_is_also_namespaced + run_generator + assert_file "app/helpers/test_app/account_helper.rb", /module TestApp/, / module AccountHelper/ + assert_file "test/unit/helpers/test_app/account_helper_test.rb", /module TestApp/, / class AccountHelperTest/ + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/functional/test_app/account_controller_test.rb" + end + + def test_invokes_default_template_engine + run_generator + assert_file "app/views/test_app/account/foo.html.erb", %r(app/views/test_app/account/foo\.html\.erb) + assert_file "app/views/test_app/account/bar.html.erb", %r(app/views/test_app/account/bar\.html\.erb) + end + + def test_routes_should_not_be_namespaced + run_generator + assert_file "config/routes.rb", /get "account\/foo"/, /get "account\/bar"/ + end +# + def test_invokes_default_template_engine_even_with_no_action + run_generator ["account"] + assert_file "app/views/test_app/account" + end +end + +class NamespacedModelGeneratorTest < NamespacedGeneratorTestCase + include GeneratorsTestHelper + arguments %w(Account name:string age:integer) + tests Rails::Generators::ModelGenerator + + def test_module_file_is_not_created + run_generator + assert_no_file "app/models/test_app.rb" + end + + def test_adds_namespace_to_model + run_generator + assert_file "app/models/test_app/account.rb", /module TestApp/, / class Account < ActiveRecord::Base/ + end + + def test_model_with_namespace + run_generator ["admin/account"] + assert_file "app/models/test_app/admin.rb", /module TestApp/, /module Admin/ + assert_file "app/models/test_app/admin.rb", /def self\.table_name_prefix/ + assert_file "app/models/test_app/admin.rb", /'admin_'/ + assert_file "app/models/test_app/admin/account.rb", /module TestApp/, /class Admin::Account < ActiveRecord::Base/ + end + + def test_migration + run_generator + assert_migration "db/migrate/create_test_app_accounts.rb", /create_table :test_app_accounts/, /class CreateTestAppAccounts < ActiveRecord::Migration/ + end + + def test_migration_with_namespace + run_generator ["Gallery::Image"] + assert_migration "db/migrate/create_test_app_gallery_images", /class CreateTestAppGalleryImages < ActiveRecord::Migration/ + assert_no_migration "db/migrate/create_test_app_images" + end + + def test_migration_with_nested_namespace + run_generator ["Admin::Gallery::Image"] + assert_no_migration "db/migrate/create_images" + assert_no_migration "db/migrate/create_gallery_images" + assert_migration "db/migrate/create_test_app_admin_gallery_images", /class CreateTestAppAdminGalleryImages < ActiveRecord::Migration/ + assert_migration "db/migrate/create_test_app_admin_gallery_images", /create_table :test_app_admin_gallery_images/ + end + + def test_migration_with_nested_namespace_without_pluralization + ActiveRecord::Base.pluralize_table_names = false + run_generator ["Admin::Gallery::Image"] + assert_no_migration "db/migrate/create_images" + assert_no_migration "db/migrate/create_gallery_images" + assert_no_migration "db/migrate/create_test_app_admin_gallery_images" + assert_migration "db/migrate/create_test_app_admin_gallery_image", /class CreateTestAppAdminGalleryImage < ActiveRecord::Migration/ + assert_migration "db/migrate/create_test_app_admin_gallery_image", /create_table :test_app_admin_gallery_image/ + ensure + ActiveRecord::Base.pluralize_table_names = true + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/unit/test_app/account_test.rb", /module TestApp/, /class AccountTest < ActiveSupport::TestCase/ + assert_file "test/fixtures/test_app/accounts.yml", /name: MyString/, /age: 1/ + end +end + +class NamespacedObserverGeneratorTest < NamespacedGeneratorTestCase + include GeneratorsTestHelper + arguments %w(account) + tests Rails::Generators::ObserverGenerator + + def test_invokes_default_orm + run_generator + assert_file "app/models/test_app/account_observer.rb", /module TestApp/, / class AccountObserver < ActiveRecord::Observer/ + end + + def test_invokes_default_orm_with_class_path + run_generator ["admin/account"] + assert_file "app/models/test_app/admin/account_observer.rb", /module TestApp/, / class Admin::AccountObserver < ActiveRecord::Observer/ + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/unit/test_app/account_observer_test.rb", /module TestApp/, / class AccountObserverTest < ActiveSupport::TestCase/ + end +end + +class NamespacedMailerGeneratorTest < NamespacedGeneratorTestCase + include GeneratorsTestHelper + arguments %w(notifier foo bar) + tests Rails::Generators::MailerGenerator + + def test_mailer_skeleton_is_created + run_generator + assert_file "app/mailers/test_app/notifier.rb" do |mailer| + assert_match /module TestApp/, mailer + assert_match /class Notifier < ActionMailer::Base/, mailer + assert_match /default :from => "from@example.com"/, mailer + end + end + + def test_mailer_with_i18n_helper + run_generator + assert_file "app/mailers/test_app/notifier.rb" do |mailer| + assert_match /en\.notifier\.foo\.subject/, mailer + assert_match /en\.notifier\.bar\.subject/, mailer + end + end + + def test_invokes_default_test_framework + run_generator + assert_file "test/functional/test_app/notifier_test.rb" do |test| + assert_match /module TestApp/, test + assert_match /class NotifierTest < ActionMailer::TestCase/, test + assert_match /test "foo"/, test + assert_match /test "bar"/, test + end + end + + def test_invokes_default_template_engine + run_generator + assert_file "app/views/test_app/notifier/foo.text.erb" do |view| + assert_match %r(app/views/test_app/notifier/foo\.text\.erb), view + assert_match /<%= @greeting %>/, view + end + + assert_file "app/views/test_app/notifier/bar.text.erb" do |view| + assert_match %r(app/views/test_app/notifier/bar\.text\.erb), view + assert_match /<%= @greeting %>/, view + end + end + + def test_invokes_default_template_engine_even_with_no_action + run_generator ["notifier"] + assert_file "app/views/test_app/notifier" + end +end + +class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase + include GeneratorsTestHelper + arguments %w(product_line title:string price:integer) + tests Rails::Generators::ScaffoldGenerator + + setup :copy_routes + + def test_scaffold_on_invoke + run_generator + + # Model + assert_file "app/models/test_app/product_line.rb", /module TestApp\n class ProductLine < ActiveRecord::Base/ + assert_file "test/unit/test_app/product_line_test.rb", /module TestApp\n class ProductLineTest < ActiveSupport::TestCase/ + assert_file "test/fixtures/test_app/product_lines.yml" + assert_migration "db/migrate/create_test_app_product_lines.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_match(/resources :product_lines$/, route) + end + + # Controller + assert_file "app/controllers/test_app/product_lines_controller.rb" do |content| + assert_match(/module TestApp\n class ProductLinesController < ApplicationController/, content) + end + + assert_file "test/functional/test_app/product_lines_controller_test.rb", + /module TestApp\n class ProductLinesControllerTest < ActionController::TestCase/ + + # Views + %w( + index + edit + new + show + _form + ).each { |view| assert_file "app/views/test_app/product_lines/#{view}.html.erb" } + assert_no_file "app/views/layouts/test_app/product_lines.html.erb" + + # Helpers + assert_file "app/helpers/test_app/product_lines_helper.rb" + assert_file "test/unit/helpers/test_app/product_lines_helper_test.rb" + + # Stylesheets + assert_file "public/stylesheets/scaffold.css" + end + + def test_scaffold_on_revoke + run_generator + run_generator ["product_line"], :behavior => :revoke + + # Model + assert_no_file "app/models/test_app/product_line.rb" + assert_no_file "test/unit/test_app/product_line_test.rb" + assert_no_file "test/fixtures/test_app/product_lines.yml" + assert_no_migration "db/migrate/create_test_app_product_lines.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_no_match(/resources :product_lines$/, route) + end + + # Controller + assert_no_file "app/controllers/test_app/product_lines_controller.rb" + assert_no_file "test/functional/test_app/product_lines_controller_test.rb" + + # Views + assert_no_file "app/views/test_app/product_lines" + assert_no_file "app/views/test_app/layouts/product_lines.html.erb" + + # Helpers + assert_no_file "app/helpers/test_app/product_lines_helper.rb" + assert_no_file "test/unit/helpers/test_app/product_lines_helper_test.rb" + + # Stylesheets (should not be removed) + assert_file "public/stylesheets/scaffold.css" + end + + def test_scaffold_with_namespace_on_invoke + run_generator [ "admin/role", "name:string", "description:string" ] + + # 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/unit/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 resources :roles 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) + end + + assert_file "test/functional/test_app/admin/roles_controller_test.rb", + /module TestApp\n class Admin::RolesControllerTest < ActionController::TestCase/ + + # Views + %w( + index + edit + new + show + _form + ).each { |view| assert_file "app/views/test_app/admin/roles/#{view}.html.erb" } + assert_no_file "app/views/layouts/admin/roles.html.erb" + + # Helpers + assert_file "app/helpers/test_app/admin/roles_helper.rb" + assert_file "test/unit/helpers/test_app/admin/roles_helper_test.rb" + + # Stylesheets + assert_file "public/stylesheets/scaffold.css" + end + + def test_scaffold_with_namespace_on_revoke + run_generator [ "admin/role", "name:string", "description:string" ] + run_generator [ "admin/role" ], :behavior => :revoke + + # Model + assert_file "app/models/test_app/admin.rb" # ( should not be remove ) + assert_no_file "app/models/test_app/admin/role.rb" + assert_no_file "test/unit/test_app/admin/role_test.rb" + assert_no_file "test/fixtures/test_app/admin/roles.yml" + assert_no_migration "db/migrate/create_test_app_admin_roles.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_no_match(/namespace :admin do resources :roles end$/, route) + end + + # Controller + assert_no_file "app/controllers/test_app/admin/roles_controller.rb" + assert_no_file "test/functional/test_app/admin/roles_controller_test.rb" + + # Views + assert_no_file "app/views/test_app/admin/roles" + assert_no_file "app/views/layouts/test_app/admin/roles.html.erb" + + # Helpers + assert_no_file "app/helpers/test_app/admin/roles_helper.rb" + assert_no_file "test/unit/helpers/test_app/admin/roles_helper_test.rb" + + # Stylesheets (should not be removed) + assert_file "public/stylesheets/scaffold.css" + end +end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index c1f646f7c1..e6686a6af4 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -6,7 +6,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase arguments %w(plugin_fu) def test_plugin_skeleton_is_created - run_generator + silence(:stderr) { run_generator } year = Date.today.year %w( @@ -36,30 +36,36 @@ class PluginGeneratorTest < Rails::Generators::TestCase end def test_invokes_default_test_framework - run_generator + silence(:stderr) { run_generator } assert_file "vendor/plugins/plugin_fu/test/plugin_fu_test.rb", /class PluginFuTest < ActiveSupport::TestCase/ assert_file "vendor/plugins/plugin_fu/test/test_helper.rb" end def test_logs_if_the_test_framework_cannot_be_found - content = run_generator ["plugin_fu", "--test-framework=rspec"] + content = nil + silence(:stderr) { content = run_generator ["plugin_fu", "--test-framework=rspec"] } assert_match /rspec \[not found\]/, content end def test_creates_tasks_if_required - run_generator ["plugin_fu", "--tasks"] + silence(:stderr) { run_generator ["plugin_fu", "--tasks"] } assert_file "vendor/plugins/plugin_fu/lib/tasks/plugin_fu_tasks.rake" end def test_creates_generator_if_required - run_generator ["plugin_fu", "--generator"] + silence(:stderr) { run_generator ["plugin_fu", "--generator"] } assert_file "vendor/plugins/plugin_fu/lib/generators/templates" assert_file "vendor/plugins/plugin_fu/lib/generators/plugin_fu_generator.rb", /class PluginFuGenerator < Rails::Generators::NamedBase/ end def test_plugin_generator_on_revoke - run_generator + silence(:stderr) { run_generator } run_generator ["plugin_fu"], :behavior => :revoke end + + def test_deprecation + output = capture(:stderr) { run_generator } + assert_match /Plugin generator is deprecated, please use 'rails plugin new' command to generate plugin structure./, output + end end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb new file mode 100644 index 0000000000..3c11c8dbaf --- /dev/null +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -0,0 +1,229 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'rails/generators/rails/plugin_new/plugin_new_generator' +require 'generators/shared_generator_tests.rb' + +DEFAULT_PLUGIN_FILES = %w( + .gitignore + Gemfile + Rakefile + bukkits.gemspec + MIT-LICENSE + lib + lib/bukkits.rb + lib/tasks/bukkits_tasks.rake + script/rails + test/bukkits_test.rb + test/test_helper.rb + test/dummy +) + +class PluginNewGeneratorTest < Rails::Generators::TestCase + include GeneratorsTestHelper + destination File.join(Rails.root, "tmp/bukkits") + arguments [destination_root] + include SharedGeneratorTests + + def default_files + ::DEFAULT_PLUGIN_FILES + end + + def test_invalid_plugin_name_raises_an_error + content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] } + assert_equal "Invalid plugin name 43-things. Please give a name which does not start with numbers.\n", content + end + + def test_invalid_plugin_name_is_fixed + run_generator [File.join(destination_root, "things-43")] + assert_file "things-43/lib/things-43.rb", /module Things43/ + end + + def test_generating_without_options + run_generator + assert_file "README.rdoc", /Bukkits/ + assert_no_file "config/routes.rb" + assert_file "test/test_helper.rb" + assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/ + end + + def test_generating_test_files_in_full_mode + run_generator [destination_root, "--full"] + assert_directory "test/integration/" + + assert_file "test/integration/navigation_test.rb", /ActionDispatch::IntegrationTest/ + end + + def test_ensure_that_plugin_options_are_not_passed_to_app_generator + FileUtils.cd(Rails.root) + assert_no_match(/It works from file!.*It works_from_file/, run_generator([destination_root, "-m", "lib/template.rb"])) + end + + def test_ensure_that_test_dummy_can_be_generated_from_a_template + FileUtils.cd(Rails.root) + run_generator([destination_root, "-m", "lib/create_test_dummy_template.rb", "--skip-test-unit"]) + assert_file "spec/dummy" + assert_no_file "test" + end + + def test_database_entry_is_assed_by_default_in_full_mode + run_generator([destination_root, "--full"]) + assert_file "test/dummy/config/database.yml", /sqlite/ + assert_file "Gemfile", /^gem\s+["']sqlite3["']$/ + end + + def test_config_another_database + run_generator([destination_root, "-d", "mysql", "--full"]) + assert_file "test/dummy/config/database.yml", /mysql/ + assert_file "Gemfile", /^gem\s+["']mysql2["']$/ + end + + def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given + run_generator [destination_root, "--skip-active-record"] + assert_file "test/dummy/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/ + end + + def test_ensure_that_skip_active_record_option_is_passed_to_app_generator + run_generator [destination_root, "--skip_active_record"] + assert_no_file "test/dummy/config/database.yml" + assert_no_match(/ActiveRecord/, File.read(File.join(destination_root, "test/test_helper.rb"))) + end + + def test_ensure_that_database_option_is_passed_to_app_generator + run_generator [destination_root, "--database", "postgresql"] + assert_file "test/dummy/config/database.yml", /postgres/ + end + + def test_skipping_javascripts_without_mountable_option + run_generator + assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/rails.js" + assert_no_file "public/javascripts/controls.js" + assert_no_file "public/javascripts/dragdrop.js" + assert_no_file "public/javascripts/dragdrop.js" + assert_no_file "public/javascripts/application.js" + end + + def test_javascripts_generation + run_generator [destination_root, "--mountable"] + assert_file "public/javascripts/rails.js" + assert_file "public/javascripts/prototype.js" + assert_file "public/javascripts/controls.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/dragdrop.js" + assert_file "public/javascripts/application.js" + end + + def test_skip_javascripts + run_generator [destination_root, "--skip-javascript", "--mountable"] + assert_no_file "public/javascripts/prototype.js" + assert_no_file "public/javascripts/rails.js" + assert_no_file "public/javascripts/controls.js" + assert_no_file "public/javascripts/dragdrop.js" + assert_no_file "public/javascripts/dragdrop.js" + end + + def test_ensure_that_javascript_option_is_passed_to_app_generator + run_generator [destination_root, "--javascript", "jquery"] + assert_file "test/dummy/public/javascripts/jquery.js" + end + + def test_ensure_that_skip_javascript_option_is_passed_to_app_generator + run_generator [destination_root, "--skip_javascript"] + assert_no_file "test/dummy/public/javascripts/prototype.js" + end + + def test_template_from_dir_pwd + FileUtils.cd(Rails.root) + assert_match(/It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"])) + end + + def test_ensure_that_tests_works + run_generator + FileUtils.cd destination_root + `bundle install` + assert_match(/1 tests, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test`) + end + + def test_ensure_that_tests_works_in_full_mode + run_generator [destination_root, "--full", "--skip_active_record"] + FileUtils.cd destination_root + `bundle install` + assert_match(/2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test`) + end + + def test_creating_engine_in_full_mode + run_generator [destination_root, "--full"] + assert_file "config/routes.rb", /Rails.application.routes.draw do/ + assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < Rails::Engine\n end\nend/ + assert_file "lib/bukkits.rb", /require "bukkits\/engine"/ + end + + def test_being_quiet_while_creating_dummy_application + assert_no_match(/create\s+config\/application.rb/, run_generator) + end + + def test_create_mountable_application_with_mountable_option + run_generator [destination_root, "--mountable"] + assert_file "config/routes.rb", /Bukkits::Engine.routes.draw do/ + 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/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/ + assert_file "app/views/layouts/bukkits/application.html.erb", /<title>Bukkits<\/title>/ + end + + def test_passing_dummy_path_as_a_parameter + run_generator [destination_root, "--dummy_path", "spec/dummy"] + assert_file "spec/dummy" + assert_file "spec/dummy/config/application.rb" + assert_no_file "test/dummy" + end + + def test_skipping_gemspec + run_generator [destination_root, "--skip-gemspec"] + assert_no_file "bukkits.gemspec" + end + +protected + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end + +end + +class CustomPluginGeneratorTest < Rails::Generators::TestCase + include GeneratorsTestHelper + tests Rails::Generators::PluginNewGenerator + + destination File.join(Rails.root, "tmp/bukkits") + arguments [destination_root] + include SharedCustomGeneratorTests + + def test_overriding_test_framework + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/spec_builder.rb"]) + assert_file 'spec/spec_helper.rb' + assert_file 'spec/dummy' + assert_file 'Rakefile', /task :default => :spec/ + assert_file 'Rakefile', /# spec tasks in rakefile/ + assert_file 'script/rails', %r{spec/dummy} + end + +protected + def default_files + ::DEFAULT_PLUGIN_FILES + end + + def builder_class + :PluginBuilder + end + + def builders_dir + "plugin_builders" + end + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end +end diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb index 55d5bd6f83..71b3619351 100644 --- a/railties/test/generators/resource_generator_test.rb +++ b/railties/test/generators/resource_generator_test.rb @@ -73,6 +73,11 @@ class ResourceGeneratorTest < Rails::Generators::TestCase assert_no_match /Plural version of the model detected/, content end + def test_mass_nouns_do_not_throw_warnings + content = run_generator ["sheep".freeze] + assert_no_match /Plural version of the model detected/, content + end + def test_route_is_removed_on_revoke run_generator run_generator ["account"], :behavior => :revoke diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index f12445ae35..df787f61ba 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -3,7 +3,7 @@ require 'rails/generators/rails/scaffold/scaffold_generator' class ScaffoldGeneratorTest < Rails::Generators::TestCase include GeneratorsTestHelper - arguments %w(product_line title:string price:integer) + arguments %w(product_line title:string product:belongs_to user:references) setup :copy_routes @@ -14,48 +14,51 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_file "app/models/product_line.rb", /class ProductLine < ActiveRecord::Base/ assert_file "test/unit/product_line_test.rb", /class ProductLineTest < ActiveSupport::TestCase/ assert_file "test/fixtures/product_lines.yml" - assert_migration "db/migrate/create_product_lines.rb" + assert_migration "db/migrate/create_product_lines.rb", /belongs_to :product/ + assert_migration "db/migrate/create_product_lines.rb", /add_index :product_lines, :product_id/ + assert_migration "db/migrate/create_product_lines.rb", /references :user/ + assert_migration "db/migrate/create_product_lines.rb", /add_index :product_lines, :user_id/ # Route assert_file "config/routes.rb" do |route| - assert_match /resources :product_lines$/, route + assert_match(/resources :product_lines$/, route) end # Controller assert_file "app/controllers/product_lines_controller.rb" do |content| - assert_match /class ProductLinesController < ApplicationController/, content + assert_match(/class ProductLinesController < ApplicationController/, content) assert_instance_method :index, content do |m| - assert_match /@product_lines = ProductLine\.all/, m + assert_match(/@product_lines = ProductLine\.all/, m) end assert_instance_method :show, content do |m| - assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m + assert_match(/@product_line = ProductLine\.find\(params\[:id\]\)/, m) end assert_instance_method :new, content do |m| - assert_match /@product_line = ProductLine\.new/, m + assert_match(/@product_line = ProductLine\.new/, m) end assert_instance_method :edit, content do |m| - assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m + assert_match(/@product_line = ProductLine\.find\(params\[:id\]\)/, m) end assert_instance_method :create, content do |m| - assert_match /@product_line = ProductLine\.new\(params\[:product_line\]\)/, m - assert_match /@product_line\.save/, m - assert_match /@product_line\.errors/, m + assert_match(/@product_line = ProductLine\.new\(params\[:product_line\]\)/, m) + assert_match(/@product_line\.save/, m) + assert_match(/@product_line\.errors/, m) end assert_instance_method :update, content do |m| - assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m - assert_match /@product_line\.update_attributes\(params\[:product_line\]\)/, m - assert_match /@product_line\.errors/, m + assert_match(/@product_line = ProductLine\.find\(params\[:id\]\)/, m) + assert_match(/@product_line\.update_attributes\(params\[:product_line\]\)/, m) + assert_match(/@product_line\.errors/, m) end assert_instance_method :destroy, content do |m| - assert_match /@product_line = ProductLine\.find\(params\[:id\]\)/, m - assert_match /@product_line\.destroy/, m + assert_match(/@product_line = ProductLine\.find\(params\[:id\]\)/, m) + assert_match(/@product_line\.destroy/, m) end end @@ -92,7 +95,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Route assert_file "config/routes.rb" do |route| - assert_no_match /resources :product_lines$/, route + assert_no_match(/resources :product_lines$/, route) end # Controller @@ -123,44 +126,44 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Route assert_file "config/routes.rb" do |route| - assert_match /namespace :admin do resources :roles end$/, route + assert_match(/namespace :admin do resources :roles end$/, route) end # Controller assert_file "app/controllers/admin/roles_controller.rb" do |content| - assert_match /class Admin::RolesController < ApplicationController/, content + assert_match(/class Admin::RolesController < ApplicationController/, content) assert_instance_method :index, content do |m| - assert_match /@admin_roles = Admin::Role\.all/, m + assert_match(/@admin_roles = Admin::Role\.all/, m) end assert_instance_method :show, content do |m| - assert_match /@admin_role = Admin::Role\.find\(params\[:id\]\)/, m + assert_match(/@admin_role = Admin::Role\.find\(params\[:id\]\)/, m) end assert_instance_method :new, content do |m| - assert_match /@admin_role = Admin::Role\.new/, m + assert_match(/@admin_role = Admin::Role\.new/, m) end assert_instance_method :edit, content do |m| - assert_match /@admin_role = Admin::Role\.find\(params\[:id\]\)/, m + assert_match(/@admin_role = Admin::Role\.find\(params\[:id\]\)/, m) end assert_instance_method :create, content do |m| - assert_match /@admin_role = Admin::Role\.new\(params\[:admin_role\]\)/, m - assert_match /@admin_role\.save/, m - assert_match /@admin_role\.errors/, m + assert_match(/@admin_role = Admin::Role\.new\(params\[:admin_role\]\)/, m) + assert_match(/@admin_role\.save/, m) + assert_match(/@admin_role\.errors/, m) end assert_instance_method :update, content do |m| - assert_match /@admin_role = Admin::Role\.find\(params\[:id\]\)/, m - assert_match /@admin_role\.update_attributes\(params\[:admin_role\]\)/, m - assert_match /@admin_role\.errors/, m + assert_match(/@admin_role = Admin::Role\.find\(params\[:id\]\)/, m) + assert_match(/@admin_role\.update_attributes\(params\[:admin_role\]\)/, m) + assert_match(/@admin_role\.errors/, m) end assert_instance_method :destroy, content do |m| - assert_match /@admin_role = Admin::Role\.find\(params\[:id\]\)/, m - assert_match /@admin_role\.destroy/, m + assert_match(/@admin_role = Admin::Role\.find\(params\[:id\]\)/, m) + assert_match(/@admin_role\.destroy/, m) end end @@ -198,7 +201,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase # Route assert_file "config/routes.rb" do |route| - assert_no_match /namespace :admin do resources :roles end$/, route + assert_no_match(/namespace :admin do resources :roles end$/, route) end # Controller @@ -231,4 +234,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_file "config/routes.rb", /\.routes\.draw do\s*\|map\|\s*$/ end + + def test_scaffold_generator_outputs_error_message_on_missing_attribute_type + content = capture(:stderr) { run_generator ["post", "title:string", "body"]} + assert_match(/Missing type for attribute 'body'/, content) + assert_match(/Example: 'body:string' where string is the type/, content) + end end diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb new file mode 100644 index 0000000000..c9c5d2fad2 --- /dev/null +++ b/railties/test/generators/shared_generator_tests.rb @@ -0,0 +1,195 @@ +module SharedGeneratorTests + def setup + Rails.application = TestApp::Application + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + + Kernel::silence_warnings do + Thor::Base.shell.send(:attr_accessor, :always_force) + @shell = Thor::Base.shell.new + @shell.send(:always_force=, true) + end + end + + def teardown + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + Rails.application = TestApp::Application.instance + end + + def test_skeleton_is_created + run_generator + + default_files.each{ |path| assert_file path } + end + + def test_plugin_new_generate_pretend + run_generator ["testapp", "--pretend"] + default_files.each{ |path| assert_no_file File.join("testapp",path) } + end + + def test_invalid_database_option_raises_an_error + content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) } + assert_match(/Invalid value for \-\-database option/, content) + end + + def test_test_unit_is_skipped_if_required + run_generator [destination_root, "--skip-test-unit"] + assert_no_file "test" + end + + def test_options_before_application_name_raises_an_error + content = capture(:stderr){ run_generator(["--pretend", destination_root]) } + assert_match(/Options should be given after the \w+ name. For details run: rails( plugin)? --help\n/, content) + end + + def test_name_collision_raises_an_error + reserved_words = %w[application destroy plugin runner test] + reserved_words.each do |reserved| + content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } + assert_match(/Invalid \w+ name #{reserved}. Please give a name which does not match one of the reserved rails words.\n/, content) + end + end + + def test_name_raises_an_error_if_name_already_used_constant + %w{ String Hash Class Module Set Symbol }.each do |ruby_class| + content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] } + assert_match(/Invalid \w+ name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another \w+ name.\n/, content) + end + end + + def test_shebang_is_added_to_rails_file + run_generator [destination_root, "--ruby", "foo/bar/baz"] + assert_file "script/rails", /#!foo\/bar\/baz/ + end + + def test_shebang_when_is_the_same_as_default_use_env + run_generator [destination_root, "--ruby", Thor::Util.ruby_command] + assert_file "script/rails", /#!\/usr\/bin\/env/ + end + + def test_template_raises_an_error_with_invalid_path + content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } + assert_match(/The template \[.*\] could not be loaded/, content) + assert_match(/non\/existant\/path/, content) + end + + def test_template_is_executed_when_supplied + path = "http://gist.github.com/103208.txt" + 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) + assert_match(/It works!/, silence(:stdout){ generator.invoke_all }) + end + + def test_dev_option + generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + rails_path = File.expand_path('../../..', Rails.root) + assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ + end + + def test_edge_option + generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} + end + + def test_template_raises_an_error_with_invalid_path + content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } + assert_match(/The template \[.*\] could not be loaded/, content) + assert_match(/non\/existant\/path/, content) + end + + def test_template_is_executed_when_supplied + path = "http://gist.github.com/103208.txt" + 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) + assert_match(/It works!/, silence(:stdout){ generator.invoke_all }) + end + + def test_template_is_executed_when_supplied_an_https_path + path = "https://gist.github.com/103208.txt" + 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) + assert_match(/It works!/, silence(:stdout){ generator.invoke_all }) + end + + def test_dev_option + generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + rails_path = File.expand_path('../../..', Rails.root) + assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ + end + + def test_edge_option + generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} + end +end + +module SharedCustomGeneratorTests + def setup + Rails.application = TestApp::Application + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + end + + def teardown + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + Object.class_eval do + remove_const :AppBuilder if const_defined?(:AppBuilder) + remove_const :PluginBuilder if const_defined?(:PluginBuilder) + end + Rails.application = TestApp::Application.instance + end + + def test_builder_option_with_empty_app_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/empty_builder.rb"]) + default_files.each{ |path| assert_no_file path } + end + + def test_builder_option_with_simple_plugin_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/simple_builder.rb"]) + (default_files - ['.gitignore']).each{ |path| assert_no_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_relative_path + here = File.expand_path(File.dirname(__FILE__)) + FileUtils.cd(here) + run_generator([destination_root, "-b", "../fixtures/lib/#{builders_dir}/simple_builder.rb"]) + FileUtils.cd(destination_root) + (default_files - ['.gitignore']).each{ |path| assert_no_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_tweak_plugin_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/tweak_builder.rb"]) + default_files.each{ |path| assert_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_http + path = "http://gist.github.com/103208.txt" + template = "class #{builder_class}; end" + template.instance_eval "def read; self; end" # Make the string respond to read + + generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + capture(:stdout) { generator.invoke_all } + + default_files.each{ |path| assert_no_file(path) } + end +end diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb index f93800a5ae..99c9d790eb 100644 --- a/railties/test/generators_test.rb +++ b/railties/test/generators_test.rb @@ -94,6 +94,14 @@ class GeneratorsTest < Rails::Generators::TestCase assert_match /Rails 2\.x generator/, output end + def test_invoke_with_nested_namespaces + model_generator = mock('ModelGenerator') do + expects(:start).with(["Account"], {}) + end + Rails::Generators.expects(:find_by_namespace).with('namespace', 'my:awesome').returns(model_generator) + Rails::Generators.invoke 'my:awesome:namespace', ["Account"] + end + def test_rails_generators_help_with_builtin_information output = capture(:stdout){ Rails::Generators.help } assert_match /Rails:/, output @@ -102,6 +110,12 @@ class GeneratorsTest < Rails::Generators::TestCase assert_no_match /^ app$/, output end + def test_rails_generators_help_does_not_include_app_nor_plugin_new + output = capture(:stdout){ Rails::Generators.help } + assert_no_match /app/, output + assert_no_match /plugin_new/, output + end + def test_rails_generators_with_others_information output = capture(:stdout){ Rails::Generators.help } assert_match /Fixjour:/, output @@ -114,6 +128,16 @@ class GeneratorsTest < Rails::Generators::TestCase assert_match /^ active_record:fixjour$/, output end + def test_default_banner_should_show_generator_namespace + klass = Rails::Generators.find_by_namespace(:foobar) + assert_match /^rails generate foobar:foobar/, klass.banner + end + + def test_default_banner_should_not_show_rails_generator_namespace + klass = Rails::Generators.find_by_namespace(:model) + assert_match /^rails generate model/, klass.banner + end + def test_no_color_sets_proper_shell Rails::Generators.no_color! assert_equal Thor::Shell::Basic, Thor::Base.shell diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index 390c0ab543..c5b1cb9a80 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -19,6 +19,7 @@ RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..") # to run the tests require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/isolation" require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/testing/declarative" +require "#{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/core_ext/kernel/reporting" module TestHelpers module Paths @@ -44,6 +45,17 @@ module TestHelpers end module Rack + def app(env = "production") + old_env = ENV["RAILS_ENV"] + @app ||= begin + ENV["RAILS_ENV"] = env + require "#{app_path}/config/environment" + Rails.application + end + ensure + ENV["RAILS_ENV"] = old_env + end + def extract_body(response) "".tap do |body| response[2].each {|chunk| body << chunk } @@ -123,6 +135,22 @@ module TestHelpers extend ::Rack::Test::Methods end + def simple_controller + controller :foo, <<-RUBY + class FooController < ApplicationController + def index + render :text => "foo" + end + end + RUBY + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match ':controller(/:action)' + end + RUBY + end + class Bukkit attr_reader :path @@ -187,6 +215,13 @@ module TestHelpers end end + def remove_from_config(str) + file = "#{app_path}/config/application.rb" + contents = File.read(file) + contents.sub!(/#{str}/, "") + File.open(file, "w+") { |f| f.puts contents } + end + def app_file(path, contents) FileUtils.mkdir_p File.dirname("#{app_path}/#{path}") File.open("#{app_path}/#{path}", 'w') do |f| @@ -203,6 +238,7 @@ module TestHelpers :activemodel, :activerecord, :activeresource] - arr + remove_from_config "config.active_record.identity_map = true" if to_remove.include? :activerecord $:.reject! {|path| path =~ %r'/(#{to_remove.join('|')})/' } end diff --git a/railties/test/paths_test.rb b/railties/test/paths_test.rb index 80fae8c543..6e4e3446b3 100644 --- a/railties/test/paths_test.rb +++ b/railties/test/paths_test.rb @@ -20,234 +20,264 @@ class PathsTest < ActiveSupport::TestCase test "a paths object initialized with nil can be updated" do root = Rails::Paths::Root.new(nil) - root.app = "app" + root.add "app" root.path = "/root" - assert_equal ["/root/app"], root.app.to_a + assert_equal ["app"], root["app"] + assert_equal ["/root/app"], root["app"].to_a end test "creating a root level path" do - @root.app = "/foo/bar" - assert_equal ["/foo/bar"], @root.app.to_a + @root.add "app" + assert_equal ["/foo/bar/app"], @root["app"].to_a + end + + test "creating a root level path with options" do + @root.add "app", :with => "/foo/bar" + assert_equal ["/foo/bar"], @root["app"].to_a end test "raises exception if root path never set" do root = Rails::Paths::Root.new(nil) - root.app = "app" + root.add "app" assert_raises RuntimeError do - root.app.to_a + root["app"].to_a end end - test "creating a root level path without assignment" do - @root.app "/foo/bar" - assert_equal ["/foo/bar"], @root.app.to_a - end - - test "trying to access a path that does not exist raises NoMethodError" do - assert_raises(NoMethodError) { @root.app } - end - - test "relative paths are relative to the paths root" do - @root.app = "app" - assert_equal ["/foo/bar/app"], @root.app.to_a - end - - test "relative paths are relative to the paths root without assignment" do - @root.app "app" - assert_equal ["/foo/bar/app"], @root.app.to_a - end - test "creating a child level path" do - @root.app = "/foo/bar" - @root.app.models = "/foo/bar/baz" - assert_equal ["/foo/bar/baz"], @root.app.models.to_a + @root.add "app" + @root.add "app/models" + assert_equal ["/foo/bar/app/models"], @root["app/models"].to_a end - test "creating a child level path without assignment" do - @root.app = "/foo/bar" - @root.app.models "/foo/bar/baz" - assert_equal ["/foo/bar/baz"], @root.app.models.to_a + test "creating a child level path with option" do + @root.add "app" + @root.add "app/models", :with => "/foo/bar/baz" + assert_equal ["/foo/bar/baz"], @root["app/models"].to_a end test "child level paths are relative from the root" do - @root.app = "/app" - @root.app.models = "baz" - - assert_equal ["/foo/bar/baz"], @root.app.models.to_a + @root.add "app" + @root.add "app/models", :with => "baz" + assert_equal ["/foo/bar/baz"], @root["app/models"].to_a end test "adding multiple physical paths as an array" do - @root.app = ["/app", "/app2"] - assert_equal ["/app", "/app2"], @root.app.to_a - end - - test "adding multiple physical paths as an array without assignment" do - @root.app "/app", "/app2" - assert_equal ["/app", "/app2"], @root.app.to_a + @root.add "app", :with => ["/app", "/app2"] + assert_equal ["/app", "/app2"], @root["app"].to_a end test "adding multiple physical paths using #push" do - @root.app = "/app" - @root.app.push "/app2" - assert_equal ["/app", "/app2"], @root.app.to_a + @root.add "app" + @root["app"].push "app2" + assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a end test "adding multiple physical paths using <<" do - @root.app = "/app" - @root.app << "/app2" - assert_equal ["/app", "/app2"], @root.app.to_a + @root.add "app" + @root["app"] << "app2" + assert_equal ["/foo/bar/app", "/foo/bar/app2"], @root["app"].to_a end test "adding multiple physical paths using concat" do - @root.app = "/app" - @root.app.concat ["/app2", "/app3"] - assert_equal ["/app", "/app2", "/app3"], @root.app.to_a + @root.add "app" + @root["app"].concat ["app2", "/app3"] + assert_equal ["/foo/bar/app", "/foo/bar/app2", "/app3"], @root["app"].to_a end test "adding multiple physical paths using #unshift" do - @root.app = "/app" - @root.app.unshift "/app2" - assert_equal ["/app2", "/app"], @root.app.to_a + @root.add "app" + @root["app"].unshift "app2" + assert_equal ["/foo/bar/app2", "/foo/bar/app"], @root["app"].to_a end test "the root can only have one physical path" do assert_raise(RuntimeError) { Rails::Paths::Root.new(["/fiz", "/biz"]) } - assert_raise(RuntimeError) { @root.push "/biz" } - assert_raise(RuntimeError) { @root.unshift "/biz" } - assert_raise(RuntimeError) { @root.concat ["/biz"]} - assert_raise(RuntimeError) { @root << "/biz" } end test "it is possible to add a path that should be autoloaded only once" do - @root.app = "/app" - @root.app.autoload_once! - assert @root.app.autoload_once? - assert @root.autoload_once.include?(@root.app.paths.first) + @root.add "app", :with => "/app" + @root["app"].autoload_once! + assert @root["app"].autoload_once? + assert @root.autoload_once.include?(@root["app"].expanded.first) end test "it is possible to remove a path that should be autoloaded only once" do - @root.app = "/app" - @root.app.autoload_once! - assert @root.app.autoload_once? + @root["app"] = "/app" + @root["app"].autoload_once! + assert @root["app"].autoload_once? - @root.app.skip_autoload_once! - assert !@root.app.autoload_once? - assert !@root.autoload_once.include?(@root.app.paths.first) + @root["app"].skip_autoload_once! + assert !@root["app"].autoload_once? + assert !@root.autoload_once.include?(@root["app"].expanded.first) end test "it is possible to add a path without assignment and specify it should be loaded only once" do - @root.app "/app", :autoload_once => true - assert @root.app.autoload_once? + @root.add "app", :with => "/app", :autoload_once => true + assert @root["app"].autoload_once? assert @root.autoload_once.include?("/app") end test "it is possible to add multiple paths without assignment and specify it should be loaded only once" do - @root.app "/app", "/app2", :autoload_once => true - assert @root.app.autoload_once? + @root.add "app", :with => ["/app", "/app2"], :autoload_once => true + assert @root["app"].autoload_once? assert @root.autoload_once.include?("/app") assert @root.autoload_once.include?("/app2") end test "making a path autoload_once more than once only includes it once in @root.load_once" do - @root.app = "/app" - @root.app.autoload_once! - @root.app.autoload_once! - assert_equal 1, @root.autoload_once.select {|p| p == @root.app.paths.first }.size + @root["app"] = "/app" + @root["app"].autoload_once! + @root["app"].autoload_once! + assert_equal 1, @root.autoload_once.select {|p| p == @root["app"].expanded.first }.size end test "paths added to a load_once path should be added to the autoload_once collection" do - @root.app = "/app" - @root.app.autoload_once! - @root.app << "/app2" + @root["app"] = "/app" + @root["app"].autoload_once! + @root["app"] << "/app2" assert_equal 2, @root.autoload_once.size end test "it is possible to mark a path as eager loaded" do - @root.app = "/app" - @root.app.eager_load! - assert @root.app.eager_load? - assert @root.eager_load.include?(@root.app.paths.first) + @root["app"] = "/app" + @root["app"].eager_load! + assert @root["app"].eager_load? + assert @root.eager_load.include?(@root["app"].to_a.first) end test "it is possible to skip a path from eager loading" do - @root.app = "/app" - @root.app.eager_load! - assert @root.app.eager_load? + @root["app"] = "/app" + @root["app"].eager_load! + assert @root["app"].eager_load? - @root.app.skip_eager_load! - assert !@root.app.eager_load? - assert !@root.eager_load.include?(@root.app.paths.first) + @root["app"].skip_eager_load! + assert !@root["app"].eager_load? + assert !@root.eager_load.include?(@root["app"].to_a.first) end test "it is possible to add a path without assignment and mark it as eager" do - @root.app "/app", :eager_load => true - assert @root.app.eager_load? + @root.add "app", :with => "/app", :eager_load => true + assert @root["app"].eager_load? assert @root.eager_load.include?("/app") end test "it is possible to add multiple paths without assignment and mark them as eager" do - @root.app "/app", "/app2", :eager_load => true - assert @root.app.eager_load? + @root.add "app", :with => ["/app", "/app2"], :eager_load => true + assert @root["app"].eager_load? assert @root.eager_load.include?("/app") assert @root.eager_load.include?("/app2") end test "it is possible to create a path without assignment and mark it both as eager and load once" do - @root.app "/app", :eager_load => true, :autoload_once => true - assert @root.app.eager_load? - assert @root.app.autoload_once? + @root.add "app", :with => "/app", :eager_load => true, :autoload_once => true + assert @root["app"].eager_load? + assert @root["app"].autoload_once? assert @root.eager_load.include?("/app") assert @root.autoload_once.include?("/app") end test "making a path eager more than once only includes it once in @root.eager_paths" do - @root.app = "/app" - @root.app.eager_load! - @root.app.eager_load! - assert_equal 1, @root.eager_load.select {|p| p == @root.app.paths.first }.size + @root["app"] = "/app" + @root["app"].eager_load! + @root["app"].eager_load! + assert_equal 1, @root.eager_load.select {|p| p == @root["app"].expanded.first }.size end test "paths added to a eager_load path should be added to the eager_load collection" do - @root.app = "/app" - @root.app.eager_load! - @root.app << "/app2" + @root["app"] = "/app" + @root["app"].eager_load! + @root["app"] << "/app2" assert_equal 2, @root.eager_load.size end test "it should be possible to add a path's default glob" do - @root.app = "/app" - @root.app.glob = "*.rb" - assert_equal "*.rb", @root.app.glob + @root["app"] = "/app" + @root["app"].glob = "*.rb" + assert_equal "*.rb", @root["app"].glob end test "it should be possible to override a path's default glob without assignment" do - @root.app "/app", :glob => "*.rb" - assert_equal "*.rb", @root.app.glob + @root.add "app", :with => "/app", :glob => "*.rb" + assert_equal "*.rb", @root["app"].glob end test "a path can be added to the load path" do - @root.app = "app" - @root.app.load_path! - @root.app.models = "app/models" + @root["app"] = "app" + @root["app"].load_path! + @root["app/models"] = "app/models" assert_equal ["/foo/bar/app"], @root.load_paths end test "a path can be added to the load path on creation" do - @root.app "/app", :load_path => true - assert @root.app.load_path? + @root.add "app", :with => "/app", :load_path => true + assert @root["app"].load_path? assert_equal ["/app"], @root.load_paths end test "a path can be marked as autoload path" do - @root.app = "app" - @root.app.autoload! - @root.app.models = "app/models" + @root["app"] = "app" + @root["app"].autoload! + @root["app/models"] = "app/models" assert_equal ["/foo/bar/app"], @root.autoload_paths end test "a path can be marked as autoload on creation" do - @root.app "/app", :autoload => true - assert @root.app.autoload? + @root.add "app", :with => "/app", :autoload => true + assert @root["app"].autoload? assert_equal ["/app"], @root.autoload_paths end + + # Deprecated API tests + + test "reading a root level path with assignment" do + @root.add "app" + assert_deprecated do + assert_equal ["/foo/bar/app"], @root.app.to_a + end + end + + test "creating a root level path with assignment" do + assert_deprecated do + @root.app = "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app"].to_a + end + + test "creating a root level path without assignment" do + assert_deprecated do + @root.app "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app"].to_a + end + + test "reading a nested level path with assignment" do + @root.add "app" + @root.add "app/model" + assert_deprecated do + assert_equal ["/foo/bar/app/model"], @root.app.model.to_a + end + end + + test "creating a nested level path with assignment" do + @root.add "app" + assert_deprecated do + @root.app.model = "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app/model"].to_a + end + + test "creating a nested level path without assignment" do + @root.add "app" + assert_deprecated do + @root.app.model "/foo/bar" + end + assert_equal ["/foo/bar"], @root["app/model"].to_a + end + + test "trying to access a path that does not exist raises NoMethodError" do + assert_deprecated do + assert_raises(NoMethodError) { @root.app } + end + end end diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index 687c2d1568..9d194f41a6 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -14,26 +14,28 @@ class InfoControllerTest < ActionController::TestCase Rails.application.routes.draw do match '/rails/info/properties' => "rails/info#properties" end - @controller.stubs(:consider_all_requests_local? => false, :local_request? => true) + @request.stubs(:local? => true) + @controller.stubs(:consider_all_requests_local? => false) @routes = Rails.application.routes Rails::InfoController.send(:include, @routes.url_helpers) end test "info controller does not allow remote requests" do - @controller.stubs(:consider_all_requests_local? => false, :local_request? => false) + @request.stubs(:local? => false) get :properties assert_response :forbidden end test "info controller renders an error message when request was forbidden" do - @controller.stubs(:consider_all_requests_local? => false, :local_request? => false) + @request.stubs(:local? => false) get :properties assert_select 'p' end test "info controller allows requests when all requests are considered local" do - @controller.stubs(:consider_all_requests_local? => true, :local_request? => false) + @request.stubs(:local? => false) + @controller.stubs(:consider_all_requests_local? => true) get :properties assert_response :success end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 7410a10712..0ce00db3c4 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -1,10 +1,15 @@ require "isolation/abstract_unit" require "railties/shared_tests" +require 'stringio' +require 'rack/test' +require 'rack/file' module RailtiesTest class EngineTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation include SharedTests + include Rack::Test::Methods def setup build_app @@ -13,6 +18,7 @@ module RailtiesTest plugin.write "lib/bukkits.rb", <<-RUBY class Bukkits class Engine < ::Rails::Engine + railtie_name "bukkits" end end RUBY @@ -50,5 +56,750 @@ module RailtiesTest assert index < initializers.index { |i| i.name == :build_middleware_stack } end + + + class Upcaser + def initialize(app) + @app = app + end + + def call(env) + response = @app.call(env) + response[2].each { |b| b.upcase! } + response + end + end + + test "engine is a rack app and can have his own middleware stack" do + add_to_config("config.action_dispatch.show_exceptions = false") + + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['Hello World']] } + config.middleware.use ::RailtiesTest::EngineTest::Upcaser + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + mount(Bukkits::Engine => "/bukkits") + end + RUBY + + boot_rails + + get("/bukkits") + assert_equal "HELLO WORLD", last_response.body + end + + test "it provides routes as default endpoint" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/foo" => lambda { |env| [200, {'Content-Type' => 'text/html'}, ['foo']] } + end + RUBY + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + mount(Bukkits::Engine => "/bukkits") + end + RUBY + + boot_rails + + get("/bukkits/foo") + assert_equal "foo", last_response.body + end + + test "engine can load its own plugins" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + @plugin.write "vendor/plugins/yaffle/init.rb", <<-RUBY + config.yaffle_loaded = true + RUBY + + boot_rails + + assert Bukkits::Engine.config.yaffle_loaded + end + + test "engine does not load plugins that already exists in application" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + @plugin.write "vendor/plugins/yaffle/init.rb", <<-RUBY + config.engine_yaffle_loaded = true + RUBY + + app_file "vendor/plugins/yaffle/init.rb", <<-RUBY + config.app_yaffle_loaded = true + RUBY + + warnings = capture(:stderr) { boot_rails } + + assert !warnings.empty? + assert !Bukkits::Engine.config.respond_to?(:engine_yaffle_loaded) + assert Rails.application.config.app_yaffle_loaded + end + + test "it loads its environment file" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + @plugin.write "config/environments/development.rb", <<-RUBY + Bukkits::Engine.configure do + config.environment_loaded = true + end + RUBY + + boot_rails + + assert Bukkits::Engine.config.environment_loaded + end + + test "it passes router in env" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, 'hello'] } + end + end + RUBY + + boot_rails + + env = Rack::MockRequest.env_for("/") + Bukkits::Engine.call(env) + assert_equal Bukkits::Engine.routes, env['action_dispatch.routes'] + + env = Rack::MockRequest.env_for("/") + Rails.application.call(env) + assert_equal Rails.application.routes, env['action_dispatch.routes'] + end + + test "it allows to set asset_path" do + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/foo" => "foo#index" + end + RUBY + + @plugin.write "app/controllers/foo_controller.rb", <<-RUBY + class FooController < ActionController::Base + def index + render :index + end + end + RUBY + + @plugin.write "app/views/foo/index.html.erb", <<-ERB + <%= image_path("foo.png") %> + <%= javascript_include_tag("foo") %> + <%= stylesheet_link_tag("foo") %> + ERB + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + mount Bukkits::Engine => "/bukkits" + end + RUBY + + add_to_config 'config.asset_path = "/omg%s"' + + boot_rails + + # should set asset_path with engine name by default + assert_equal "/bukkits_engine%s", ::Bukkits::Engine.config.asset_path + + ::Bukkits::Engine.config.asset_path = "/bukkits%s" + + get("/bukkits/foo") + stripped_body = last_response.body.split("\n").map(&:strip).join + + expected = "/omg/bukkits/images/foo.png" + + "<script src=\"/omg/bukkits/javascripts/foo.js\" type=\"text/javascript\"></script>" + + "<link href=\"/omg/bukkits/stylesheets/foo.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />" + assert_equal expected, stripped_body + end + + test "default application's asset_path" do + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/foo" => "foo#index" + end + RUBY + + @plugin.write "app/controllers/foo_controller.rb", <<-RUBY + class FooController < ActionController::Base + def index + render :inline => '<%= image_path("foo.png") %>' + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + mount Bukkits::Engine => "/bukkits" + end + RUBY + + boot_rails + + get("/bukkits/foo") + assert_equal "/bukkits/images/foo.png", last_response.body.strip + end + + test "engine's files are served via ActionDispatch::Static" do + add_to_config "config.serve_static_assets = true" + + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + engine_name :bukkits + end + end + RUBY + + @plugin.write "public/bukkits.html", "/bukkits/bukkits.html" + app_file "public/app.html", "/app.html" + app_file "public/bukkits/file_from_app.html", "/bukkits/file_from_app.html" + + boot_rails + + get("/app.html") + assert_equal File.read(File.join(app_path, "public/app.html")), last_response.body + + get("/bukkits/bukkits.html") + assert_equal File.read(File.join(@plugin.path, "public/bukkits.html")), last_response.body + + get("/bukkits/file_from_app.html") + assert_equal File.read(File.join(app_path, "public/bukkits/file_from_app.html")), last_response.body + end + + test "an applications files are given priority over an engines files when served via ActionDispatch::Static" do + add_to_config "config.serve_static_assets = true" + + @plugin.write "lib/bukkits.rb", <<-RUBY + class Bukkits + class Engine < ::Rails::Engine + engine_name :bukkits + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + mount Bukkits::Engine => "/bukkits" + end + RUBY + + @plugin.write "public/bukkits.html", "in engine" + + app_file "public/bukkits/bukkits.html", "in app" + + boot_rails + + get('/bukkits/bukkits.html') + + assert_equal 'in app', last_response.body.strip + end + + test "shared engine should include application's helpers and own helpers" do + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + match "/foo" => "bukkits/foo#index", :as => "foo" + match "/foo/show" => "bukkits/foo#show" + match "/foo/bar" => "bukkits/foo#bar" + end + RUBY + + app_file "app/helpers/some_helper.rb", <<-RUBY + module SomeHelper + def something + "Something... Something... Something..." + end + end + RUBY + + @plugin.write "app/helpers/bar_helper.rb", <<-RUBY + module BarHelper + def bar + "It's a bar." + end + end + RUBY + + @plugin.write "app/controllers/bukkits/foo_controller.rb", <<-RUBY + class Bukkits::FooController < ActionController::Base + def index + render :inline => "<%= something %>" + end + + def show + render :text => foo_path + end + + def bar + render :inline => "<%= bar %>" + end + end + RUBY + + boot_rails + + get("/foo") + assert_equal "Something... Something... Something...", last_response.body + + get("/foo/show") + assert_equal "/foo", last_response.body + + get("/foo/bar") + assert_equal "It's a bar.", last_response.body + end + + test "isolated engine should include only its own routes and helpers" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + isolate_namespace Bukkits + end + end + RUBY + + @plugin.write "app/models/bukkits/post.rb", <<-RUBY + module Bukkits + class Post + extend ActiveModel::Naming + + def to_param + "1" + end + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + match "/bar" => "bar#index", :as => "bar" + mount Bukkits::Engine => "/bukkits", :as => "bukkits" + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/foo" => "foo#index", :as => "foo" + match "/foo/show" => "foo#show" + match "/from_app" => "foo#from_app" + match "/routes_helpers_in_view" => "foo#routes_helpers_in_view" + match "/polymorphic_path_without_namespace" => "foo#polymorphic_path_without_namespace" + resources :posts + end + RUBY + + app_file "app/helpers/some_helper.rb", <<-RUBY + module SomeHelper + def something + "Something... Something... Something..." + end + end + RUBY + + @plugin.write "app/helpers/engine_helper.rb", <<-RUBY + module EngineHelper + def help_the_engine + "Helped." + end + end + RUBY + + @plugin.write "app/controllers/bukkits/foo_controller.rb", <<-RUBY + class Bukkits::FooController < ActionController::Base + def index + render :inline => "<%= help_the_engine %>" + end + + def show + render :text => foo_path + end + + def from_app + render :inline => "<%= (self.respond_to?(:bar_path) || self.respond_to?(:something)) %>" + end + + def routes_helpers_in_view + render :inline => "<%= foo_path %>, <%= main_app.bar_path %>" + end + + def polymorphic_path_without_namespace + render :text => polymorphic_path(Post.new) + end + end + RUBY + + @plugin.write "app/mailers/bukkits/my_mailer.rb", <<-RUBY + module Bukkits + class MyMailer < ActionMailer::Base + end + end + RUBY + + add_to_config("config.action_dispatch.show_exceptions = false") + + boot_rails + + assert_equal "bukkits_", Bukkits.table_name_prefix + assert_equal "bukkits", Bukkits::Engine.engine_name + assert_equal Bukkits._railtie, Bukkits::Engine + assert ::Bukkits::MyMailer.method_defined?(:foo_path) + assert !::Bukkits::MyMailer.method_defined?(:bar_path) + + get("/bukkits/from_app") + assert_equal "false", last_response.body + + get("/bukkits/foo/show") + assert_equal "/bukkits/foo", last_response.body + + get("/bukkits/foo") + assert_equal "Helped.", last_response.body + + get("/bukkits/routes_helpers_in_view") + assert_equal "/bukkits/foo, /bar", last_response.body + + get("/bukkits/polymorphic_path_without_namespace") + assert_equal "/bukkits/posts/1", last_response.body + end + + test "isolated engine should avoid namespace in names if that's possible" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + isolate_namespace Bukkits + end + end + RUBY + + @plugin.write "app/models/bukkits/post.rb", <<-RUBY + module Bukkits + class Post + extend ActiveModel::Naming + include ActiveModel::Conversion + attr_accessor :title + + def to_param + "1" + end + + def persisted? + false + end + end + end + RUBY + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do + mount Bukkits::Engine => "/bukkits", :as => "bukkits" + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + resources :posts + end + RUBY + + @plugin.write "app/controllers/bukkits/posts_controller.rb", <<-RUBY + class Bukkits::PostsController < ActionController::Base + def new + end + end + RUBY + + @plugin.write "app/views/bukkits/posts/new.html.erb", <<-ERB + <%= form_for(Bukkits::Post.new) do |f| %> + <%= f.text_field :title %> + <% end %> + ERB + + add_to_config("config.action_dispatch.show_exceptions = false") + + boot_rails + + get("/bukkits/posts/new") + assert_match /name="post\[title\]"/, last_response.body + end + + test "loading seed data" do + @plugin.write "db/seeds.rb", <<-RUBY + Bukkits::Engine.config.bukkits_seeds_loaded = true + RUBY + + app_file "db/seeds.rb", <<-RUBY + Rails.application.config.app_seeds_loaded = true + RUBY + + boot_rails + + Rails.application.load_seed + assert Rails.application.config.app_seeds_loaded + assert_raise(NoMethodError) do Bukkits::Engine.config.bukkits_seeds_loaded end + + Bukkits::Engine.load_seed + assert Bukkits::Engine.config.bukkits_seeds_loaded + end + + test "using namespace more than once on one module should not overwrite _railtie method" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module AppTemplate + class Engine < ::Rails::Engine + isolate_namespace(AppTemplate) + end + end + RUBY + + add_to_config "isolate_namespace AppTemplate" + + app_file "config/routes.rb", <<-RUBY + AppTemplate::Application.routes.draw do end + RUBY + + boot_rails + + assert_equal AppTemplate._railtie, AppTemplate::Engine + end + + test "properly reload routes" do + # when routes are inside application class definition + # they should not be reloaded when engine's routes + # file has changed + add_to_config <<-RUBY + routes do + mount lambda{|env| [200, {}, ["foo"]]} => "/foo" + mount Bukkits::Engine => "/bukkits" + end + RUBY + + FileUtils.rm(File.join(app_path, "config/routes.rb")) + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + mount lambda{|env| [200, {}, ["bar"]]} => "/bar" + end + RUBY + + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + isolate_namespace(Bukkits) + end + end + RUBY + + boot_rails + + require "#{rails_root}/config/environment" + + get("/foo") + assert_equal "foo", last_response.body + + get("/bukkits/bar") + assert_equal "bar", last_response.body + end + + test "setting generators for engine and overriding app generator's" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + config.generators do |g| + g.orm :datamapper + g.template_engine :haml + g.test_framework :rspec + end + + config.app_generators do |g| + g.orm :mongoid + g.template_engine :liquid + g.test_framework :shoulda + end + end + end + RUBY + + add_to_config <<-RUBY + config.generators do |g| + g.test_framework :test_unit + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + app_generators = Rails.application.config.generators.options[:rails] + assert_equal :mongoid , app_generators[:orm] + assert_equal :liquid , app_generators[:template_engine] + assert_equal :test_unit, app_generators[:test_framework] + + generators = Bukkits::Engine.config.generators.options[:rails] + assert_equal :datamapper, generators[:orm] + assert_equal :haml , generators[:template_engine] + assert_equal :rspec , generators[:test_framework] + end + + test "engine should get default generators with ability to overwrite them" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + config.generators.test_framework :rspec + end + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + generators = Bukkits::Engine.config.generators.options[:rails] + assert_equal :active_record, generators[:orm] + assert_equal :rspec , generators[:test_framework] + + app_generators = Rails.application.config.generators.options[:rails] + assert_equal :test_unit , app_generators[:test_framework] + end + + test "do not create table_name_prefix method if it already exists" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + def self.table_name_prefix + "foo" + end + + class Engine < ::Rails::Engine + isolate_namespace(Bukkits) + end + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + assert_equal "foo", Bukkits.table_name_prefix + end + + test "fetching engine by path" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + end + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + assert_equal Bukkits::Engine.instance, Rails::Engine.find(@plugin.path) + + # check expanding paths + engine_dir = @plugin.path.chomp("/").split("/").last + engine_path = File.join(@plugin.path, '..', engine_dir) + assert_equal Bukkits::Engine.instance, Rails::Engine.find(engine_path) + end + + test "ensure that engine properly sets assets directories" do + add_to_config("config.action_dispatch.show_exceptions = false") + add_to_config("config.serve_static_assets = true") + + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + isolate_namespace Bukkits + end + end + RUBY + + @plugin.write "public/stylesheets/foo.css", "" + @plugin.write "public/javascripts/foo.js", "" + + @plugin.write "app/views/layouts/bukkits/application.html.erb", <<-RUBY + <%= stylesheet_link_tag :all %> + <%= javascript_include_tag :all %> + <%= yield %> + RUBY + + @plugin.write "app/controllers/bukkits/home_controller.rb", <<-RUBY + module Bukkits + class HomeController < ActionController::Base + def index + render :text => "Good morning!", :layout => "bukkits/application" + end + end + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Bukkits::Engine.routes.draw do + match "/home" => "home#index" + end + RUBY + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + mount Bukkits::Engine => "/bukkits" + end + RUBY + + require 'rack/test' + extend Rack::Test::Methods + + boot_rails + + require "#{rails_root}/config/environment" + + assert_equal File.join(@plugin.path, "public"), Bukkits::HomeController.assets_dir + assert_equal File.join(@plugin.path, "public/stylesheets"), Bukkits::HomeController.stylesheets_dir + assert_equal File.join(@plugin.path, "public/javascripts"), Bukkits::HomeController.javascripts_dir + + assert_equal File.join(app_path, "public"), ActionController::Base.assets_dir + assert_equal File.join(app_path, "public/stylesheets"), ActionController::Base.stylesheets_dir + assert_equal File.join(app_path, "public/javascripts"), ActionController::Base.javascripts_dir + + get "/bukkits/home" + + assert_match %r{bukkits/stylesheets/foo.css}, last_response.body + assert_match %r{bukkits/javascripts/foo.js}, last_response.body + end + + private + def app + Rails.application + end end end diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb new file mode 100644 index 0000000000..47a4753e78 --- /dev/null +++ b/railties/test/railties/mounted_engine_test.rb @@ -0,0 +1,174 @@ +require 'isolation/abstract_unit' + +module ApplicationTests + class ApplicationRoutingTest < Test::Unit::TestCase + require 'rack/test' + include Rack::Test::Methods + include ActiveSupport::Testing::Isolation + + def setup + build_app + + add_to_config("config.action_dispatch.show_exceptions = false") + + @plugin = engine "blog" + + app_file 'config/routes.rb', <<-RUBY + AppTemplate::Application.routes.draw do + match "/engine_route" => "application_generating#engine_route" + match "/engine_route_in_view" => "application_generating#engine_route_in_view" + match "/url_for_engine_route" => "application_generating#url_for_engine_route" + match "/polymorphic_route" => "application_generating#polymorphic_route" + scope "/:user", :user => "anonymous" do + mount Blog::Engine => "/blog" + end + root :to => 'main#index' + end + RUBY + + @plugin.write "app/models/blog/post.rb", <<-RUBY + module Blog + class Post + extend ActiveModel::Naming + + def id + 44 + end + + def to_param + id.to_s + end + + def new_record? + false + end + end + end + RUBY + + @plugin.write "lib/blog.rb", <<-RUBY + module Blog + class Engine < ::Rails::Engine + isolate_namespace(Blog) + end + end + RUBY + + @plugin.write "config/routes.rb", <<-RUBY + Blog::Engine.routes.draw do + resources :posts + match '/generate_application_route', :to => 'posts#generate_application_route' + match '/application_route_in_view', :to => 'posts#application_route_in_view' + end + RUBY + + @plugin.write "app/controllers/blog/posts_controller.rb", <<-RUBY + module Blog + class PostsController < ActionController::Base + def index + render :text => blog.post_path(1) + end + + def generate_application_route + path = main_app.url_for(:controller => "/main", + :action => "index", + :only_path => true) + render :text => path + end + + def application_route_in_view + render :inline => "<%= main_app.root_path %>" + end + end + end + RUBY + + app_file "app/controllers/application_generating_controller.rb", <<-RUBY + class ApplicationGeneratingController < ActionController::Base + def engine_route + render :text => blog.posts_path + end + + def engine_route_in_view + render :inline => "<%= blog.posts_path %>" + end + + def url_for_engine_route + render :text => blog.url_for(:controller => "blog/posts", :action => "index", :user => "john", :only_path => true) + end + + def polymorphic_route + render :text => polymorphic_url([blog, Blog::Post.new]) + end + end + RUBY + + boot_rails + end + + def app + @app ||= begin + require "#{app_path}/config/environment" + Rails.application + end + end + + def reset_script_name! + Rails.application.routes.default_url_options = {} + end + + def script_name(script_name) + Rails.application.routes.default_url_options = {:script_name => script_name} + end + + test "routes generation in engine and application" do + # test generating engine's route from engine + get "/john/blog/posts" + assert_equal "/john/blog/posts/1", last_response.body + + # test generating engine's route from engine with default_url_options + script_name "/foo" + get "/john/blog/posts", {}, 'SCRIPT_NAME' => "/foo" + assert_equal "/foo/john/blog/posts/1", last_response.body + reset_script_name! + + # test generating engine's route from application + get "/engine_route" + assert_equal "/anonymous/blog/posts", last_response.body + + get "/engine_route_in_view" + assert_equal "/anonymous/blog/posts", last_response.body + + get "/url_for_engine_route" + assert_equal "/john/blog/posts", last_response.body + + # test generating engine's route from application with default_url_options + script_name "/foo" + get "/engine_route", {}, 'SCRIPT_NAME' => "/foo" + assert_equal "/foo/anonymous/blog/posts", last_response.body + + script_name "/foo" + get "/url_for_engine_route", {}, 'SCRIPT_NAME' => "/foo" + assert_equal "/foo/john/blog/posts", last_response.body + reset_script_name! + + # test generating application's route from engine + get "/someone/blog/generate_application_route" + assert_equal "/", last_response.body + + get "/somone/blog/application_route_in_view" + assert_equal "/", last_response.body + + # test generating application's route from engine with default_url_options + script_name "/foo" + get "/someone/blog/generate_application_route", {}, 'SCRIPT_NAME' => '/foo' + assert_equal "/foo/", last_response.body + reset_script_name! + + # test polymorphic routes + get "/polymorphic_route" + assert_equal "http://example.org/anonymous/blog/posts/44", last_response.body + end + end +end + diff --git a/railties/test/railties/plugin_test.rb b/railties/test/railties/plugin_test.rb index b143f56484..c15ac05103 100644 --- a/railties/test/railties/plugin_test.rb +++ b/railties/test/railties/plugin_test.rb @@ -110,37 +110,10 @@ module RailtiesTest boot_rails rescue Exception => e rescued = true - assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as plugin', e.message + assert_equal '"bukkits" is a Railtie/Engine and cannot be installed as a plugin', e.message end assert rescued, "Expected boot rails to fail" end - - test "loads deprecated rails/init.rb" do - @plugin.write "rails/init.rb", <<-RUBY - $loaded = true - RUBY - - boot_rails - assert $loaded - end - - test "deprecated tasks are also loaded" do - $executed = false - @plugin.write "tasks/foo.rake", <<-RUBY - task :foo do - $executed = true - end - RUBY - - boot_rails - require 'rake' - require 'rake/rdoctask' - require 'rake/testtask' - Rails.application.load_tasks - Rake::Task[:foo].invoke - assert $executed - end - end end diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb index db0fd87491..7ea8364ae9 100644 --- a/railties/test/railties/railtie_test.rb +++ b/railties/test/railties/railtie_test.rb @@ -19,6 +19,22 @@ module RailtiesTest assert !Rails::Railtie.respond_to?(:config) end + test "Railtie provides railtie_name" do + begin + class ::FooBarBaz < Rails::Railtie ; end + assert_equal "foo_bar_baz", ::FooBarBaz.railtie_name + ensure + Object.send(:remove_const, :"FooBarBaz") + end + end + + test "railtie_name can be set manualy" do + class Foo < Rails::Railtie + railtie_name "bar" + end + assert_equal "bar", Foo.railtie_name + end + test "cannot inherit from a railtie" do class Foo < Rails::Railtie ; end assert_raise RuntimeError do @@ -87,6 +103,30 @@ module RailtiesTest assert $ran_block end + test "rake_tasks block defined in superclass of railtie is also executed" do + $ran_block = [] + + class Rails::Railtie + rake_tasks do + $ran_block << railtie_name + end + end + + class MyTie < Rails::Railtie + railtie_name "my_tie" + end + + require "#{app_path}/config/environment" + + assert_equal [], $ran_block + require 'rake' + require 'rake/testtask' + require 'rake/rdoctask' + + AppTemplate::Application.load_tasks + assert $ran_block.include?("my_tie") + end + test "generators block is executed when MyApp.load_generators is called" do $ran_block = false @@ -132,7 +172,7 @@ module RailtiesTest require "#{app_path}/config/environment" assert $ran_block end - + test "we can change our environment if we want to" do begin original_env = Rails.env diff --git a/railties/test/railties/shared_tests.rb b/railties/test/railties/shared_tests.rb index ce7c55c11c..3eb79d57c8 100644 --- a/railties/test/railties/shared_tests.rb +++ b/railties/test/railties/shared_tests.rb @@ -10,6 +10,100 @@ module RailtiesTest @app ||= Rails.application end + def test_install_migrations_and_assets + @plugin.write "public/javascripts/foo.js", "doSomething()" + + @plugin.write "db/migrate/1_create_users.rb", <<-RUBY + class CreateUsers < ActiveRecord::Migration + end + RUBY + + app_file "db/migrate/1_create_sessions.rb", <<-RUBY + class CreateSessions < ActiveRecord::Migration + end + RUBY + + add_to_config "ActiveRecord::Base.timestamped_migrations = false" + + Dir.chdir(app_path) do + `rake bukkits:install` + assert File.exists?("#{app_path}/db/migrate/2_create_users.rb") + assert File.exists?(app_path("public/bukkits/javascripts/foo.js")) + end + end + + def test_copying_assets + @plugin.write "public/javascripts/foo.js", "doSomething()" + @plugin.write "public/stylesheets/foo.css", "h1 { font-size: 10000px }" + @plugin.write "public/images/img.png", "" + + Dir.chdir(app_path) do + `rake bukkits:install:assets --trace` + + assert File.exists?(app_path("public/bukkits/javascripts/foo.js")) + assert_equal "doSomething()\n", File.read(app_path("public/bukkits/javascripts/foo.js")) + assert File.exists?(app_path("public/bukkits/stylesheets/foo.css")) + assert_equal "h1 { font-size: 10000px }\n", File.read(app_path("public/bukkits/stylesheets/foo.css")) + assert File.exists?(app_path("public/bukkits/images/img.png")) + end + end + + def test_copying_migrations + @plugin.write "db/migrate/1_create_users.rb", <<-RUBY + class CreateUsers < ActiveRecord::Migration + end + RUBY + + @plugin.write "db/migrate/2_add_last_name_to_users.rb", <<-RUBY + class AddLastNameToUsers < ActiveRecord::Migration + end + RUBY + + @plugin.write "db/migrate/3_create_sessions.rb", <<-RUBY + class CreateSessions < ActiveRecord::Migration + end + RUBY + + app_file "db/migrate/1_create_sessions.rb", <<-RUBY + class CreateSessions < ActiveRecord::Migration + end + RUBY + + yaffle = plugin "acts_as_yaffle", "::LEVEL = config.log_level" do |plugin| + plugin.write "lib/acts_as_yaffle.rb", "class ActsAsYaffle; end" + end + + yaffle.write "db/migrate/1_create_yaffles.rb", <<-RUBY + class CreateYaffles < ActiveRecord::Migration + end + RUBY + + add_to_config "ActiveRecord::Base.timestamped_migrations = false" + + Dir.chdir(app_path) do + output = `rake bukkits:install:migrations` + + assert File.exists?("#{app_path}/db/migrate/2_create_users.rb") + assert File.exists?("#{app_path}/db/migrate/3_add_last_name_to_users.rb") + assert_match /Copied migration 2_create_users.rb from bukkits/, output + assert_match /Copied migration 3_add_last_name_to_users.rb from bukkits/, output + assert_match /NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/, output + assert_equal 3, Dir["#{app_path}/db/migrate/*.rb"].length + + output = `rake railties:install:migrations` + + assert File.exists?("#{app_path}/db/migrate/4_create_yaffles.rb") + assert_match /NOTE: Migration 3_create_sessions.rb from bukkits has been skipped/, output + assert_match /Copied migration 4_create_yaffles.rb from acts_as_yaffle/, output + assert_no_match /2_create_users/, output + + migrations_count = Dir["#{app_path}/db/migrate/*.rb"].length + output = `rake railties:install:migrations` + + assert_equal migrations_count, Dir["#{app_path}/db/migrate/*.rb"].length + end + end + def test_puts_its_lib_directory_on_load_path boot_rails require "another" @@ -129,7 +223,7 @@ module RailtiesTest RUBY app_file "config/routes.rb", <<-RUBY - AppTemplate::Application.routes.draw do |map| + AppTemplate::Application.routes.draw do match 'foo', :to => 'foo#index' end RUBY @@ -143,7 +237,7 @@ module RailtiesTest RUBY @plugin.write "config/routes.rb", <<-RUBY - Rails.application.routes.draw do |map| + Rails.application.routes.draw do match 'foo', :to => 'bar#index' match 'bar', :to => 'bar#index' end @@ -200,7 +294,7 @@ YAML boot_rails - assert_equal %W( + expected_locales = %W( #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml @@ -208,7 +302,13 @@ YAML #{@plugin.path}/config/locales/en.yml #{app_path}/config/locales/en.yml #{app_path}/app/locales/en.yml - ).map { |path| File.expand_path(path) }, I18n.load_path.map { |path| File.expand_path(path) } + ).map { |path| File.expand_path(path) } + + actual_locales = I18n.load_path.map { |path| + File.expand_path(path) + } & expected_locales # remove locales external to Rails + + assert_equal expected_locales, actual_locales assert_equal "2", I18n.t(:foo) assert_equal "1", I18n.t(:bar) diff --git a/railties/test/script_rails_loader_test.rb b/railties/test/script_rails_loader_test.rb index 2a87e5cb58..3ccc147749 100644 --- a/railties/test/script_rails_loader_test.rb +++ b/railties/test/script_rails_loader_test.rb @@ -2,21 +2,21 @@ require 'abstract_unit' require 'rails/script_rails_loader' class ScriptRailsLoaderTest < ActiveSupport::TestCase - + test "is in a rails application if script/rails exists" do File.stubs(:exists?).returns(true) assert Rails::ScriptRailsLoader.in_rails_application? end - + test "is in a rails application if parent directory has script/rails" do File.stubs(:exists?).with("/foo/bar/script/rails").returns(false) File.stubs(:exists?).with("/foo/script/rails").returns(true) assert Rails::ScriptRailsLoader.in_rails_application_subdirectory?(Pathname.new("/foo/bar")) end - + test "is not in a rails application if at the root directory and doesn't have script/rails" do Pathname.any_instance.stubs(:root?).returns true assert !Rails::ScriptRailsLoader.in_rails_application? end - + end
\ No newline at end of file |