aboutsummaryrefslogblamecommitdiffstats
path: root/railties/test/railties/engine_test.rb
blob: 92aa025238fbfe0430c013d6f44d8dad4dfb8646 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                 
                  

                   


                                         
 

                                             
                               







                                              
                                    





                                                           
 
                                                             
                

                                                












                                                                                    
                                                         
                                                                             







                                                                             


                                                                                 
 
 






                                 
                                          




                                                                        

                                                                     


                                             
                                                                                             




                                                                     




                                               
 
                
 

                                                    
       
 







                                                    

                                               
                                                                                          

           
 




                                              
 
                
 

                                            

       



                                             



             
                                                            
                                   





                                                 






















                                                                             


















                                                                 












                                                                                     
                               


                                                                        
                                 

                                                                          




                                             


















                                                                
                                                          


                                            
         
 





                                             



                                                  




                                                                           

                                                                      
 

                                                                                                        

                                                                                                                            
       
 









                                                                
                                                            



             




                                               
 
                
 

                                                                      

       












                                                                  
                                                                                 


                

                                                                                        
 

                                                                                                
 

                                                                                                          
       
 
                                                                                



                                                           
                                               










                                                    







                                                        








                                                                        



                                          




                

                                                                               
 

                                             
 

                                                    

       
                                                                            


                                             
                                     



             











                                                         








                                                               





                                                                                                 

































                                                                                                    
                                                                         
             



                                                      









                                                               

                                                                     

                

                                                         

                                                           
                                                            
 













                                                           
       




                                                                                
                                     





























                                                               
                          









                                                                          
                                                                  


                                                   
         




                                                                     

                                                             
       
 

















                                                                                     




                                                                                               
                                          



             
                                                   








                                                            






















                                                           
                                      



             


                                                

                 

                                            
                         

                                            






































                                                                          















                                                                                 


                                                                          
       


















                                                                         


















                                                                             































































                                                                                                         




                       

     
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

      @plugin = engine "bukkits" do |plugin|
        plugin.write "lib/bukkits.rb", <<-RUBY
          class Bukkits
            class Engine < ::Rails::Engine
              railtie_name "bukkits"
            end
          end
        RUBY
        plugin.write "lib/another.rb", "class Another; end"
      end
    end

    test "Rails::Engine itself does not respond to config" do
      boot_rails
      assert !Rails::Engine.respond_to?(:config)
    end

    test "initializers are executed after application configuration initializers" do
      @plugin.write "lib/bukkits.rb", <<-RUBY
        class Bukkits
          class Engine < ::Rails::Engine
            initializer "dummy_initializer" do
            end
          end
        end
      RUBY

      boot_rails

      initializers = Rails.application.initializers.tsort
      index        = initializers.index { |i| i.name == "dummy_initializer" }
      selection    = initializers[(index-3)..(index)].map(&:name).map(&:to_s)

      assert_equal %w(
       load_config_initializers
       load_config_initializers
       engines_blank_point
       dummy_initializer
      ), selection

      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 "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