condenser 0.0.1

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 (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