assets_test.rb 16.1 KB
Newer Older
1
# -*- coding: utf-8 -*-
2
require 'isolation/abstract_unit'
3
require 'active_support/core_ext/kernel/reporting'
4 5 6
require 'rack/test'

module ApplicationTests
7
  class AssetsTest < Test::Unit::TestCase
8 9 10 11
    include ActiveSupport::Testing::Isolation
    include Rack::Test::Methods

    def setup
12
      build_app(:initializers => true)
13 14 15
      boot_rails
    end

16 17 18 19
    def teardown
      teardown_app
    end

J
José Valim 已提交
20 21 22 23
    def app
      @app ||= Rails.application
    end

24 25 26 27 28 29
    def precompile!
      capture(:stdout) do
        Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
      end
    end

30 31 32 33 34 35 36 37 38
    test "assets routes have higher priority" do
      app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"

      app_file 'config/routes.rb', <<-RUBY
        AppTemplate::Application.routes.draw do
          match '*path', :to => lambda { |env| [200, { "Content-Type" => "text/html" }, "Not an asset"] }
        end
      RUBY

39 40
      require "#{app_path}/config/environment"

41 42 43
      get "/assets/demo.js"
      assert_match "alert()", last_response.body
    end
J
José Valim 已提交
44

J
José Valim 已提交
45 46
    test "assets do not require compressors until it is used" do
      app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"
47
      add_to_env_config "production", "config.assets.compile = true"
48

J
José Valim 已提交
49 50 51 52 53 54 55 56 57
      ENV["RAILS_ENV"] = "production"
      require "#{app_path}/config/environment"

      assert !defined?(Uglifier)
      get "/assets/demo.js"
      assert_match "alert()", last_response.body
      assert defined?(Uglifier)
    end

S
Santiago Pastorino 已提交
58
    test "precompile creates the file, gives it the original asset's content and run in production as default" do
59
      app_file "app/assets/javascripts/application.js", "alert();"
60
      app_file "app/assets/javascripts/foo/application.js", "alert();"
61

62
      ENV["RAILS_ENV"] = nil
63 64
      precompile!

J
Jon Leighton 已提交
65
      files = Dir["#{app_path}/public/assets/application-*.js"]
66
      files << Dir["#{app_path}/public/assets/application.js"].first
J
Jon Leighton 已提交
67
      files << Dir["#{app_path}/public/assets/foo/application-*.js"].first
68
      files << Dir["#{app_path}/public/assets/foo/application.js"].first
69 70
      files.each do |file|
        assert_not_nil file, "Expected application.js asset to be generated, but none found"
71
        assert_equal "alert()", File.read(file)
72
      end
73 74
    end

75 76 77
    test "precompile application.js and application.css and all other files not ending with .js or .css by default" do
      app_file "app/assets/javascripts/application.js", "alert();"
      app_file "app/assets/stylesheets/application.css", "body{}"
78 79 80 81

      app_file "app/assets/javascripts/someapplication.js", "alert();"
      app_file "app/assets/stylesheets/someapplication.css", "body{}"

82 83 84 85 86 87 88 89
      app_file "app/assets/javascripts/something.min.js", "alert();"
      app_file "app/assets/stylesheets/something.min.css", "body{}"

      images_should_compile = ["a.png", "happyface.png", "happy_face.png", "happy.face.png",
                               "happy-face.png", "happy.happy_face.png", "happy_happy.face.png", 
                               "happy.happy.face.png", "happy", "happy.face", "-happyface",
                               "-happy.png", "-happy.face.png", "_happyface", "_happy.face.png",
                               "_happy.png"]
90

91 92 93 94
      images_should_compile.each do |filename|
        app_file "app/assets/images/#{filename}", "happy"
      end

95
      precompile!
96 97 98 99

      images_should_compile.each do |filename|
        assert File.exists?("#{app_path}/public/assets/#{filename}")
      end
100

101 102
      assert File.exists?("#{app_path}/public/assets/application.js")
      assert File.exists?("#{app_path}/public/assets/application.css")
103 104 105 106

      assert !File.exists?("#{app_path}/public/assets/someapplication.js")
      assert !File.exists?("#{app_path}/public/assets/someapplication.css")

107 108 109 110
      assert !File.exists?("#{app_path}/public/assets/something.min.js")
      assert !File.exists?("#{app_path}/public/assets/something.min.css")
    end

111
    test "asset pipeline should use a Sprockets::Index when config.assets.digest is true" do
112 113 114
      add_to_config "config.assets.digest = true"
      add_to_config "config.action_controller.perform_caching = false"

115 116 117 118 119 120
      ENV["RAILS_ENV"] = "production"
      require "#{app_path}/config/environment"

      assert_equal Sprockets::Index, Rails.application.assets.class
    end

121
    test "precompile creates a manifest file with all the assets listed" do
122 123
      app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"
      app_file "app/assets/javascripts/application.js", "alert();"
124
      # digest is default in false, we must enable it for test environment
125
      add_to_config "config.assets.digest = true"
126

127
      precompile!
128 129 130
      manifest = "#{app_path}/public/assets/manifest.yml"

      assets = YAML.load_file(manifest)
131 132
      assert_match(/application-([0-z]+)\.js/, assets["application.js"])
      assert_match(/application-([0-z]+)\.css/, assets["application.css"])
133 134
    end

135 136 137
    test "precompile creates a manifest file in a custom path with all the assets listed" do
      app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"
      app_file "app/assets/javascripts/application.js", "alert();"
138
      # digest is default in false, we must enable it for test environment
139 140
      add_to_config "config.assets.digest = true"
      add_to_config "config.assets.manifest = '#{app_path}/shared'"
141

142
      precompile!
143 144 145
      manifest = "#{app_path}/shared/manifest.yml"

      assets = YAML.load_file(manifest)
146 147
      assert_match(/application-([0-z]+)\.js/, assets["application.js"])
      assert_match(/application-([0-z]+)\.css/, assets["application.css"])
148 149
    end

150 151
    test "the manifest file should be saved by default in the same assets folder" do
      app_file "app/assets/javascripts/application.js", "alert();"
152
      # digest is default in false, we must enable it for test environment
153 154
      add_to_config "config.assets.digest = true"
      add_to_config "config.assets.prefix = '/x'"
155

156
      precompile!
157 158 159

      manifest = "#{app_path}/public/x/manifest.yml"
      assets = YAML.load_file(manifest)
160
      assert_match(/application-([0-z]+)\.js/, assets["application.js"])
161 162
    end

163 164 165
    test "precompile does not append asset digests when config.assets.digest is false" do
      app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"
      app_file "app/assets/javascripts/application.js", "alert();"
166
      add_to_config "config.assets.digest = false"
167

168
      precompile!
169 170 171 172 173 174 175 176 177 178 179

      assert File.exists?("#{app_path}/public/assets/application.js")
      assert File.exists?("#{app_path}/public/assets/application.css")

      manifest = "#{app_path}/public/assets/manifest.yml"

      assets = YAML.load_file(manifest)
      assert_equal "application.js", assets["application.js"]
      assert_equal "application.css", assets["application.css"]
    end

180
    test "assets do not require any assets group gem when manifest file is present" do
181
      app_file "app/assets/javascripts/application.js", "alert();"
182
      add_to_env_config "production", "config.serve_static_assets = true"
183 184

      ENV["RAILS_ENV"] = "production"
185 186
      precompile!

187 188 189 190 191 192 193 194 195 196 197 198 199
      manifest = "#{app_path}/public/assets/manifest.yml"
      assets = YAML.load_file(manifest)
      asset_path = assets["application.js"]

      require "#{app_path}/config/environment"

      # Checking if Uglifier is defined we can know if Sprockets was reached or not
      assert !defined?(Uglifier)
      get "/assets/#{asset_path}"
      assert_match "alert()", last_response.body
      assert !defined?(Uglifier)
    end

200
    test "assets raise AssetNotPrecompiledError when manifest file is present and requested file isn't precompiled" do
201 202 203 204 205 206 207 208 209
      app_file "app/views/posts/index.html.erb", "<%= javascript_include_tag 'app' %>"

      app_file "config/routes.rb", <<-RUBY
        AppTemplate::Application.routes.draw do
          match '/posts', :to => "posts#index"
        end
      RUBY

      ENV["RAILS_ENV"] = "production"
210
      precompile!
211 212 213 214

      # Create file after of precompile
      app_file "app/assets/javascripts/app.js", "alert();"

215 216 217 218
      require "#{app_path}/config/environment"
      class ::PostsController < ActionController::Base ; end

      get '/posts'
219
      assert_match(/AssetNotPrecompiledError/, last_response.body)
220 221 222 223 224
      assert_match(/app.js isn't precompiled/, last_response.body)
    end

    test "assets raise AssetNotPrecompiledError when manifest file is present and requested file isn't precompiled if digest is disabled" do
      app_file "app/views/posts/index.html.erb", "<%= javascript_include_tag 'app' %>"
225
      add_to_config "config.assets.compile = false"
226 227 228 229 230 231 232 233

      app_file "config/routes.rb", <<-RUBY
        AppTemplate::Application.routes.draw do
          match '/posts', :to => "posts#index"
        end
      RUBY

      ENV["RAILS_ENV"] = "development"
234
      precompile!
235 236 237 238 239 240 241 242 243

      # Create file after of precompile
      app_file "app/assets/javascripts/app.js", "alert();"

      require "#{app_path}/config/environment"
      class ::PostsController < ActionController::Base ; end

      get '/posts'
      assert_match(/AssetNotPrecompiledError/, last_response.body)
244
      assert_match(/app.js isn't precompiled/, last_response.body)
245 246
    end

247
    test "precompile appends the md5 hash to files referenced with asset_path and run in the provided RAILS_ENV" do
248
      app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"
249
      # digest is default in false, we must enable it for test environment
250
      add_to_config "config.assets.digest = true"
251

S
Santiago Pastorino 已提交
252
      capture(:stdout) do
253
        Dir.chdir(app_path){ `bundle exec rake assets:precompile RAILS_ENV=test` }
S
Santiago Pastorino 已提交
254
      end
J
Jon Leighton 已提交
255
      file = Dir["#{app_path}/public/assets/application-*.css"].first
256
      assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file))
257 258
    end

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
    test "precompile shouldn't use the digests present in manifest.yml" do
      app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"

      ENV["RAILS_ENV"] = "production"
      precompile!

      manifest = "#{app_path}/public/assets/manifest.yml"
      assets = YAML.load_file(manifest)
      asset_path = assets["application.css"]

      app_file "app/assets/images/rails.png", "image changed"

      precompile!
      assets = YAML.load_file(manifest)

      assert_not_equal asset_path, assets["application.css"]
    end

277 278
    test "precompile appends the md5 hash to files referenced with asset_path and run in production as default even using RAILS_GROUPS=assets" do
      app_file "app/assets/stylesheets/application.css.erb", "<%= asset_path('rails.png') %>"
279
      add_to_config "config.assets.compile = true"
280 281

      ENV["RAILS_ENV"] = nil
282
      capture(:stdout) do
283
        Dir.chdir(app_path){ `bundle exec rake assets:precompile RAILS_GROUPS=assets` }
284
      end
J
Jon Leighton 已提交
285
      file = Dir["#{app_path}/public/assets/application-*.css"].first
286
      assert_match(/\/assets\/rails-([0-z]+)\.png/, File.read(file))
287 288
    end

289 290 291 292
    test "precompile should handle utf8 filenames" do
      app_file "app/assets/images/レイルズ.png", "not a image really"
      add_to_config "config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ]"

293
      precompile!
294 295 296 297 298 299 300 301
      assert File.exists?("#{app_path}/public/assets/レイルズ.png")

      manifest = "#{app_path}/public/assets/manifest.yml"

      assets = YAML.load_file(manifest)
      assert_equal "レイルズ.png", assets["レイルズ.png"]
    end

302 303 304 305 306 307 308 309 310
    test "assets are cleaned up properly" do
      app_file "public/assets/application.js", "alert();"
      app_file "public/assets/application.css", "a { color: green; }"
      app_file "public/assets/subdir/broken.png", "not really an image file"

      capture(:stdout) do
        Dir.chdir(app_path){ `bundle exec rake assets:clean` }
      end

311
      files = Dir["#{app_path}/public/assets/**/*", "#{app_path}/tmp/cache/*"]
312 313 314
      assert_equal 0, files.length, "Expected no assets, but found #{files.join(', ')}"
    end

315 316
    test "assets routes are not drawn when compilation is disabled" do
      app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"
G
Guillermo Iguaran 已提交
317
      add_to_config "config.assets.compile = false"
318 319 320 321 322 323 324 325

      ENV["RAILS_ENV"] = "production"
      require "#{app_path}/config/environment"

      get "/assets/demo.js"
      assert_equal 404, last_response.status
    end

J
José Valim 已提交
326
    test "does not stream session cookies back" do
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
      app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"

      app_file "config/routes.rb", <<-RUBY
        AppTemplate::Application.routes.draw do
          match '/omg', :to => "omg#index"
        end
      RUBY

      require "#{app_path}/config/environment"

      class ::OmgController < ActionController::Base
        def index
          flash[:cool_story] = true
          render :text => "ok"
        end
      end

      get "/omg"
      assert_equal 'ok', last_response.body

      get "/assets/demo.js"
      assert_match "alert()", last_response.body
      assert_equal nil, last_response.headers["Set-Cookie"]
J
José Valim 已提交
350
    end
351 352 353 354 355 356 357 358 359 360 361 362 363 364

    test "files in any assets/ directories are not added to Sprockets" do
      %w[app lib vendor].each do |dir|
        app_file "#{dir}/assets/#{dir}_test.erb", "testing"
      end

      app_file "app/assets/javascripts/demo.js", "alert();"

      require "#{app_path}/config/environment"

      get "/assets/demo.js"
      assert_match "alert();", last_response.body
      assert_equal 200, last_response.status
    end
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

    test "assets are concatenated when debug is off and compile is off either if debug_assets param is provided" do
      app_with_assets_in_view

      # config.assets.debug and config.assets.compile are false for production environment
      ENV["RAILS_ENV"] = "production"
      precompile!

      require "#{app_path}/config/environment"

      class ::PostsController < ActionController::Base ; end

      # the debug_assets params isn't used if compile is off
      get '/posts?debug_assets=true'
      assert_match(/<script src="\/assets\/application-([0-z]+)\.js" type="text\/javascript"><\/script>/, last_response.body)
      assert_no_match(/<script src="\/assets\/xmlhr-([0-z]+)\.js" type="text\/javascript"><\/script>/, last_response.body)
    end

    test "assets aren't concatened when compile is true is on and debug_assets params is true" do
      app_with_assets_in_view
      add_to_env_config "production", "config.assets.compile  = true"
      add_to_env_config "production", "config.assets.allow_debugging = true"

      ENV["RAILS_ENV"] = "production"
      require "#{app_path}/config/environment"

      class ::PostsController < ActionController::Base ; end

      get '/posts?debug_assets=true'
      assert_match(/<script src="\/assets\/application-([0-z]+)\.js\?body=1" type="text\/javascript"><\/script>/, last_response.body)
      assert_match(/<script src="\/assets\/xmlhr-([0-z]+)\.js\?body=1" type="text\/javascript"><\/script>/, last_response.body)
    end

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
    test "assets can access model information when precompiling" do
      app_file "app/models/post.rb", "class Post; end"
      app_file "app/assets/javascripts/application.js", "//= require_tree ."
      app_file "app/assets/javascripts/xmlhr.js.erb", "<%= Post.name %>"

      add_to_config "config.assets.digest = false"
      precompile!
      assert_equal "Post;\n", File.read("#{app_path}/public/assets/application.js")
    end

    test "assets can't access model information when precompiling if not initializing the app" do
      app_file "app/models/post.rb", "class Post; end"
      app_file "app/assets/javascripts/application.js", "//= require_tree ."
      app_file "app/assets/javascripts/xmlhr.js.erb", "<%= defined?(Post) || :NoPost %>"

      add_to_config "config.assets.digest = false"
      add_to_config "config.assets.initialize_on_precompile = false"

      precompile!
      assert_equal "NoPost;\n", File.read("#{app_path}/public/assets/application.js")
    end

420
    private
421

422 423 424 425 426 427 428 429 430 431 432
    def app_with_assets_in_view
      app_file "app/assets/javascripts/application.js", "//= require_tree ."
      app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }"
      app_file "app/views/posts/index.html.erb", "<%= javascript_include_tag 'application' %>"

      app_file "config/routes.rb", <<-RUBY
        AppTemplate::Application.routes.draw do
          match '/posts', :to => "posts#index"
        end
      RUBY
    end
433 434
  end
end