psyho_juicer 1.0.0 → 1.0.7
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.
- data/Gemfile +11 -0
- data/History.txt +33 -0
- data/Readme.rdoc +16 -4
- data/VERSION +1 -1
- data/lib/juicer/asset/path.rb +6 -10
- data/lib/juicer/cache_buster.rb +53 -13
- data/lib/juicer/command/merge.rb +14 -6
- data/lib/juicer/css_cache_buster.rb +6 -4
- data/lib/juicer/dependency_resolver/css_dependency_resolver.rb +1 -1
- data/lib/juicer/image_embed.rb +18 -20
- data/lib/juicer/install/yui_compressor_installer.rb +2 -1
- data/lib/juicer/merger/stylesheet_merger.rb +5 -5
- data/lib/juicer/minifyer/closure_compiler.rb +1 -1
- data/lib/juicer.rb +1 -1
- data/lib/psyho_juicer.rb +1 -0
- data/test/data/Changelog.txt +10 -0
- data/test/data/a.css +3 -0
- data/test/data/a.js +5 -0
- data/test/data/a1.css +5 -0
- data/test/data/b.css +1 -0
- data/test/data/b.js +5 -0
- data/test/data/b1.css +5 -0
- data/test/data/b2.css +5 -0
- data/test/data/c1.css +3 -0
- data/test/data/css/2.gif +1 -0
- data/test/data/css/test.css +15 -0
- data/test/data/css/test2.css +1 -0
- data/test/data/css/test3.css +12 -0
- data/test/data/d1.css +3 -0
- data/test/data/images/1.png +1 -0
- data/test/data/my_app.js +2 -0
- data/test/data/not-ok.js +2 -0
- data/test/data/ok.js +3 -0
- data/test/data/path_test.css +5 -0
- data/test/data/path_test2.css +14 -0
- data/test/data/pkg/module/moda.js +2 -0
- data/test/data/pkg/module/modb.js +3 -0
- data/test/data/pkg/pkg.js +1 -0
- data/test/fixtures/git-tracked-file.txt +1 -0
- data/test/fixtures/yui-download.html +103 -243
- data/test/test_helper.rb +27 -1
- data/test/unit/juicer/asset/path_test.rb +7 -1
- data/test/unit/juicer/cache_buster_test.rb +95 -5
- data/test/unit/juicer/command/util_test.rb +1 -1
- data/test/unit/juicer/css_cache_buster_test.rb +127 -32
- data/test/unit/juicer/image_embed_test.rb +35 -0
- data/test/unit/juicer/merger/stylesheet_merger_test.rb +175 -109
- data/test/unit/juicer/minifyer/closure_compressor_test.rb +3 -3
- metadata +68 -21
@@ -26,10 +26,17 @@ class CacheBusterTest < Test::Unit::TestCase
|
|
26
26
|
assert_equal @filename, Juicer::CacheBuster.clean("#@filename?1234567890", nil)
|
27
27
|
end
|
28
28
|
|
29
|
+
should "not destroy numeric file names with no cache buster name" do
|
30
|
+
@numeric_filename = "815.gif"
|
31
|
+
File.open(@numeric_filename, "w") { |f| f.puts "Testing" }
|
32
|
+
assert_equal @numeric_filename, Juicer::CacheBuster.clean("#@numeric_filename?1234567890", nil)
|
33
|
+
File.delete(@numeric_filename)
|
34
|
+
end
|
35
|
+
|
29
36
|
should "remove cache buster query parameters with custom name" do
|
30
37
|
assert_equal @filename, Juicer::CacheBuster.clean("#@filename?cb=1234567890", :cb)
|
31
38
|
end
|
32
|
-
|
39
|
+
|
33
40
|
should "remove hard cache buster" do
|
34
41
|
assert_equal @filename, Juicer::CacheBuster.clean(@filename.sub(/(\.txt)/, '-jcb1234567890\1'))
|
35
42
|
end
|
@@ -63,12 +70,47 @@ class CacheBusterTest < Test::Unit::TestCase
|
|
63
70
|
|
64
71
|
should "include only mtime when parameter name is nil" do
|
65
72
|
mtime = File.mtime(@filename).to_i
|
66
|
-
assert_equal "#@filename?#{mtime}", Juicer::CacheBuster.soft(@filename, nil)
|
73
|
+
assert_equal "#@filename?#{mtime}", Juicer::CacheBuster.soft(@filename, :parameter => nil)
|
67
74
|
end
|
68
75
|
|
69
76
|
should "include custom parameter name" do
|
70
77
|
mtime = File.mtime(@filename).to_i
|
71
|
-
assert_equal "#@filename?juicer=#{mtime}", Juicer::CacheBuster.soft(@filename, :juicer)
|
78
|
+
assert_equal "#@filename?juicer=#{mtime}", Juicer::CacheBuster.soft(@filename, :parameter => :juicer)
|
79
|
+
end
|
80
|
+
|
81
|
+
should "use git cache buster if passed as a parameter" do
|
82
|
+
revision = revision_of_tracked_file
|
83
|
+
file_name = git_tracked_file
|
84
|
+
assert_equal "#{file_name}?jcb=#{revision}", Juicer::CacheBuster.soft(file_name, :revision_type => :git)
|
85
|
+
end
|
86
|
+
|
87
|
+
should "use mtime cache buster if passed as a parameter" do
|
88
|
+
file_name = git_tracked_file
|
89
|
+
revision = File.mtime(file_name).to_i
|
90
|
+
assert_equal "#{file_name}?jcb=#{revision}", Juicer::CacheBuster.soft(file_name, :revision_type => :mtime)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "creating rails-style cache busters" do
|
95
|
+
should "clean file before adding new cache buster" do
|
96
|
+
cache_buster = "1234567890"
|
97
|
+
assert_no_match /#{cache_buster}/, Juicer::CacheBuster.rails("#@filename?#{cache_buster}")
|
98
|
+
end
|
99
|
+
|
100
|
+
should "append no cache buster when parameters exist" do
|
101
|
+
parameters = "id=1"
|
102
|
+
assert_match /#{parameters}/, Juicer::CacheBuster.rails("#@filename?#{parameters}")
|
103
|
+
end
|
104
|
+
|
105
|
+
should "include only mtime as query parameter" do
|
106
|
+
mtime = File.mtime(@filename).to_i
|
107
|
+
assert_equal "#@filename?#{mtime}", Juicer::CacheBuster.rails(@filename)
|
108
|
+
end
|
109
|
+
|
110
|
+
should "always use mtime cache busters" do
|
111
|
+
file_name = git_tracked_file
|
112
|
+
revision = Juicer::CacheBuster::Revision.mtime(file_name)
|
113
|
+
assert_equal "#{file_name}?#{revision}", Juicer::CacheBuster.rails(file_name, :revision_type => :git)
|
72
114
|
end
|
73
115
|
end
|
74
116
|
|
@@ -93,12 +135,60 @@ class CacheBusterTest < Test::Unit::TestCase
|
|
93
135
|
|
94
136
|
should "include only mtime when parameter name is nil" do
|
95
137
|
mtime = File.mtime("#@filename.txt").to_i
|
96
|
-
assert_equal "#@filename-#{mtime}.txt", Juicer::CacheBuster.hard("#@filename.txt", nil)
|
138
|
+
assert_equal "#@filename-#{mtime}.txt", Juicer::CacheBuster.hard("#@filename.txt", :parameter => nil)
|
97
139
|
end
|
98
140
|
|
99
141
|
should "include custom parameter name" do
|
100
142
|
mtime = File.mtime("#@filename.txt").to_i
|
101
|
-
assert_equal "#@filename-juicer#{mtime}.txt", Juicer::CacheBuster.hard("#@filename.txt", :juicer)
|
143
|
+
assert_equal "#@filename-juicer#{mtime}.txt", Juicer::CacheBuster.hard("#@filename.txt", :parameter => :juicer)
|
144
|
+
end
|
145
|
+
|
146
|
+
should "use git cache buster if passed as a paramater" do
|
147
|
+
revision = revision_of_tracked_file
|
148
|
+
file_name = git_tracked_file
|
149
|
+
assert_equal "#{file_name.gsub('.txt', '')}-jcb#{revision}.txt", Juicer::CacheBuster.hard(file_name, :revision_type => :git)
|
150
|
+
end
|
151
|
+
|
152
|
+
should "use mtime cache buster if passed as a parameter" do
|
153
|
+
file_name = git_tracked_file
|
154
|
+
revision = File.mtime(file_name).to_i
|
155
|
+
assert_equal "#{file_name.gsub('.txt', '')}-jcb#{revision}.txt", Juicer::CacheBuster.hard(file_name, :revision_type => :mtime)
|
102
156
|
end
|
103
157
|
end
|
158
|
+
|
159
|
+
context "Revision" do
|
160
|
+
context "mtime" do
|
161
|
+
should "return the file modification time" do
|
162
|
+
assert_equal File.mtime(@filename).to_i, Juicer::CacheBuster::Revision.mtime(@filename)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
context "git" do
|
167
|
+
should "return the last commit that modified the file if file is tracked by git" do
|
168
|
+
# given
|
169
|
+
expected_hash = revision_of_tracked_file
|
170
|
+
file_name = git_tracked_file
|
171
|
+
|
172
|
+
# then
|
173
|
+
assert_equal expected_hash, Juicer::CacheBuster::Revision.git(file_name)
|
174
|
+
end
|
175
|
+
|
176
|
+
should "return the last commit of the repository if file is not tracked by git" do
|
177
|
+
# given
|
178
|
+
last_commit = %x[git log -1 --pretty=oneline].split.first
|
179
|
+
|
180
|
+
# then
|
181
|
+
assert_equal last_commit, Juicer::CacheBuster::Revision.git(@filename)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def git_tracked_file
|
187
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'git-tracked-file.txt'))
|
188
|
+
end
|
189
|
+
|
190
|
+
def revision_of_tracked_file
|
191
|
+
'98477054651e764b4ece65f417df3eb17eb5de83'
|
192
|
+
end
|
193
|
+
|
104
194
|
end
|
@@ -6,7 +6,7 @@ end
|
|
6
6
|
|
7
7
|
class TestCommandUtil < Test::Unit::TestCase
|
8
8
|
|
9
|
-
CSS_FILES = %w{a.css a1.css b.css b1.css c1.css d1.css path_test.css path_test2.css}
|
9
|
+
CSS_FILES = %w{a.css a1.css b.css b1.css b2.css c1.css d1.css path_test.css path_test2.css}
|
10
10
|
JS_FILES = %w{a.js}
|
11
11
|
ALL_FILES = (CSS_FILES + JS_FILES).sort
|
12
12
|
|
@@ -11,61 +11,156 @@ class TestCssCacheBuster < Test::Unit::TestCase
|
|
11
11
|
Juicer::Test::FileSetup.new.create
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
context "finding urls" do
|
15
|
+
should "find all urls" do
|
16
|
+
urls = @buster.urls(path("css/test.css"))
|
17
|
+
assert_equal 4, urls.length
|
18
|
+
assert_equal "../a1.css../images/1.png2.gif2.gif", urls.collect { |a| a.path }.sort.join.gsub(path("/"), "")
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
context "image references" do
|
23
|
+
should "update image urls" do
|
24
|
+
file = path("css/test.css")
|
25
|
+
buster = Juicer::CssCacheBuster.new
|
26
|
+
buster.save file
|
24
27
|
|
25
|
-
|
26
|
-
|
28
|
+
File.read(file).scan(/url\(([^\)]*)\)/m).each do |path|
|
29
|
+
assert_match(/[^\?]*\?jcb=\d+/, path.first)
|
30
|
+
end
|
27
31
|
end
|
28
|
-
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
should "not add multiple cache busters" do
|
34
|
+
file = path("css/test.css")
|
35
|
+
buster = Juicer::CssCacheBuster.new
|
36
|
+
buster.save file
|
37
|
+
|
38
|
+
assert_no_match /2\.gif\?jcb=\d+\?jcb=/, File.read(file)
|
39
|
+
end
|
33
40
|
|
34
|
-
|
41
|
+
should "not add multiple cache busters when asset host cycling is used" do
|
42
|
+
file = path("css/test3.css")
|
43
|
+
buster = Juicer::CssCacheBuster.new( { :hosts => [ 'http://assets1', 'http://assets2', 'http://assets3' ], :document_root => './test/data' } )
|
35
44
|
buster.save file
|
45
|
+
|
46
|
+
assert_no_match /2\.gif\?jcb=\d+\?jcb=/, File.read(file)
|
36
47
|
end
|
48
|
+
|
37
49
|
end
|
38
50
|
|
39
|
-
|
40
|
-
|
41
|
-
|
51
|
+
context "absolute paths" do
|
52
|
+
# should "fail without document root" do
|
53
|
+
# file = path("css/test2.css")
|
54
|
+
# buster = Juicer::CssCacheBuster.new
|
42
55
|
|
43
|
-
|
44
|
-
|
56
|
+
# assert_raise FileNotFoundError do
|
57
|
+
# buster.save file
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
|
61
|
+
should "resolve with document root" do
|
62
|
+
file = path("css/test.css")
|
63
|
+
buster = Juicer::CssCacheBuster.new :document_root => path("")
|
64
|
+
|
65
|
+
assert_nothing_raised do
|
66
|
+
buster.save file
|
67
|
+
end
|
68
|
+
|
69
|
+
File.read(file).scan(/url\(([^\)]*)\)/m).each do |path|
|
70
|
+
assert_match(/[^\?]*\?jcb=\d+/, path.first)
|
71
|
+
end
|
45
72
|
end
|
73
|
+
end
|
46
74
|
|
47
|
-
|
48
|
-
|
75
|
+
context "cache busters" do
|
76
|
+
should "add mtime to urls" do
|
77
|
+
File.open(path("a2.css"), "w") { |f| f.puts "" }
|
78
|
+
file = path("path_test2.css")
|
79
|
+
output = path("path_test3.css")
|
80
|
+
buster = Juicer::CssCacheBuster.new :document_root => path("")
|
81
|
+
buster.save file, output
|
82
|
+
|
83
|
+
buster.urls(output).each { |url| assert url !~ /(jcb=\d+).*(jcb=\d+)/, url }
|
49
84
|
end
|
50
85
|
end
|
51
86
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
87
|
+
context "rails cache busters" do
|
88
|
+
should "should append mtime to urls" do
|
89
|
+
File.open(path("a2.css"), "w") { |f| f.puts "" }
|
90
|
+
file = path("path_test2.css")
|
91
|
+
output = path("path_test3.css")
|
92
|
+
buster = Juicer::CssCacheBuster.new :document_root => path(""), :type => :rails
|
93
|
+
buster.save file, output
|
58
94
|
|
59
|
-
|
95
|
+
buster.urls(output).each { |asset| assert_match /\?\d+$/, asset.path }
|
96
|
+
end
|
60
97
|
end
|
98
|
+
|
99
|
+
context "hard cache busters" do
|
100
|
+
should "should alter file name" do
|
101
|
+
File.open(path("a2.css"), "w") { |f| f.puts "" }
|
102
|
+
file = path("path_test2.css")
|
103
|
+
output = path("path_test3.css")
|
104
|
+
buster = Juicer::CssCacheBuster.new :document_root => path(""), :type => :hard
|
105
|
+
buster.save file, output
|
61
106
|
|
62
|
-
|
107
|
+
buster.urls(output).each { |asset| assert_match /-jcb\d+\.[a-z]{3}$/, asset.path }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def given_a_buster_with_type_hard_and_format(format)
|
63
112
|
File.open(path("a2.css"), "w") { |f| f.puts "" }
|
113
|
+
return Juicer::CssCacheBuster.new :document_root => path(""), :type => :hard, :format => format
|
114
|
+
end
|
115
|
+
|
116
|
+
def when_buster_saves_file(buster)
|
64
117
|
file = path("path_test2.css")
|
65
118
|
output = path("path_test3.css")
|
66
|
-
buster = Juicer::CssCacheBuster.new :document_root => path(""), :type => :hard
|
67
119
|
buster.save file, output
|
120
|
+
return output
|
121
|
+
end
|
68
122
|
|
69
|
-
|
123
|
+
def assert_all_urls_match(buster, output, pattern)
|
124
|
+
buster.urls(output).each { |asset| assert_match pattern, asset.path }
|
125
|
+
end
|
126
|
+
|
127
|
+
context "cache busters with git format" do
|
128
|
+
should "include last git commit touching that file in file name" do
|
129
|
+
# given
|
130
|
+
Juicer::CacheBuster::Revision.stubs(:git => 'GIT_LAST_COMMIT')
|
131
|
+
buster = given_a_buster_with_type_hard_and_format(:git)
|
132
|
+
|
133
|
+
# when
|
134
|
+
output = when_buster_saves_file(buster)
|
135
|
+
|
136
|
+
# then
|
137
|
+
assert_all_urls_match(buster, output, /-jcbGIT_LAST_COMMIT\.[a-z]{3}$/)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "cache busters with mtime format" do
|
142
|
+
should "include file modification time in file name" do
|
143
|
+
# given
|
144
|
+
File.stubs(:mtime => 123)
|
145
|
+
buster = given_a_buster_with_type_hard_and_format(:mtime)
|
146
|
+
|
147
|
+
# when
|
148
|
+
output = when_buster_saves_file(buster)
|
149
|
+
|
150
|
+
# then
|
151
|
+
assert_all_urls_match(buster, output, /-jcb123\.[a-z]{3}$/)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "non-existent urls" do
|
156
|
+
should "not raise" do
|
157
|
+
File.open(path("a2.css"), "w") { |f| f.puts "a { background: url(i/dont/exist.fck); }" }
|
158
|
+
file = path("a2.css")
|
159
|
+
buster = Juicer::CssCacheBuster.new :document_root => path("")
|
160
|
+
|
161
|
+
assert_nothing_raised do
|
162
|
+
buster.save file
|
163
|
+
end
|
164
|
+
end
|
70
165
|
end
|
71
166
|
end
|
@@ -73,6 +73,41 @@ class TestImageEmbed < Test::Unit::TestCase
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
context "non empty document root" do
|
77
|
+
setup do
|
78
|
+
@document_root = '/path/to/public/dir'
|
79
|
+
@another_embedder = Juicer::ImageEmbed.new(:type => :data_uri, :document_root => @document_root)
|
80
|
+
@files = [{ :path => "#{@document_root}/images/custom-file.png", :filename => '/images/custom-file.png', :content => "hello png!" }]
|
81
|
+
create_files(@files)
|
82
|
+
end
|
83
|
+
|
84
|
+
should "embed urls with embedder" do
|
85
|
+
stylesheets = [{ :path => "#{@document_root}/stylesheets/test_absolute_path.css", :content => "body: { background: url(#{@files.first[:filename]}?embed=true); }" }]
|
86
|
+
create_files(stylesheets)
|
87
|
+
|
88
|
+
@another_embedder.save stylesheets.first[:path]
|
89
|
+
css_contents = File.read(stylesheets.first[:path])
|
90
|
+
|
91
|
+
# encode the image
|
92
|
+
image_contents = File.read(@files.first[:path])
|
93
|
+
data_uri = Datafy::make_data_uri(image_contents, 'image/png')
|
94
|
+
|
95
|
+
# make sure the encoded data_uri is present in the stylesheet
|
96
|
+
assert css_contents.include?(data_uri)
|
97
|
+
end
|
98
|
+
|
99
|
+
should "not embed urls with embedder" do
|
100
|
+
stylesheets = [{ :path => "#{@document_root}/stylesheets/test_absolute_path.css", :content => "body: { background: url(#{@files.first[:filename]}?embed=false); }" }]
|
101
|
+
create_files(stylesheets)
|
102
|
+
|
103
|
+
@another_embedder.save stylesheets.first[:path]
|
104
|
+
css_contents = File.read(stylesheets.first[:path])
|
105
|
+
|
106
|
+
# encode the image
|
107
|
+
assert css_contents.include?(@files.first[:filename])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
76
111
|
context "with duplicated urls" do
|
77
112
|
setup do
|
78
113
|
@stylesheets = [{
|