ktheory-juicer 1.0.0.ktheory1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/History.txt +30 -0
  2. data/Manifest.txt +58 -0
  3. data/Rakefile +96 -0
  4. data/Readme.rdoc +312 -0
  5. data/VERSION +1 -0
  6. data/bin/juicer +8 -0
  7. data/lib/juicer.rb +70 -0
  8. data/lib/juicer/asset/path.rb +275 -0
  9. data/lib/juicer/asset/path_resolver.rb +79 -0
  10. data/lib/juicer/binary.rb +171 -0
  11. data/lib/juicer/cache_buster.rb +130 -0
  12. data/lib/juicer/chainable.rb +106 -0
  13. data/lib/juicer/cli.rb +56 -0
  14. data/lib/juicer/command/install.rb +61 -0
  15. data/lib/juicer/command/list.rb +57 -0
  16. data/lib/juicer/command/merge.rb +205 -0
  17. data/lib/juicer/command/util.rb +32 -0
  18. data/lib/juicer/command/verify.rb +60 -0
  19. data/lib/juicer/css_cache_buster.rb +80 -0
  20. data/lib/juicer/datafy/datafy.rb +20 -0
  21. data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +29 -0
  22. data/lib/juicer/dependency_resolver/dependency_resolver.rb +101 -0
  23. data/lib/juicer/dependency_resolver/javascript_dependency_resolver.rb +23 -0
  24. data/lib/juicer/ext/logger.rb +5 -0
  25. data/lib/juicer/ext/string.rb +47 -0
  26. data/lib/juicer/ext/symbol.rb +15 -0
  27. data/lib/juicer/image_embed.rb +136 -0
  28. data/lib/juicer/install/base.rb +186 -0
  29. data/lib/juicer/install/closure_compiler_installer.rb +69 -0
  30. data/lib/juicer/install/jslint_installer.rb +51 -0
  31. data/lib/juicer/install/rhino_installer.rb +53 -0
  32. data/lib/juicer/install/yui_compressor_installer.rb +67 -0
  33. data/lib/juicer/jslint.rb +90 -0
  34. data/lib/juicer/merger/base.rb +74 -0
  35. data/lib/juicer/merger/javascript_merger.rb +29 -0
  36. data/lib/juicer/merger/stylesheet_merger.rb +110 -0
  37. data/lib/juicer/minifyer/closure_compiler.rb +90 -0
  38. data/lib/juicer/minifyer/java_base.rb +77 -0
  39. data/lib/juicer/minifyer/yui_compressor.rb +96 -0
  40. data/test/bin/jslint-1.0.js +523 -0
  41. data/test/bin/jslint.js +523 -0
  42. data/test/bin/rhino1_7R1.zip +0 -0
  43. data/test/bin/rhino1_7R2-RC1.jar +0 -0
  44. data/test/bin/rhino1_7R2-RC1.zip +0 -0
  45. data/test/bin/yuicompressor +0 -0
  46. data/test/bin/yuicompressor-2.3.5.zip +0 -0
  47. data/test/bin/yuicompressor-2.4.2.jar +0 -0
  48. data/test/bin/yuicompressor-2.4.2.zip +0 -0
  49. data/test/data/Changelog.txt +10 -0
  50. data/test/data/a.css +3 -0
  51. data/test/data/a.js +5 -0
  52. data/test/data/a1.css +5 -0
  53. data/test/data/b.css +1 -0
  54. data/test/data/b.js +5 -0
  55. data/test/data/b1.css +5 -0
  56. data/test/data/c1.css +3 -0
  57. data/test/data/css/2.gif +1 -0
  58. data/test/data/css/test.css +11 -0
  59. data/test/data/css/test2.css +1 -0
  60. data/test/data/d1.css +3 -0
  61. data/test/data/images/1.png +1 -0
  62. data/test/data/my_app.js +2 -0
  63. data/test/data/not-ok.js +2 -0
  64. data/test/data/ok.js +3 -0
  65. data/test/data/path_test.css +5 -0
  66. data/test/data/path_test2.css +14 -0
  67. data/test/data/pkg/module/moda.js +2 -0
  68. data/test/data/pkg/module/modb.js +3 -0
  69. data/test/data/pkg/pkg.js +1 -0
  70. data/test/test_helper.rb +169 -0
  71. data/test/unit/juicer/asset/path_resolver_test.rb +76 -0
  72. data/test/unit/juicer/asset/path_test.rb +370 -0
  73. data/test/unit/juicer/cache_buster_test.rb +104 -0
  74. data/test/unit/juicer/chainable_test.rb +94 -0
  75. data/test/unit/juicer/command/install_test.rb +58 -0
  76. data/test/unit/juicer/command/list_test.rb +81 -0
  77. data/test/unit/juicer/command/merge_test.rb +162 -0
  78. data/test/unit/juicer/command/util_test.rb +58 -0
  79. data/test/unit/juicer/command/verify_test.rb +48 -0
  80. data/test/unit/juicer/css_cache_buster_test.rb +71 -0
  81. data/test/unit/juicer/datafy_test.rb +37 -0
  82. data/test/unit/juicer/dependency_resolver/css_dependency_resolver_test.rb +36 -0
  83. data/test/unit/juicer/dependency_resolver/javascript_dependency_resolver_test.rb +50 -0
  84. data/test/unit/juicer/ext/string_test.rb +59 -0
  85. data/test/unit/juicer/ext/symbol_test.rb +27 -0
  86. data/test/unit/juicer/image_embed_test.rb +271 -0
  87. data/test/unit/juicer/install/installer_base_test.rb +214 -0
  88. data/test/unit/juicer/install/jslint_installer_test.rb +54 -0
  89. data/test/unit/juicer/install/rhino_installer_test.rb +57 -0
  90. data/test/unit/juicer/install/yui_compressor_test.rb +56 -0
  91. data/test/unit/juicer/jslint_test.rb +60 -0
  92. data/test/unit/juicer/merger/base_test.rb +122 -0
  93. data/test/unit/juicer/merger/javascript_merger_test.rb +74 -0
  94. data/test/unit/juicer/merger/stylesheet_merger_test.rb +180 -0
  95. data/test/unit/juicer/minifyer/closure_compressor_test.rb +107 -0
  96. data/test/unit/juicer/minifyer/yui_compressor_test.rb +116 -0
  97. data/test/unit/juicer_test.rb +1 -0
  98. metadata +265 -0
@@ -0,0 +1,58 @@
1
+ require "test_helper"
2
+
3
+ class Dummy
4
+ include Juicer::Command::Util
5
+ end
6
+
7
+ class TestCommandUtil < Test::Unit::TestCase
8
+
9
+ CSS_FILES = %w{a.css a1.css b.css b1.css c1.css d1.css path_test.css path_test2.css}
10
+ JS_FILES = %w{a.js}
11
+ ALL_FILES = (CSS_FILES + JS_FILES).sort
12
+
13
+ def setup
14
+ @impl = Dummy.new
15
+ Juicer::Test::FileSetup.new.create
16
+ Dir.glob("test/data/*.min.css").each { |file| File.delete(file) }
17
+ end
18
+
19
+ def test_files_from_single_file
20
+ files = @impl.files("test/data/a.css")
21
+ assert files.is_a?(Array)
22
+ assert_equal "test/data/a.css", files.sort.join
23
+ end
24
+
25
+ def test_files_from_single_glob_pattern
26
+ files = @impl.files("test/data/*.css")
27
+ assert files.is_a?(Array)
28
+ assert_equal CSS_FILES.collect { |f| "test/data/#{f}" }.join, files.sort.join
29
+ end
30
+
31
+ def test_files_from_mixed_arguments
32
+ files = @impl.files("test/data/*.css", "test/data/a.js")
33
+ assert files.is_a?(Array)
34
+ assert_equal ALL_FILES.collect { |f| "test/data/#{f}" }.join, files.sort.join
35
+ end
36
+
37
+ def test_files_from_array
38
+ files = @impl.files(["test/data/*.css", "test/data/a.js"])
39
+ assert files.is_a?(Array)
40
+ assert_equal ALL_FILES.collect { |f| "test/data/#{f}" }.join, files.sort.join
41
+ end
42
+
43
+ def test_relative_path_single_file
44
+ assert_equal "test/data/a.css", @impl.relative("test/data/a.css")
45
+ end
46
+
47
+ def test_relative_path_many_files
48
+ files = @impl.relative(Dir.glob("test/data/*.css"))
49
+ assert files.is_a?(Array)
50
+ assert_equal CSS_FILES.collect { |f| "test/data/#{f}" }.join, files.sort.join
51
+ end
52
+
53
+ def test_relative_path_many_files_explicit_reference
54
+ files = @impl.relative(Dir.glob("test/data/*.css"), "lib")
55
+ assert files.is_a?(Array)
56
+ assert_equal CSS_FILES.collect { |f| "../test/data/#{f}" }.join, files.sort.join
57
+ end
58
+ end
@@ -0,0 +1,48 @@
1
+ require "test_helper"
2
+
3
+ class TestVerifyCommand < Test::Unit::TestCase
4
+ def setup
5
+ @io = StringIO.new
6
+ @command = Juicer::Command::Verify.new(Logger.new(@io))
7
+ @path = Dir.pwd
8
+ @juicer = Juicer.home
9
+ end
10
+
11
+ def teardown
12
+ Dir.chdir(@path)
13
+ Juicer.home = @juicer
14
+ end
15
+
16
+ context "executing command" do
17
+ should "fail with no files" do
18
+ assert_raise ArgumentError do
19
+ @command.execute []
20
+ end
21
+ end
22
+
23
+ should "fail if installer is not found" do
24
+ Juicer.home = path("somewhere")
25
+ Dir.chdir("lib")
26
+ command = Juicer::Command::Verify.new(Logger.new(@io))
27
+
28
+ assert_raise FileNotFoundError do
29
+ command.execute path("a.js")
30
+ end
31
+ end
32
+
33
+ should "verify several files" do
34
+ files = %w[file1.js file2.js file3.js]
35
+ ok = "OK!\njslint: No problems"
36
+
37
+ Juicer::Command::Verify.any_instance.expects(:files).with(files).returns(files)
38
+ Juicer::JsLint.any_instance.expects(:check).with(files[0]).returns(Juicer::JsLint::Report.new)
39
+ Juicer::JsLint.any_instance.expects(:check).with(files[1]).returns(Juicer::JsLint::Report.new(["Oops"]))
40
+ Juicer::JsLint.any_instance.expects(:check).with(files[2]).returns(Juicer::JsLint::Report.new)
41
+
42
+ @command.execute(files)
43
+
44
+ assert_match(/OK!/, @io.string)
45
+ assert_match(/Problems detected/, @io.string)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,71 @@
1
+ require "test_helper"
2
+
3
+ class TestCssCacheBuster < Test::Unit::TestCase
4
+ def setup
5
+ Juicer::Test::FileSetup.new.create
6
+ @buster = Juicer::CssCacheBuster.new
7
+ end
8
+
9
+ def teardown
10
+ Juicer::Test::FileSetup.new.delete
11
+ Juicer::Test::FileSetup.new.create
12
+ end
13
+
14
+ def test_find_urls
15
+ urls = @buster.urls(path("css/test.css"))
16
+ assert_equal 3, urls.length
17
+ assert_equal "../a1.css../images/1.png2.gif", urls.collect { |a| a.path }.sort.join.gsub(path("/"), "")
18
+ end
19
+
20
+ def test_image_references_should_be_updated
21
+ file = path("css/test.css")
22
+ buster = Juicer::CssCacheBuster.new
23
+ buster.save file
24
+
25
+ File.read(file).scan(/url\(([^\)]*)\)/m).each do |path|
26
+ assert_match(/[^\?]*\?jcb=\d+/, path.first)
27
+ end
28
+ end
29
+
30
+ def test_absolute_path_without_web_root_should_fail
31
+ file = path("css/test2.css")
32
+ buster = Juicer::CssCacheBuster.new
33
+
34
+ assert_raise FileNotFoundError do
35
+ buster.save file
36
+ end
37
+ end
38
+
39
+ def test_absolute_path_should_be_resolved_when_web_root_known
40
+ file = path("css/test.css")
41
+ buster = Juicer::CssCacheBuster.new :web_root => path("")
42
+
43
+ assert_nothing_raised do
44
+ buster.save file
45
+ end
46
+
47
+ File.read(file).scan(/url\(([^\)]*)\)/m).each do |path|
48
+ assert_match(/[^\?]*\?jcb=\d+/, path.first)
49
+ end
50
+ end
51
+
52
+ def test_urls_should_only_have_mtime_appended_once
53
+ File.open(path("a2.css"), "w") { |f| f.puts "" }
54
+ file = path("path_test2.css")
55
+ output = path("path_test3.css")
56
+ buster = Juicer::CssCacheBuster.new :web_root => path("")
57
+ buster.save file, output
58
+
59
+ buster.urls(output).each { |url| assert url !~ /(jcb=\d+).*(jcb=\d+)/, url }
60
+ end
61
+
62
+ def test_type_hard_should_produce_hard_buster_urls
63
+ File.open(path("a2.css"), "w") { |f| f.puts "" }
64
+ file = path("path_test2.css")
65
+ output = path("path_test3.css")
66
+ buster = Juicer::CssCacheBuster.new :web_root => path(""), :type => :hard
67
+ buster.save file, output
68
+
69
+ buster.urls(output).each { |asset| assert_match /-jcb\d+\.[a-z]{3}$/, asset.path }
70
+ end
71
+ end
@@ -0,0 +1,37 @@
1
+ require 'test/unit'
2
+ require "test_helper"
3
+
4
+ class TC_Datafy < Test::Unit::TestCase
5
+
6
+ def test_make_data_uri_text_plain
7
+ assert_equal(SHORT_TEXT_PLAIN_URI, Datafy::make_data_uri(SHORT_STRING, TEXT_PLAIN))
8
+ assert_equal(LONG_TEXT_PLAIN_URI, Datafy::make_data_uri(LONG_STRING, TEXT_PLAIN))
9
+ end
10
+
11
+ def test_make_data_uri_octet_stream
12
+ assert_equal(SHORT_APPLICATION_OCTET_STREAM_URI, Datafy::make_data_uri(SHORT_STRING, APPLICATION_OCTET_STREAM))
13
+ assert_equal(LONG_APPLICATION_OCTET_STREAM_URI, Datafy::make_data_uri(LONG_STRING, APPLICATION_OCTET_STREAM))
14
+ end
15
+
16
+ # mime types
17
+ TEXT_PLAIN = 'text/plain'
18
+ APPLICATION_OCTET_STREAM = 'application/octet-stream'
19
+
20
+ # string versions
21
+ SHORT_STRING = 'this is some text'
22
+ SHORT_BASE64 = 'dGhpcyBpcyBzb21lIHRleHQ='
23
+ SHORT_URLENCODED = 'this+is+some+text'
24
+
25
+ LONG_STRING = 'this is a really long string. this is a really long string. this is a really long string. this is a really long string. this is a really long string. this is a really long string. this is a really long string. this is a really long string.'
26
+ LONG_BASE64 = 'dGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4gdGhpcyBpcyBhIHJlYWxseSBsb25nIHN0cmluZy4='
27
+ LONG_URLENCODED = 'this+is+a+really+long+string.+this+is+a+really+long+string.+this+is+a+really+long+string.+this+is+a+really+long+string.+this+is+a+really+long+string.+this+is+a+really+long+string.+this+is+a+really+long+string.+this+is+a+really+long+string.'
28
+
29
+ # data: uris
30
+ SHORT_APPLICATION_OCTET_STREAM_URI = "data:#{APPLICATION_OCTET_STREAM};base64,#{SHORT_BASE64}"
31
+ SHORT_TEXT_PLAIN_URI = "data:#{TEXT_PLAIN},#{SHORT_URLENCODED}"
32
+
33
+ LONG_APPLICATION_OCTET_STREAM_URI = "data:#{APPLICATION_OCTET_STREAM};base64,#{LONG_BASE64}"
34
+ LONG_TEXT_PLAIN_URI = "data:#{TEXT_PLAIN},#{LONG_URLENCODED}"
35
+
36
+
37
+ end
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+
3
+ class TestCssDependencyResolver < Test::Unit::TestCase
4
+ def setup
5
+ @resolver = Juicer::CssDependencyResolver.new
6
+ Juicer::Test::FileSetup.new.create
7
+ end
8
+
9
+ def test_init
10
+ assert_equal [], @resolver.files
11
+ end
12
+
13
+ def test_resolve
14
+ b_file = path('b.css')
15
+ a_file = path('a.css')
16
+
17
+ files = @resolver.resolve(path('a.css')) do |file|
18
+ assert b_file == file || a_file == file
19
+ b_file != file
20
+ end
21
+
22
+ assert_equal [a_file], files
23
+
24
+ files = @resolver.resolve(path('a.css')) do |file|
25
+ assert b_file == file || a_file == file
26
+ true
27
+ end
28
+
29
+ assert_equal [a_file, b_file], files.sort
30
+ end
31
+
32
+ def test_load_order
33
+ files = @resolver.resolve(path("a1.css")).collect { |file| file.split("/").pop }
34
+ assert_equal "d1.cssb1.cssc1.cssa1.css", files.join
35
+ end
36
+ end
@@ -0,0 +1,50 @@
1
+ require "test_helper"
2
+
3
+ class TestJavaScriptDependencyResolver < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @resolver = Juicer::JavaScriptDependencyResolver.new
7
+ Juicer::Test::FileSetup.new.create
8
+ end
9
+
10
+ def test_init
11
+ assert_equal [], @resolver.files
12
+ end
13
+
14
+ def test_resolve
15
+ b_file = path('b.js')
16
+ a_file = path('a.js')
17
+
18
+ files = @resolver.resolve(a_file) do |file|
19
+ assert b_file == file || a_file == file, file
20
+ b_file != file
21
+ end
22
+
23
+ assert_equal [a_file], files
24
+
25
+ files = @resolver.resolve(a_file) do |file|
26
+ assert b_file == file || a_file == file
27
+ true
28
+ end
29
+
30
+ assert_equal [a_file, b_file], files.sort
31
+
32
+ files = @resolver.resolve(b_file) do |file|
33
+ assert b_file == file || a_file == file
34
+ true
35
+ end
36
+
37
+ assert_equal [a_file, b_file], files.sort
38
+ end
39
+
40
+ def test_directory_resolve
41
+ my_app = path("my_app.js")
42
+ expected_files = %w(pkg/pkg.js
43
+ pkg/module/moda.js
44
+ pkg/module/modb.js
45
+ my_app.js).map{|file| path(file)}
46
+
47
+ actual_files = @resolver.resolve(my_app)
48
+ assert_equal expected_files, actual_files
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ require "test_helper"
2
+
3
+ class TestStringExtensions < Test::Unit::TestCase
4
+ context "camel case method" do
5
+ should "convert underscored string" do
6
+ assert_equal "CamelCase", "camel_case".camel_case
7
+ end
8
+
9
+ should "convert spaced string" do
10
+ assert_equal "Camel case", "camel case".camel_case
11
+ end
12
+
13
+ should "convert upper-case underscored string" do
14
+ assert_equal "CamelCase", "CAMEL_CASE".camel_case
15
+ end
16
+
17
+ should "convert 'camel cased' underscored string" do
18
+ assert_equal "CamelCase", "Camel_Case".camel_case
19
+ end
20
+ end
21
+
22
+ context "to_class method" do
23
+ should "return String class" do
24
+ assert_equal String, "String".to_class
25
+ end
26
+
27
+ should "return String class from Object" do
28
+ assert_equal String, "String".to_class(Object)
29
+ end
30
+
31
+ should "return nested class" do
32
+ assert_equal Juicer::DependencyResolver, "Juicer::DependencyResolver".to_class
33
+ end
34
+
35
+ should "return class from module" do
36
+ assert_equal Juicer::DependencyResolver, "DependencyResolver".to_class(Juicer)
37
+ end
38
+
39
+ should "return class from nested module" do
40
+ assert_equal Juicer::Install::YuiCompressorInstaller, "YuiCompressorInstaller".to_class(Juicer::Install)
41
+ end
42
+ end
43
+
44
+ context "classify method" do
45
+ should "return class from underscored string" do
46
+ assert_equal Juicer::DependencyResolver, "dependency_resolver".classify(Juicer)
47
+ end
48
+
49
+ should "return top level class from underscored string" do
50
+ assert_equal FileUtils, "file_utils".classify
51
+ end
52
+ end
53
+
54
+ context "underscore method" do
55
+ should "return underscored string from camel cased string" do
56
+ assert_equal "stylesheet_merger", "StylesheetMerger".underscore
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,27 @@
1
+ require "test_helper"
2
+
3
+ class TestSymbolExtensions < Test::Unit::TestCase
4
+ context "camel case method" do
5
+ should "return camel cased string from underscored symbol" do
6
+ assert_equal "CamelCase", :camel_case.camel_case
7
+ end
8
+
9
+ should "return camel cased string from upper cased underscored symbol" do
10
+ assert_equal "CamelCase", :CAMEL_CASE.camel_case
11
+ end
12
+
13
+ should "return camel cased string from 'camel cased' underscored symbol" do
14
+ assert_equal "CamelCase", :Camel_Case.camel_case
15
+ end
16
+ end
17
+
18
+ context "classify method" do
19
+ should "return nested class" do
20
+ assert_equal Juicer::DependencyResolver, :dependency_resolver.classify(Juicer)
21
+ end
22
+
23
+ should "return top level class from underscored symbol" do
24
+ assert_equal FileUtils, :file_utils.classify
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,271 @@
1
+ require "test_helper"
2
+ require 'fakefs/safe'
3
+
4
+ class TestImageEmbed < Test::Unit::TestCase
5
+ include FakeFS
6
+
7
+ context "ImageEmbed instance using data_uri," do
8
+ setup do
9
+ FakeFS.activate!
10
+ FileSystem.clear
11
+ FileUtils.mkdir_p("/stylesheets")
12
+ FileUtils.mkdir_p("/images")
13
+
14
+ @supported_assets = [
15
+ { :path => '/images/test.png', :content => 'hello png!' },
16
+ { :path => '/images/test.gif', :content => 'hello gif!' },
17
+ { :path => '/images/test.jpg', :content => 'hello jpg!' },
18
+ { :path => '/images/test.jpeg', :content => 'hello jpeg!' },
19
+ ]
20
+ create_files(@supported_assets)
21
+
22
+ @unsupported_assets = [
23
+ { :path => '/images/test.bmp', :content => 'hello bmp!' },
24
+ { :path => '/images/test.js', :content => 'hello js!' },
25
+ { :path => '/images/test.txt', :content => 'hello txt!' },
26
+ { :path => '/images/test.swf', :content => 'hello swf!' },
27
+ { :path => '/images/test.swf', :content => 'hello swf!' },
28
+ { :path => '/images/test.ico', :content => 'hello ico!' },
29
+ { :path => '/images/test.tif', :content => 'hello tif!' },
30
+ { :path => '/images/test.tiff', :content => 'hello tiff!' },
31
+ { :path => '/images/test.applet', :content => 'hello applet!' },
32
+ { :path => '/images/test.jar', :content => 'hello jar!' }
33
+ ]
34
+ create_files(@unsupported_assets)
35
+ @embedder = Juicer::ImageEmbed.new(:type => :data_uri, :web_root => '')
36
+ end
37
+
38
+ teardown do
39
+ FakeFS.deactivate!
40
+ end
41
+
42
+ context "save method" do
43
+ context "with files exceeding SIZE_LIMIT" do
44
+ setup do
45
+ @large_files = [{ :path => '/images/large-file.png',
46
+ :content => "hello png!" + (" " * @embedder.size_limit) }]
47
+ create_files(@large_files)
48
+
49
+ @stylesheets = [{
50
+ :path => '/stylesheets/test_embed_duplicates.css',
51
+ :content => "body: { background: url(#{@large_files.first[:path]}?embed=true); }"
52
+ }]
53
+ create_files(@stylesheets)
54
+ end
55
+
56
+ should "not embed images that exceeds size limit" do
57
+ # make sure there are no errors
58
+ assert_nothing_raised do
59
+ @embedder.save @stylesheets.first[:path]
60
+ end
61
+
62
+ css_contents = File.read(@stylesheets.first[:path])
63
+
64
+ # encode the image
65
+ image_contents = File.read( @large_files.first[:path] )
66
+ data_uri = Datafy::make_data_uri(image_contents, 'image/png')
67
+
68
+ # make sure the encoded data_uri is not present in the stylesheet
69
+ assert !css_contents.include?(data_uri)
70
+
71
+ # make sure the original url still exist in the stylesheet
72
+ assert_match Regexp.new(@large_files.first[:path]), css_contents
73
+ end
74
+ end
75
+
76
+ context "with duplicated urls" do
77
+ setup do
78
+ @stylesheets = [{
79
+ :path => '/stylesheets/test_embed_duplicates.css',
80
+ :content => <<-EOF
81
+ body: { background: url(#{@supported_assets.first[:path]}?embed=true); }
82
+ div.section: { background: url(#{@supported_assets.first[:path]}?embed=true); }
83
+ div.article: { background: url(#{@supported_assets.last[:path]}?embed=true); }
84
+ EOF
85
+ }]
86
+ create_files(@stylesheets)
87
+ end
88
+
89
+ should_eventually "provide warnings for duplicate urls"
90
+
91
+ should "not embed duplicates" do
92
+ # make sure there are no errors
93
+ assert_nothing_raised do
94
+ @embedder.save @stylesheets.first[:path]
95
+ end
96
+
97
+ css_contents = File.read(@stylesheets.first[:path])
98
+
99
+ # encode the image
100
+ image_contents = File.read(@supported_assets.first[:path])
101
+ data_uri = Datafy::make_data_uri(image_contents, 'image/png')
102
+
103
+ # make sure the encoded data_uri is not present in the stylesheet
104
+ assert !css_contents.include?(data_uri)
105
+ end
106
+
107
+ should "embed distinct urls" do
108
+ # make sure there are no errors
109
+ assert_nothing_raised do
110
+ @embedder.save @stylesheets.first[:path]
111
+ end
112
+
113
+ css_contents = File.read(@stylesheets.first[:path])
114
+
115
+ # encode the image
116
+ image_contents = File.read(@supported_assets.last[:path])
117
+ data_uri = Datafy::make_data_uri(image_contents, 'image/jpeg')
118
+
119
+ # make sure the encoded data_uri is not present in the stylesheet
120
+ assert css_contents.include?(data_uri)
121
+
122
+ assert_no_match Regexp.new(@supported_assets.last[:path]), css_contents
123
+ end
124
+
125
+ end
126
+
127
+ should "embed images into css file" do
128
+ @stylesheets = [
129
+ {
130
+ :path => '/stylesheets/test_embed_true.css',
131
+ :content => "body: { background: url(#{@supported_assets.first[:path]}?embed=true); }"
132
+ }
133
+ ]
134
+ create_files( @stylesheets )
135
+
136
+ @stylesheets.each do |stylesheet|
137
+ old_contents = File.read( stylesheet[:path] )
138
+
139
+ # make sure there are no errors
140
+ assert_nothing_raised do
141
+ @embedder.save stylesheet[:path]
142
+ end
143
+
144
+ css_contents = File.read( stylesheet[:path] )
145
+
146
+ # make sure the original url does not exist anymore
147
+ assert_no_match( Regexp.new( @supported_assets.first[:path] ), css_contents )
148
+
149
+ # make sure the url has been converted into a data uri
150
+ image_contents = File.read( @supported_assets.first[:path] )
151
+
152
+ # # create the data uri from the image contents
153
+ data_uri = Datafy::make_data_uri( image_contents, 'image/png' )
154
+
155
+ # let's see if the data uri exists in the file
156
+ assert css_contents.include?( data_uri )
157
+ end
158
+ end
159
+
160
+ should "not embed unflagged images" do
161
+ @stylesheets = [
162
+ {
163
+ :path => '/stylesheets/test_embed_true.css',
164
+ :content => "
165
+ body: { background: url(#{@supported_assets.first[:path]}); }
166
+ h1: { background: url(#{@supported_assets.last[:path]}?embed=false); }
167
+ "
168
+ }
169
+ ]
170
+ create_files( @stylesheets )
171
+
172
+ @stylesheets.each do |stylesheet|
173
+ old_contents = File.read( stylesheet[:path] )
174
+
175
+ # make sure there are no errors
176
+ assert_nothing_raised do
177
+ @embedder.save stylesheet[:path]
178
+ end
179
+
180
+ css_contents = File.read( stylesheet[:path] )
181
+
182
+ # make sure the original url still exists
183
+ assert_match( Regexp.new( @supported_assets.first[:path] ), css_contents )
184
+ assert_match( Regexp.new( @supported_assets.last[:path] ), css_contents )
185
+ end
186
+ end
187
+
188
+
189
+ should "not embed unsupported images" do
190
+ @stylesheets = [
191
+ {
192
+ :path => '/stylesheets/test_embed_true.css',
193
+ :content => "
194
+ body: { background: url(#{@unsupported_assets.first[:path]}?embed=true); }
195
+ h1: { background: url(#{@unsupported_assets.last[:path]}?embed=true); }
196
+ "
197
+ }
198
+ ]
199
+ create_files( @stylesheets )
200
+
201
+ @stylesheets.each do |stylesheet|
202
+ old_contents = File.read( stylesheet[:path] )
203
+
204
+ # make sure there are no errors
205
+ assert_nothing_raised do
206
+ @embedder.save stylesheet[:path]
207
+ end
208
+
209
+ css_contents = File.read( stylesheet[:path] )
210
+
211
+ # make sure the original url still exists
212
+ assert_match( Regexp.new( @unsupported_assets.first[:path] ), css_contents )
213
+ assert_match( Regexp.new( @unsupported_assets.last[:path] ), css_contents )
214
+ end
215
+ end
216
+
217
+
218
+ end # context
219
+
220
+ context "embed method" do
221
+ should "not modify regular paths" do
222
+ path = @supported_assets.first[:path]
223
+ assert_equal( path, @embedder.embed_data_uri( path ) )
224
+ end
225
+
226
+ should "not modify paths flagged as not embeddable" do
227
+ path = "#{@supported_assets.first[:path]}?embed=false"
228
+ assert_equal( path, @embedder.embed_data_uri( path ) )
229
+ end
230
+
231
+ should "embed image when path flagged as embeddable" do
232
+ path = "#{@supported_assets.first[:path]}?embed=true"
233
+ assert_not_equal( path, @embedder.embed_data_uri( path ) )
234
+ end
235
+
236
+ should "encode all supported asset types" do
237
+ @supported_assets.each do |asset|
238
+ path = "#{asset[:path]}?embed=true"
239
+ assert_not_equal( path, @embedder.embed_data_uri( path ) )
240
+ end
241
+ end
242
+
243
+ should "not encod unsupported asset types" do
244
+ @unsupported_assets.each do |asset|
245
+ path = "#{asset[:path]}?embed=true"
246
+ assert_equal( path, @embedder.embed_data_uri( path ) )
247
+ end
248
+ end
249
+
250
+ should "set correct mimetype for supported extensions" do
251
+ @supported_assets.each do |asset|
252
+ path = "#{asset[:path]}?embed=true"
253
+ extension = /(png|gif|jpg|jpeg)/.match( asset[:path] )
254
+ assert_match(/image\/#{extension}/, @embedder.embed_data_uri( path ) )
255
+ end
256
+ end
257
+ end # context
258
+ end
259
+
260
+ private
261
+ # expects the containing path to have been created already
262
+ def create_files( files = [] )
263
+ files.each do |file|
264
+ path = file[:path]
265
+ File.open(path, 'w') do |f|
266
+ f.write file[:content]
267
+ assert File.exists?( file[:path] )
268
+ end
269
+ end
270
+ end
271
+ end