ktheory-juicer 1.0.0.ktheory1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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