condenser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +1 -0
  4. data/lib/condenser.rb +108 -0
  5. data/lib/condenser/asset.rb +221 -0
  6. data/lib/condenser/cache/memory_store.rb +92 -0
  7. data/lib/condenser/cache/null_store.rb +37 -0
  8. data/lib/condenser/context.rb +272 -0
  9. data/lib/condenser/encoding_utils.rb +155 -0
  10. data/lib/condenser/environment.rb +50 -0
  11. data/lib/condenser/errors.rb +11 -0
  12. data/lib/condenser/export.rb +68 -0
  13. data/lib/condenser/manifest.rb +89 -0
  14. data/lib/condenser/pipeline.rb +82 -0
  15. data/lib/condenser/processors/babel.min.js +25 -0
  16. data/lib/condenser/processors/babel_processor.rb +87 -0
  17. data/lib/condenser/processors/node_processor.rb +38 -0
  18. data/lib/condenser/processors/rollup.js +24083 -0
  19. data/lib/condenser/processors/rollup_processor.rb +164 -0
  20. data/lib/condenser/processors/sass_importer.rb +81 -0
  21. data/lib/condenser/processors/sass_processor.rb +300 -0
  22. data/lib/condenser/resolve.rb +202 -0
  23. data/lib/condenser/server.rb +307 -0
  24. data/lib/condenser/templating_engine/erb.rb +21 -0
  25. data/lib/condenser/utils.rb +32 -0
  26. data/lib/condenser/version.rb +3 -0
  27. data/lib/condenser/writers/file_writer.rb +28 -0
  28. data/lib/condenser/writers/zlib_writer.rb +42 -0
  29. data/test/cache_test.rb +24 -0
  30. data/test/environment_test.rb +49 -0
  31. data/test/manifest_test.rb +513 -0
  32. data/test/pipeline_test.rb +31 -0
  33. data/test/preprocessor/babel_test.rb +21 -0
  34. data/test/processors/rollup_test.rb +71 -0
  35. data/test/resolve_test.rb +105 -0
  36. data/test/server_test.rb +361 -0
  37. data/test/templates/erb_test.rb +18 -0
  38. data/test/test_helper.rb +68 -0
  39. data/test/transformers/scss_test.rb +49 -0
  40. metadata +193 -0
@@ -0,0 +1,21 @@
1
+ require "erubi"
2
+
3
+ class Condenser
4
+ class Erubi
5
+
6
+ def self.call(environment, data)
7
+ source = ::Erubi::Engine.new(data[:source], {
8
+ preamble: "@output_buffer = String.new;",
9
+ bufvar: "@output_buffer",
10
+ postamble: "@output_buffer.to_s"
11
+ }).src
12
+
13
+ source = eval("proc { #{source} }", nil, data[:filename] || "(erubi)")
14
+ source = environment.new_context_class.instance_eval(&source)
15
+
16
+
17
+ data[:source] = source
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ class Condenser
2
+ module Utils
3
+
4
+ # Public: Write to a file atomically. Useful for situations where you
5
+ # don't want other processes or threads to see half-written files.
6
+ #
7
+ # Utils.atomic_write('important.file') do |file|
8
+ # file.write('hello')
9
+ # end
10
+ #
11
+ # Returns nothing.
12
+ def self.atomic_write(filename)
13
+ dirname, basename = File.split(filename)
14
+ basename = [
15
+ basename,
16
+ Thread.current.object_id,
17
+ Process.pid,
18
+ rand(1000000)
19
+ ].join('.'.freeze)
20
+ tmpname = File.join(dirname, basename)
21
+
22
+ File.open(tmpname, 'wb+') do |f|
23
+ yield f
24
+ end
25
+
26
+ File.rename(tmpname, filename)
27
+ ensure
28
+ File.delete(tmpname) if File.exist?(tmpname)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ class Condenser
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,28 @@
1
+ require 'condenser/utils'
2
+
3
+ class Condenser
4
+ # Writes a an asset file to disk
5
+ class FileWriter
6
+
7
+ def skip?(asset, logger)
8
+ if ::File.exist?(asset.path)
9
+ logger.debug "Skipping #{ asset.filename }, already exists"
10
+ true
11
+ else
12
+ logger.info "Writing #{ asset.filename }"
13
+ false
14
+ end
15
+ end
16
+
17
+ def call(output_directory, asset)
18
+ filename = File.join(output_directory, asset.path)
19
+ FileUtils.mkdir_p(File.dirname(filename))
20
+ Utils.atomic_write(filename) do |file|
21
+ file.write(asset.source)
22
+ end
23
+
24
+ [asset.filename]
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,42 @@
1
+ require 'zlib'
2
+ require 'condenser/utils'
3
+
4
+ class Condenser
5
+ # Generates a `.gz` file using the zlib algorithm built into
6
+ # Ruby's standard library.
7
+ class ZlibWriter
8
+
9
+ # What mime types should we compress? This list comes from:
10
+ # https://www.fastly.com/blog/new-gzip-settings-and-deciding-what-compress
11
+ COMPRESSALBE_TYPES = %w( text/html application/x-javascript text/css
12
+ application/javascript text/javascript text/plain text/xml
13
+ application/json application/vnd.ms-fontobject application/x-font-opentype
14
+ application/x-font-truetype application/x-font-ttf application/xml font/eot
15
+ font/opentype font/otf image/svg+xml image/vnd.microsoft.icon image/x-icon)
16
+
17
+ def skip?(asset, logger)
18
+ target = "#{asset.path}.gz"
19
+ if ::File.exist?(target)
20
+ logger.debug "Skipping #{ target }, already exists"
21
+ true
22
+ else
23
+ logger.info "Writing #{ target }"
24
+ false
25
+ end
26
+ end
27
+
28
+ def call(output_directory, asset)
29
+ filename = File.join(output_directory, "#{asset.path}.gz")
30
+ FileUtils.mkdir_p(File.dirname(filename))
31
+ Utils.atomic_write(filename) do |file|
32
+ gz = Zlib::GzipWriter.new(file, Zlib::BEST_COMPRESSION)
33
+ gz.write(asset.source)
34
+ gz.close
35
+ # File.utime(mtime, mtime, file.path)
36
+ end
37
+
38
+ ["#{asset.filename}.gz"]
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class CacheTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ super
7
+ @env.cache = Condenser::Cache::MemoryStore.new
8
+ end
9
+
10
+ test 'resolving and asset twice only compiles once' do
11
+ file 'test.txt.erb', "1<%= 1 + 1 %>3\n"
12
+
13
+ assert_file 'test.txt', 'text/plain', <<~CSS
14
+ 123
15
+ CSS
16
+
17
+ Condenser::Erubi.stubs(:call).never
18
+
19
+ assert_file 'test.txt', 'text/plain', <<~CSS
20
+ 123
21
+ CSS
22
+ end
23
+
24
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ class EnvironmentTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ super
7
+ @env.clear_path
8
+ end
9
+
10
+ test "working directory is the default root" do
11
+ assert_equal Dir.pwd, Condenser.new.root
12
+ end
13
+
14
+ test "default logger level is set to warn" do
15
+ assert_equal Logger::WARN, @env.logger.level
16
+ end
17
+
18
+ test "paths" do
19
+ assert_equal [], @env.path
20
+ end
21
+
22
+ test "prepend_path" do
23
+ assert_equal [], @env.path
24
+ @env.prepend_path 'a'
25
+ @env.prepend_path 'b'
26
+ assert_equal ['b', 'a'].map { |d| File.expand_path(d, @path) }, @env.path
27
+ end
28
+
29
+ test "append_path" do
30
+ assert_equal [], @env.path
31
+ @env.append_path 'a'
32
+ @env.append_path 'b'
33
+ assert_equal ['a', 'b'].map { |d| File.expand_path(d, @path) }, @env.path
34
+ end
35
+
36
+ test "clear_path" do
37
+ @env.append_path 'a'
38
+ assert_not_empty @env.path
39
+ @env.clear_path
40
+ assert_empty @env.path
41
+ end
42
+
43
+ test "digestor=" do
44
+ assert_equal @env.digestor, Digest::SHA256
45
+ @env.digestor = Digest::MD5
46
+ assert_equal @env.digestor, Digest::MD5
47
+ end
48
+
49
+ end
@@ -0,0 +1,513 @@
1
+ require 'test_helper'
2
+
3
+ class ManifestTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ super
7
+ @dir = Dir.mktmpdir
8
+ end
9
+
10
+ def teardown
11
+ super
12
+ FileUtils.remove_entry(@dir, true)
13
+ end
14
+
15
+ test "specify full manifest filename" do
16
+ directory = Dir::tmpdir
17
+ filename = File.join(directory, 'manifest.json')
18
+
19
+ manifest = Condenser::Manifest.new(@env, filename)
20
+
21
+ assert_equal directory, manifest.directory
22
+ assert_equal filename, manifest.filename
23
+ end
24
+
25
+ test "specify manifest directory yields manifest.json" do
26
+ manifest = Condenser::Manifest.new(@env, @dir)
27
+
28
+ assert_equal @dir, manifest.directory
29
+ assert_match('manifest.json', File.basename(manifest.filename))
30
+ end
31
+
32
+ test "must specify manifest directory or filename" do
33
+ assert_raises ArgumentError do
34
+ Condenser::Manifest.new(@env)
35
+ end
36
+ end
37
+
38
+ test "must specify env to compile assets" do
39
+ manifest = Condenser::Manifest.new(@dir)
40
+
41
+ assert_raises Condenser::Error do
42
+ manifest.compile('application.js')
43
+ end
44
+ end
45
+
46
+ test "compile asset" do
47
+ file 'application.js', <<-JS
48
+ console.log(1);
49
+ JS
50
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
51
+
52
+ asset = @env['application.js']
53
+ assert !File.exist?("#{@dir}/#{asset.path}")
54
+
55
+ manifest.compile('application.js')
56
+ assert File.directory?(manifest.directory)
57
+ assert File.file?(manifest.filename)
58
+
59
+ assert File.exist?("#{@dir}/manifest.json")
60
+ assert File.exist?("#{@dir}/#{asset.path}")
61
+ assert File.exist?("#{@dir}/#{asset.path}.gz")
62
+
63
+ data = JSON.parse(File.read(manifest.filename))
64
+ assert data['application.js']
65
+ assert data['application.js']['size'] > 16
66
+ assert_equal asset.path, data['application.js']['path']
67
+ end
68
+
69
+ # TODO:
70
+ # test "compile asset with aliased index links" do
71
+ # manifest = Sprockets::Manifest.new(@env, File.join(@dir, 'manifest.json'))
72
+ #
73
+ # main_digest_path = @env['alias-index-link.js'].path
74
+ # dep_digest_path = @env['coffee.js'].path
75
+ #
76
+ # assert !File.exist?("#{@dir}/#{main_digest_path}")
77
+ # assert !File.exist?("#{@dir}/#{dep_digest_path}")
78
+ #
79
+ # manifest.compile('alias-index-link.js')
80
+ # assert File.directory?(manifest.directory)
81
+ # assert File.file?(manifest.filename)
82
+ #
83
+ # assert File.exist?("#{@dir}/manifest.json")
84
+ # assert File.exist?("#{@dir}/#{main_digest_path}")
85
+ # assert File.exist?("#{@dir}/#{dep_digest_path}")
86
+ #
87
+ # data = JSON.parse(File.read(manifest.filename))
88
+ #
89
+ # assert data['files'][main_digest_path]
90
+ # assert data['files'][dep_digest_path]
91
+ # assert_equal "alias-index-link.js", data['files'][main_digest_path]['logical_path']
92
+ # assert_equal "coffee.js", data['files'][dep_digest_path]['logical_path']
93
+ # assert_equal main_digest_path, data['assets']['alias-index-link.js']
94
+ # assert_equal dep_digest_path, data['assets']['coffee.js']
95
+ # end
96
+ #
97
+ test "compile to directory and seperate location" do
98
+ file 'application.js', <<-JS
99
+ console.log(1);
100
+ JS
101
+
102
+ root = File.join(Dir::tmpdir, 'public')
103
+ dir = File.join(root, 'assets')
104
+ path = File.join(root, 'manifests', 'manifest-123.json')
105
+
106
+ FileUtils.remove_entry(root, true)
107
+
108
+ assert !File.exist?(root)
109
+ manifest = Condenser::Manifest.new(@env, dir, path)
110
+
111
+ manifest.compile('application.js')
112
+ assert File.directory?(manifest.directory)
113
+ assert File.file?(path)
114
+ FileUtils.remove_entry(root, true)
115
+ end
116
+
117
+ # TODO:
118
+ # test "compile asset with absolute path" do
119
+ # manifest = Sprockets::Manifest.new(@env, File.join(@dir, 'manifest.json'))
120
+ #
121
+ # digest_path = @env['gallery.js'].path
122
+ #
123
+ # assert !File.exist?("#{@dir}/#{digest_path}")
124
+ #
125
+ # manifest.compile(fixture_path('default/gallery.js'))
126
+ #
127
+ # assert File.exist?("#{@dir}/manifest.json")
128
+ # assert File.exist?("#{@dir}/#{digest_path}")
129
+ #
130
+ # data = JSON.parse(File.read(manifest.filename))
131
+ # assert data['files'][digest_path]
132
+ # assert_equal digest_path, data['assets']['gallery.js']
133
+ # end
134
+
135
+ test "compile multiple assets" do
136
+ file 'application.js', <<-JS
137
+ console.log(1);
138
+ JS
139
+
140
+ file 'gallery.css', <<-CSS
141
+ * { color: green }
142
+ CSS
143
+
144
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
145
+
146
+ app_digest_path = @env.find_export('application.js').path
147
+ gallery_digest_path = @env.find_export('gallery.css').path
148
+
149
+ assert !File.exist?("#{@dir}/#{app_digest_path}")
150
+ assert !File.exist?("#{@dir}/#{gallery_digest_path}")
151
+
152
+ manifest.compile('application.js', 'gallery.css')
153
+
154
+ assert File.exist?("#{@dir}/manifest.json")
155
+ puts app_digest_path
156
+ puts Dir.glob(File.join(@dir, '**/*'))
157
+ assert File.exist?("#{@dir}/#{app_digest_path}")
158
+ assert File.exist?("#{@dir}/#{gallery_digest_path}")
159
+
160
+ data = JSON.parse(File.read(manifest.filename))
161
+ assert data['application.js']
162
+ assert data['gallery.css']
163
+ assert_equal app_digest_path, data['application.js']['path']
164
+ assert_equal gallery_digest_path, data['gallery.css']['path']
165
+ end
166
+
167
+ # TODO:
168
+ # test "compile with transformed asset" do
169
+ # assert svg_digest_path = @env['logo.svg'].path
170
+ # assert png_digest_path = @env['logo.png'].path
171
+ #
172
+ # assert !File.exist?("#{@dir}/#{svg_digest_path}")
173
+ # assert !File.exist?("#{@dir}/#{png_digest_path}")
174
+ #
175
+ # manifest = Sprockets::Manifest.new(@env, File.join(@dir, 'manifest.json'))
176
+ # manifest.compile('logo.svg', 'logo.png')
177
+ #
178
+ # assert File.exist?("#{@dir}/manifest.json")
179
+ # assert File.exist?("#{@dir}/#{svg_digest_path}")
180
+ # assert File.exist?("#{@dir}/#{png_digest_path}")
181
+ #
182
+ # data = JSON.parse(File.read(manifest.filename))
183
+ # assert data['files'][svg_digest_path]
184
+ # assert data['files'][png_digest_path]
185
+ # assert_equal svg_digest_path, data['assets']['logo.svg']
186
+ # assert_equal png_digest_path, data['assets']['logo.png']
187
+ # end
188
+
189
+ # TODO:
190
+ # test "compile asset with links" do
191
+ # manifest = Sprockets::Manifest.new(@env, File.join(@dir, 'manifest.json'))
192
+ #
193
+ # main_digest_path = @env['gallery-link.js'].path
194
+ # dep_digest_path = @env['gallery.js'].path
195
+ #
196
+ # assert !File.exist?("#{@dir}/#{main_digest_path}")
197
+ # assert !File.exist?("#{@dir}/#{dep_digest_path}")
198
+ #
199
+ # manifest.compile('gallery-link.js')
200
+ # assert File.directory?(manifest.directory)
201
+ # assert File.file?(manifest.filename)
202
+ #
203
+ # assert File.exist?("#{@dir}/manifest.json")
204
+ # assert File.exist?("#{@dir}/#{main_digest_path}")
205
+ # assert File.exist?("#{@dir}/#{dep_digest_path}")
206
+ #
207
+ # data = JSON.parse(File.read(manifest.filename))
208
+ # assert data['files'][main_digest_path]
209
+ # assert data['files'][dep_digest_path]
210
+ # assert_equal "gallery-link.js", data['files'][main_digest_path]['logical_path']
211
+ # assert_equal "gallery.js", data['files'][dep_digest_path]['logical_path']
212
+ # assert_equal main_digest_path, data['assets']['gallery-link.js']
213
+ # assert_equal dep_digest_path, data['assets']['gallery.js']
214
+ # end
215
+
216
+ # TODO:
217
+ # test "compile nested asset with links" do
218
+ # manifest = Sprockets::Manifest.new(@env, File.join(@dir, 'manifest.json'))
219
+ #
220
+ # main_digest_path = @env['explore-link.js'].path
221
+ # dep_digest_path = @env['gallery-link.js'].path
222
+ # subdep_digest_path = @env['gallery.js'].path
223
+ #
224
+ # assert !File.exist?("#{@dir}/#{main_digest_path}")
225
+ # assert !File.exist?("#{@dir}/#{dep_digest_path}")
226
+ # assert !File.exist?("#{@dir}/#{subdep_digest_path}")
227
+ #
228
+ # manifest.compile('explore-link.js')
229
+ # assert File.directory?(manifest.directory)
230
+ # assert File.file?(manifest.filename)
231
+ #
232
+ # assert File.exist?("#{@dir}/manifest.json")
233
+ # assert File.exist?("#{@dir}/#{main_digest_path}")
234
+ # assert File.exist?("#{@dir}/#{dep_digest_path}")
235
+ # assert File.exist?("#{@dir}/#{subdep_digest_path}")
236
+ #
237
+ # data = JSON.parse(File.read(manifest.filename))
238
+ # assert data['files'][main_digest_path]
239
+ # assert data['files'][dep_digest_path]
240
+ # assert data['files'][subdep_digest_path]
241
+ # assert_equal "explore-link.js", data['files'][main_digest_path]['logical_path']
242
+ # assert_equal "gallery-link.js", data['files'][dep_digest_path]['logical_path']
243
+ # assert_equal "gallery.js", data['files'][subdep_digest_path]['logical_path']
244
+ # assert_equal main_digest_path, data['assets']['explore-link.js']
245
+ # assert_equal dep_digest_path, data['assets']['gallery-link.js']
246
+ # assert_equal subdep_digest_path, data['assets']['gallery.js']
247
+ # end
248
+
249
+ test "recompile asset" do
250
+ file 'application.js', "console.log(1);"
251
+
252
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
253
+
254
+ digest_path = @env['application.js'].path
255
+ assert !File.exist?("#{@dir}/#{digest_path}"), Dir["#{@dir}/*"].inspect
256
+
257
+ manifest.compile('application.js')
258
+
259
+ assert File.exist?("#{@dir}/manifest.json")
260
+ assert File.exist?("#{@dir}/#{digest_path}")
261
+
262
+ data = JSON.parse(File.read(manifest.filename))
263
+ assert data['application.js']
264
+ assert_equal digest_path, data['application.js']['path']
265
+
266
+ File.write(File.join(@path, 'application.js'), "console.log(2);")
267
+
268
+ # mtime = Time.now + 1
269
+ # File.utime(mtime, mtime, filename)
270
+ new_digest_path = @env['application.js'].path
271
+ assert_not_equal new_digest_path, digest_path
272
+
273
+ manifest.compile('application.js')
274
+
275
+ assert File.exist?("#{@dir}/manifest.json")
276
+ assert File.exist?("#{@dir}/#{digest_path}")
277
+ assert File.exist?("#{@dir}/#{new_digest_path}")
278
+
279
+ data = JSON.parse(File.read(manifest.filename))
280
+ assert data['application.js']
281
+ assert_equal new_digest_path, data['application.js']['path']
282
+ end
283
+
284
+ test "test manifest does not exist" do
285
+ file 'application.js', "console.log(1);"
286
+
287
+ assert !File.exist?("#{@dir}/manifest.json")
288
+
289
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
290
+ manifest.compile('application.js')
291
+
292
+ assert File.exist?("#{@dir}/manifest.json")
293
+ data = JSON.parse(File.read(manifest.filename))
294
+ assert data['application.js']
295
+ end
296
+
297
+ test "test blank manifest" do
298
+ file 'application.js', "console.log(1);"
299
+
300
+ assert !File.exist?("#{@dir}/manifest.json")
301
+
302
+ FileUtils.mkdir_p(@dir)
303
+ File.write("#{@dir}/manifest.json", '{}')
304
+ assert_equal "{}", File.read("#{@dir}/manifest.json")
305
+
306
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
307
+ manifest.compile('application.js')
308
+
309
+ assert File.exist?("#{@dir}/manifest.json")
310
+ data = JSON.parse(File.read(manifest.filename))
311
+ assert data['application.js']
312
+ end
313
+
314
+ test "test skip invalid manifest" do
315
+ file 'application.js', "console.log(1);"
316
+
317
+ assert !File.exist?("#{@dir}/manifest.json")
318
+
319
+ FileUtils.mkdir_p(@dir)
320
+ File.write("#{@dir}/manifest.json", "not valid json;")
321
+ assert_equal "not valid json;", File.read("#{@dir}/manifest.json")
322
+
323
+ manifest = Condenser::Manifest.new(@env, File.join(@dir, 'manifest.json'))
324
+ manifest.compile('application.js')
325
+
326
+ assert File.exist?("#{@dir}/manifest.json")
327
+ data = JSON.parse(File.read(manifest.filename))
328
+ assert data['application.js']
329
+ end
330
+
331
+ test "nil environment raises compilation error" do
332
+ assert !File.exist?("#{@dir}/manifest.json")
333
+
334
+ manifest = Condenser::Manifest.new(nil, File.join(@dir, 'manifest.json'))
335
+ assert_raises Condenser::Error do
336
+ manifest.compile('application.js')
337
+ end
338
+ end
339
+
340
+ test "no environment raises compilation error" do
341
+ assert !File.exist?("#{@dir}/manifest.json")
342
+
343
+ manifest = Condenser::Manifest.new(File.join(@dir, 'manifest.json'))
344
+ assert_raises Condenser::Error do
345
+ manifest.compile('application.js')
346
+ end
347
+ end
348
+
349
+ # TODO:
350
+ # test "find_sources with environment" do
351
+ # manifest = Sprockets::Manifest.new(@env, @dir)
352
+ #
353
+ # result = manifest.find_sources("mobile/a.js", "mobile/b.js")
354
+ # assert_equal ["var A;\n", "var B;\n"], result.to_a.sort
355
+ #
356
+ # result = manifest.find_sources("not_existent.js", "also_not_existent.js")
357
+ # assert_equal [], result.to_a
358
+ #
359
+ # result = manifest.find_sources("mobile/a.js", "also_not_existent.js")
360
+ # assert_equal ["var A;\n"], result.to_a
361
+ # end
362
+
363
+ # TODO:
364
+ # test "find_sources without environment" do
365
+ # manifest = Sprockets::Manifest.new(@env, @dir)
366
+ # manifest.compile('mobile/a.js', 'mobile/b.js')
367
+ #
368
+ # manifest = Sprockets::Manifest.new(nil, @dir)
369
+ #
370
+ # result = manifest.find_sources("mobile/a.js", "mobile/b.js")
371
+ # assert_equal ["var A;\n", "var B;\n"], result.to_a
372
+ #
373
+ # result = manifest.find_sources("not_existent.js", "also_not_existent.js")
374
+ # assert_equal [], result.to_a
375
+ #
376
+ # result = manifest.find_sources("mobile/a.js", "also_not_existent.js")
377
+ # assert_equal ["var A;\n"], result.to_a
378
+ # end
379
+
380
+ test "compress non-binary assets" do
381
+ file 'gallery.css', 'x'
382
+ file 'application.js', 'x'
383
+ file 'logo.svg', 'x'
384
+ file 'favicon.ico', 'x'
385
+
386
+ manifest = Condenser::Manifest.new(@env, @dir)
387
+ %W{ gallery.css application.js logo.svg favicon.ico }.each do |file_name|
388
+ original_path = @env[file_name].path
389
+ manifest.compile(file_name)
390
+ assert File.exist?("#{@dir}/#{original_path}.gz"), "Expecting '#{original_path}' to generate gzipped file: '#{original_path}.gz' but it did not"
391
+ end
392
+ end
393
+
394
+ # TODO:
395
+ # test "writes gzip files even if files were already on disk" do
396
+ # @env.gzip = false
397
+ # manifest = Sprockets::Manifest.new(@env, @dir)
398
+ # files = %W{ gallery.css application.js logo.svg favicon.ico}
399
+ # files.each do |file_name|
400
+ # original_path = @env[file_name].path
401
+ # manifest.compile(file_name)
402
+ # assert File.exist?("#{@dir}/#{original_path}"), "Expecting '#{@dir}/#{original_path}' to exist but did not"
403
+ # end
404
+ #
405
+ # @env.gzip = true
406
+ # files.each do |file_name|
407
+ # original_path = @env[file_name].path
408
+ # manifest.compile(file_name)
409
+ # assert File.exist?("#{@dir}/#{original_path}.gz"), "Expecting '#{original_path}' to generate gzipped file: '#{original_path}.gz' but it did not"
410
+ # end
411
+ # end
412
+
413
+ # TODO:
414
+ # test "disable file gzip" do
415
+ # @env.gzip = false
416
+ # manifest = Sprockets::Manifest.new(@env, @dir)
417
+ # %W{ gallery.css application.js logo.svg favicon.ico }.each do |file_name|
418
+ # original_path = @env[file_name].path
419
+ # manifest.compile(file_name)
420
+ # refute File.exist?("#{@dir}/#{original_path}.gz"), "Expecting '#{original_path}' to not generate gzipped file: '#{original_path}.gz' but it did"
421
+ # end
422
+ # end
423
+
424
+ test "do not compress binary assets" do
425
+ file 'blank.gif', Random.new.bytes(128)
426
+
427
+ manifest = Condenser::Manifest.new(@env, @path)
428
+ %W{ blank.gif }.each do |file_name|
429
+ original_path = @env[file_name].path
430
+ manifest.compile(file_name)
431
+ refute File.exist?("#{@path}/#{original_path}.gz"), "Expecting '#{original_path}' to not generate gzipped file: '#{original_path}.gz' but it did"
432
+ end
433
+ end
434
+
435
+ # TODO:
436
+ # test 'raises exception when gzip fails' do
437
+ # manifest = Sprockets::Manifest.new(@env, @dir)
438
+ # Zlib::GzipWriter.stub(:new, -> (io, level) { fail 'kaboom' }) do
439
+ # ex = assert_raises(RuntimeError) { manifest.compile('application.js') }
440
+ # assert_equal 'kaboom', ex.message
441
+ # end
442
+ # end
443
+ #
444
+ # # Sleep duration to context switch between concurrent threads.
445
+ # CONTEXT_SWITCH_DURATION = 0.1
446
+ #
447
+ # # Record Exporter sequence with a delay to test concurrency.
448
+ # class SlowExporter < Sprockets::Exporters::Base
449
+ # class << self
450
+ # attr_accessor :seq
451
+ # end
452
+ #
453
+ # def call
454
+ # SlowExporter.seq << '0'
455
+ # sleep CONTEXT_SWITCH_DURATION
456
+ # SlowExporter.seq << '1'
457
+ # end
458
+ # end
459
+ #
460
+ # class SlowExporter2 < SlowExporter
461
+ # end
462
+ #
463
+ # test 'concurrent exporting' do
464
+ # # Register 2 exporters and compile 2 files to ensure that
465
+ # # all 4 exporting tasks run concurrently.
466
+ # SlowExporter.seq = []
467
+ # @env.register_exporter 'image/png',SlowExporter
468
+ # @env.register_exporter 'image/png',SlowExporter2
469
+ # Sprockets::Manifest.new(@env, @dir).compile('logo.png', 'troll.png')
470
+ # refute_equal %w(0 1 0 1 0 1 0 1), SlowExporter.seq
471
+ # end
472
+ #
473
+ # test 'sequential exporting' do
474
+ # @env.export_concurrent = false
475
+ # SlowExporter.seq = []
476
+ # @env.register_exporter 'image/png',SlowExporter
477
+ # @env.register_exporter 'image/png',SlowExporter2
478
+ # Sprockets::Manifest.new(@env, @dir).compile('logo.png', 'troll.png')
479
+ # assert_equal %w(0 1 0 1 0 1 0 1), SlowExporter.seq
480
+ # end
481
+ #
482
+ # # Record Processor sequence with a delay to test concurrency.
483
+ # class SlowProcessor
484
+ # attr_reader :seq
485
+ #
486
+ # def initialize
487
+ # @seq = []
488
+ # end
489
+ #
490
+ # def call(_)
491
+ # seq << '0'
492
+ # sleep CONTEXT_SWITCH_DURATION
493
+ # seq << '1'
494
+ # nil
495
+ # end
496
+ # end
497
+ #
498
+ # test 'concurrent processing' do
499
+ # processor = SlowProcessor.new
500
+ # @env.register_postprocessor 'image/png', processor
501
+ # Sprockets::Manifest.new(@env, @dir).compile('logo.png', 'troll.png')
502
+ # refute_equal %w(0 1 0 1), processor.seq
503
+ # end
504
+ #
505
+ # test 'sequential processing' do
506
+ # @env.export_concurrent = false
507
+ # processor = SlowProcessor.new
508
+ # @env.register_postprocessor 'image/png', processor
509
+ # Sprockets::Manifest.new(@env, @dir).compile('logo.png', 'troll.png')
510
+ # assert_equal %w(0 1 0 1), processor.seq
511
+ # end
512
+
513
+ end