image_optim 0.29.0 → 0.30.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -3
- data/CHANGELOG.markdown +4 -0
- data/README.markdown +2 -1
- data/Vagrantfile +1 -1
- data/image_optim.gemspec +1 -1
- data/lib/image_optim.rb +15 -3
- data/lib/image_optim/bin_resolver/bin.rb +7 -7
- data/lib/image_optim/cache.rb +6 -0
- data/lib/image_optim/cmd.rb +45 -6
- data/lib/image_optim/config.rb +9 -1
- data/lib/image_optim/elapsed_time.rb +26 -0
- data/lib/image_optim/errors.rb +9 -0
- data/lib/image_optim/runner/option_parser.rb +4 -0
- data/lib/image_optim/timer.rb +25 -0
- data/lib/image_optim/worker.rb +24 -12
- data/lib/image_optim/worker/advpng.rb +2 -2
- data/lib/image_optim/worker/gifsicle.rb +3 -3
- data/lib/image_optim/worker/jhead.rb +2 -2
- data/lib/image_optim/worker/jpegoptim.rb +2 -2
- data/lib/image_optim/worker/jpegrecompress.rb +2 -2
- data/lib/image_optim/worker/jpegtran.rb +3 -3
- data/lib/image_optim/worker/optipng.rb +2 -2
- data/lib/image_optim/worker/pngcrush.rb +2 -2
- data/lib/image_optim/worker/pngout.rb +2 -2
- data/lib/image_optim/worker/pngquant.rb +2 -2
- data/lib/image_optim/worker/svgo.rb +2 -2
- data/script/worker_analysis +4 -4
- data/spec/image_optim/bin_resolver_spec.rb +5 -5
- data/spec/image_optim/cache_path_spec.rb +3 -7
- data/spec/image_optim/cache_spec.rb +7 -7
- data/spec/image_optim/cmd_spec.rb +58 -6
- data/spec/image_optim/config_spec.rb +36 -20
- data/spec/image_optim/elapsed_time_spec.rb +14 -0
- data/spec/image_optim/hash_helpers_spec.rb +18 -18
- data/spec/image_optim/option_definition_spec.rb +6 -6
- data/spec/image_optim/path_spec.rb +4 -8
- data/spec/image_optim/runner/option_parser_spec.rb +4 -4
- data/spec/image_optim/timer_spec.rb +32 -0
- data/spec/image_optim/worker/jpegrecompress_spec.rb +2 -2
- data/spec/image_optim/worker/optipng_spec.rb +11 -11
- data/spec/image_optim/worker/pngquant_spec.rb +5 -5
- data/spec/image_optim/worker_spec.rb +17 -17
- data/spec/image_optim_spec.rb +46 -9
- data/spec/spec_helper.rb +16 -15
- metadata +11 -4
@@ -21,7 +21,7 @@ class ImageOptim
|
|
21
21
|
4
|
22
22
|
end
|
23
23
|
|
24
|
-
def optimize(src, dst)
|
24
|
+
def optimize(src, dst, options = {})
|
25
25
|
src.copy(dst)
|
26
26
|
args = %W[
|
27
27
|
--recompress
|
@@ -30,7 +30,7 @@ class ImageOptim
|
|
30
30
|
--
|
31
31
|
#{dst}
|
32
32
|
]
|
33
|
-
execute(:advpng,
|
33
|
+
execute(:advpng, args, options) && optimized?(src, dst)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -12,7 +12,7 @@ class ImageOptim
|
|
12
12
|
return super if options.key?(:interlace)
|
13
13
|
|
14
14
|
[false, true].map do |interlace|
|
15
|
-
new(image_optim, options.merge(:
|
15
|
+
new(image_optim, options.merge(interlace: interlace))
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -37,7 +37,7 @@ class ImageOptim
|
|
37
37
|
CAREFUL_OPTION =
|
38
38
|
option(:careful, false, 'Avoid bugs with some software'){ |v| !!v }
|
39
39
|
|
40
|
-
def optimize(src, dst)
|
40
|
+
def optimize(src, dst, options = {})
|
41
41
|
args = %W[
|
42
42
|
--output=#{dst}
|
43
43
|
--no-comments
|
@@ -58,7 +58,7 @@ class ImageOptim
|
|
58
58
|
end
|
59
59
|
args.unshift '--careful' if careful
|
60
60
|
args.unshift "--optimize=#{level}" if level
|
61
|
-
execute(:gifsicle,
|
61
|
+
execute(:gifsicle, args, options) && optimized?(src, dst)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -25,7 +25,7 @@ class ImageOptim
|
|
25
25
|
[:jhead, :jpegtran]
|
26
26
|
end
|
27
27
|
|
28
|
-
def optimize(src, dst)
|
28
|
+
def optimize(src, dst, options = {})
|
29
29
|
return false unless oriented?(src)
|
30
30
|
|
31
31
|
src.copy(dst)
|
@@ -34,7 +34,7 @@ class ImageOptim
|
|
34
34
|
#{dst}
|
35
35
|
]
|
36
36
|
resolve_bin!(:jpegtran)
|
37
|
-
execute(:jhead,
|
37
|
+
execute(:jhead, args, options) && dst.size?
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
@@ -47,7 +47,7 @@ class ImageOptim
|
|
47
47
|
max_quality < 100 ? -1 : 0
|
48
48
|
end
|
49
49
|
|
50
|
-
def optimize(src, dst)
|
50
|
+
def optimize(src, dst, options = {})
|
51
51
|
src.copy(dst)
|
52
52
|
args = %W[
|
53
53
|
--quiet
|
@@ -58,7 +58,7 @@ class ImageOptim
|
|
58
58
|
args.unshift "--strip-#{strip_marker}"
|
59
59
|
end
|
60
60
|
args.unshift "--max=#{max_quality}" if max_quality < 100
|
61
|
-
execute(:jpegoptim,
|
61
|
+
execute(:jpegoptim, args, options) && optimized?(src, dst)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -49,7 +49,7 @@ class ImageOptim
|
|
49
49
|
-5
|
50
50
|
end
|
51
51
|
|
52
|
-
def optimize(src, dst)
|
52
|
+
def optimize(src, dst, options = {})
|
53
53
|
args = %W[
|
54
54
|
--quality #{QUALITY_NAMES[quality]}
|
55
55
|
--method #{method}
|
@@ -57,7 +57,7 @@ class ImageOptim
|
|
57
57
|
#{src}
|
58
58
|
#{dst}
|
59
59
|
]
|
60
|
-
execute(:'jpeg-recompress',
|
60
|
+
execute(:'jpeg-recompress', args, options) && optimized?(src, dst)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -23,7 +23,7 @@ class ImageOptim
|
|
23
23
|
jpegrescan ? [:jpegtran, :jpegrescan] : [:jpegtran]
|
24
24
|
end
|
25
25
|
|
26
|
-
def optimize(src, dst)
|
26
|
+
def optimize(src, dst, options = {})
|
27
27
|
if jpegrescan
|
28
28
|
args = %W[
|
29
29
|
#{src}
|
@@ -31,7 +31,7 @@ class ImageOptim
|
|
31
31
|
]
|
32
32
|
args.unshift '-s' unless copy_chunks
|
33
33
|
resolve_bin!(:jpegtran)
|
34
|
-
execute(:jpegrescan,
|
34
|
+
execute(:jpegrescan, args, options) && optimized?(src, dst)
|
35
35
|
else
|
36
36
|
args = %W[
|
37
37
|
-optimize
|
@@ -40,7 +40,7 @@ class ImageOptim
|
|
40
40
|
]
|
41
41
|
args.unshift '-copy', (copy_chunks ? 'all' : 'none')
|
42
42
|
args.unshift '-progressive' if progressive
|
43
|
-
execute(:jpegtran,
|
43
|
+
execute(:jpegtran, args, options) && optimized?(src, dst)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -30,7 +30,7 @@ class ImageOptim
|
|
30
30
|
-4
|
31
31
|
end
|
32
32
|
|
33
|
-
def optimize(src, dst)
|
33
|
+
def optimize(src, dst, options = {})
|
34
34
|
src.copy(dst)
|
35
35
|
args = %W[
|
36
36
|
-o #{level}
|
@@ -42,7 +42,7 @@ class ImageOptim
|
|
42
42
|
if strip && resolve_bin!(:optipng).version >= '0.7'
|
43
43
|
args.unshift '-strip', 'all'
|
44
44
|
end
|
45
|
-
execute(:optipng,
|
45
|
+
execute(:optipng, args, options) && optimized?(src, dst)
|
46
46
|
end
|
47
47
|
|
48
48
|
def optimized?(src, dst)
|
@@ -28,7 +28,7 @@ class ImageOptim
|
|
28
28
|
-6
|
29
29
|
end
|
30
30
|
|
31
|
-
def optimize(src, dst)
|
31
|
+
def optimize(src, dst, options = {})
|
32
32
|
flags = %w[
|
33
33
|
-reduce
|
34
34
|
-cc
|
@@ -49,7 +49,7 @@ class ImageOptim
|
|
49
49
|
#{dst}
|
50
50
|
]
|
51
51
|
|
52
|
-
execute(:pngcrush,
|
52
|
+
execute(:pngcrush, args, options) && optimized?(src, dst)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -24,7 +24,7 @@ class ImageOptim
|
|
24
24
|
2
|
25
25
|
end
|
26
26
|
|
27
|
-
def optimize(src, dst)
|
27
|
+
def optimize(src, dst, options = {})
|
28
28
|
args = %W[
|
29
29
|
-k#{copy_chunks ? 1 : 0}
|
30
30
|
-s#{strategy}
|
@@ -33,7 +33,7 @@ class ImageOptim
|
|
33
33
|
#{src}
|
34
34
|
#{dst}
|
35
35
|
]
|
36
|
-
execute(:pngout,
|
36
|
+
execute(:pngout, args, options) && optimized?(src, dst)
|
37
37
|
rescue SignalException => e
|
38
38
|
raise unless Signal.list.key(e.signo) == 'SEGV'
|
39
39
|
raise unless resolve_bin!(:pngout).version <= '20150920'
|
@@ -50,7 +50,7 @@ class ImageOptim
|
|
50
50
|
-2
|
51
51
|
end
|
52
52
|
|
53
|
-
def optimize(src, dst)
|
53
|
+
def optimize(src, dst, options = {})
|
54
54
|
args = %W[
|
55
55
|
--quality=#{quality.begin}-#{quality.end}
|
56
56
|
--speed=#{speed}
|
@@ -61,7 +61,7 @@ class ImageOptim
|
|
61
61
|
--
|
62
62
|
#{src}
|
63
63
|
]
|
64
|
-
execute(:pngquant,
|
64
|
+
execute(:pngquant, args, options) && optimized?(src, dst)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -16,7 +16,7 @@ class ImageOptim
|
|
16
16
|
Array(v).map(&:to_s)
|
17
17
|
end
|
18
18
|
|
19
|
-
def optimize(src, dst)
|
19
|
+
def optimize(src, dst, options = {})
|
20
20
|
args = %W[
|
21
21
|
--input #{src}
|
22
22
|
--output #{dst}
|
@@ -27,7 +27,7 @@ class ImageOptim
|
|
27
27
|
enable_plugins.each do |plugin_name|
|
28
28
|
args.unshift "--enable=#{plugin_name}"
|
29
29
|
end
|
30
|
-
execute(:svgo,
|
30
|
+
execute(:svgo, args, options) && optimized?(src, dst)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
data/script/worker_analysis
CHANGED
@@ -525,10 +525,10 @@ class Analyser
|
|
525
525
|
stats = Stats.new('all', by_format[format], worker_ids2names)
|
526
526
|
path = FSPath("#{DIR}/#{basenames[format]}")
|
527
527
|
model = {
|
528
|
-
:
|
529
|
-
:
|
530
|
-
:
|
531
|
-
:
|
528
|
+
stats_format: format,
|
529
|
+
stats: stats,
|
530
|
+
format_links: basenames,
|
531
|
+
template_dir: template_path.dirname.relative_path_from(path.dirname),
|
532
532
|
}
|
533
533
|
html = template.result(OpenStruct.new(model).instance_eval{ binding })
|
534
534
|
path.write(html)
|
@@ -19,7 +19,7 @@ describe ImageOptim::BinResolver do
|
|
19
19
|
allow(ENV).to receive(:[]).and_call_original
|
20
20
|
end
|
21
21
|
|
22
|
-
let(:image_optim){ double(:image_optim, :
|
22
|
+
let(:image_optim){ double(:image_optim, verbose: false, pack: false) }
|
23
23
|
let(:resolver){ BinResolver.new(image_optim) }
|
24
24
|
|
25
25
|
describe '#full_path' do
|
@@ -130,7 +130,7 @@ describe ImageOptim::BinResolver do
|
|
130
130
|
it 'resolves bin specified in ENV' do
|
131
131
|
path = 'bin/the_optimizer'
|
132
132
|
stub_env 'THE_OPTIMIZER_BIN', path
|
133
|
-
tmpdir = double(:tmpdir, :
|
133
|
+
tmpdir = double(:tmpdir, to_str: 'tmpdir')
|
134
134
|
symlink = double(:symlink)
|
135
135
|
|
136
136
|
full_path = File.expand_path(path)
|
@@ -180,9 +180,9 @@ describe ImageOptim::BinResolver do
|
|
180
180
|
stub_env 'THE_OPTIMIZER_BIN', path
|
181
181
|
expect(FSPath).not_to receive(:temp_dir)
|
182
182
|
expect(resolver).not_to receive(:at_exit)
|
183
|
-
allow(File).to receive_messages(
|
184
|
-
|
185
|
-
|
183
|
+
allow(File).to receive_messages(exist?: exist?,
|
184
|
+
file?: file?,
|
185
|
+
executable?: executable?)
|
186
186
|
end
|
187
187
|
|
188
188
|
after do
|
@@ -5,8 +5,6 @@ require 'image_optim/cache_path'
|
|
5
5
|
require 'tempfile'
|
6
6
|
|
7
7
|
describe ImageOptim::CachePath do
|
8
|
-
include CapabilityCheckHelpers
|
9
|
-
|
10
8
|
before do
|
11
9
|
stub_const('Path', ImageOptim::Path)
|
12
10
|
stub_const('CachePath', ImageOptim::CachePath)
|
@@ -32,8 +30,7 @@ describe ImageOptim::CachePath do
|
|
32
30
|
expect(src).to exist
|
33
31
|
end
|
34
32
|
|
35
|
-
it 'preserves attributes of destination file' do
|
36
|
-
skip 'full file modes are not support' unless any_file_modes_allowed?
|
33
|
+
it 'preserves attributes of destination file', skip: SkipConditions[:any_file_mode_allowed] do
|
37
34
|
mode = 0o666
|
38
35
|
|
39
36
|
dst.chmod(mode)
|
@@ -54,13 +51,12 @@ describe ImageOptim::CachePath do
|
|
54
51
|
expect(dst.mtime).to be >= time
|
55
52
|
end
|
56
53
|
|
57
|
-
it 'changes inode of destination' do
|
58
|
-
skip 'inodes are not supported' unless inodes_supported?
|
54
|
+
it 'changes inode of destination', skip: SkipConditions[:inodes_support] do
|
59
55
|
expect{ src.replace(dst) }.to change{ dst.stat.ino }
|
60
56
|
end
|
61
57
|
|
62
58
|
it 'is using temporary file with .tmp extension' do
|
63
|
-
expect(src).to receive(:copy).with(having_attributes(:
|
59
|
+
expect(src).to receive(:copy).with(having_attributes(extname: '.tmp')).at_least(:once)
|
64
60
|
|
65
61
|
src.replace(dst)
|
66
62
|
end
|
@@ -11,7 +11,7 @@ describe ImageOptim::Cache do
|
|
11
11
|
stub_const('CachePath', ImageOptim::CachePath)
|
12
12
|
end
|
13
13
|
|
14
|
-
let(:tmp_file){ double('/somewhere/tmp/foo/bar', :
|
14
|
+
let(:tmp_file){ double('/somewhere/tmp/foo/bar', rename: 0) }
|
15
15
|
|
16
16
|
let(:cache_dir) do
|
17
17
|
dir = '/somewhere/cache'
|
@@ -24,7 +24,7 @@ describe ImageOptim::Cache do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
let(:original) do
|
27
|
-
original = double('/somewhere/original', :
|
27
|
+
original = double('/somewhere/original', image_format: :ext)
|
28
28
|
allow(Digest::SHA1).to receive(:file).with(original) do
|
29
29
|
Digest::SHA1.new << 'some content!'
|
30
30
|
end
|
@@ -32,7 +32,7 @@ describe ImageOptim::Cache do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
let(:optimized) do
|
35
|
-
double('/somewhere/optimized', :
|
35
|
+
double('/somewhere/optimized', format: :ext, basename: 'optimized')
|
36
36
|
end
|
37
37
|
|
38
38
|
let(:cached) do
|
@@ -45,7 +45,7 @@ describe ImageOptim::Cache do
|
|
45
45
|
|
46
46
|
context 'when cache is disabled (default)' do
|
47
47
|
let(:image_optim) do
|
48
|
-
double(:image_optim, :
|
48
|
+
double(:image_optim, cache_dir: nil, cache_worker_digests: false, timeout: nil)
|
49
49
|
end
|
50
50
|
let(:cache){ Cache.new(image_optim, double) }
|
51
51
|
|
@@ -122,7 +122,7 @@ describe ImageOptim::Cache do
|
|
122
122
|
context 'when cache is enabled (without worker digests)' do
|
123
123
|
let(:image_optim) do
|
124
124
|
double(:image_optim,
|
125
|
-
:cache_dir
|
125
|
+
cache_dir: cache_dir, cache_worker_digests: false, timeout: nil)
|
126
126
|
end
|
127
127
|
let(:cache) do
|
128
128
|
cache = Cache.new(image_optim, {})
|
@@ -144,8 +144,8 @@ describe ImageOptim::Cache do
|
|
144
144
|
context 'when cache is enabled (with worker digests)' do
|
145
145
|
let(:image_optim) do
|
146
146
|
double(:image_optim,
|
147
|
-
:
|
148
|
-
:
|
147
|
+
cache_dir: cache_dir,
|
148
|
+
cache_worker_digests: true, timeout: nil)
|
149
149
|
end
|
150
150
|
let(:cache) do
|
151
151
|
cache = Cache.new(image_optim, {})
|
@@ -4,8 +4,6 @@ require 'spec_helper'
|
|
4
4
|
require 'image_optim/cmd'
|
5
5
|
|
6
6
|
describe ImageOptim::Cmd do
|
7
|
-
include CapabilityCheckHelpers
|
8
|
-
|
9
7
|
before do
|
10
8
|
stub_const('Cmd', ImageOptim::Cmd)
|
11
9
|
end
|
@@ -35,12 +33,67 @@ describe ImageOptim::Cmd do
|
|
35
33
|
expect($CHILD_STATUS.exitstatus).to eq(66)
|
36
34
|
end
|
37
35
|
|
38
|
-
it 'raises SignalException if process terminates after signal' do
|
39
|
-
skip 'signals are not supported' unless signals_supported?
|
36
|
+
it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
|
40
37
|
expect_int_exception do
|
41
38
|
Cmd.run('kill -s INT $$')
|
42
39
|
end
|
43
40
|
end
|
41
|
+
|
42
|
+
context 'with timeout' do
|
43
|
+
it 'returns process success status' do
|
44
|
+
expect(Cmd.run('sh -c "exit 0"', timeout: 1)).to eq(true)
|
45
|
+
|
46
|
+
expect(Cmd.run('sh -c "exit 1"', timeout: 1)).to eq(false)
|
47
|
+
|
48
|
+
expect(Cmd.run('sh -c "exit 66"', timeout: 1)).to eq(false)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
|
52
|
+
expect_int_exception do
|
53
|
+
Cmd.run('kill -s INT $$', timeout: 1)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'raises TimeoutExceeded if process does not exit until timeout' do
|
58
|
+
expect do
|
59
|
+
Cmd.run('sleep 10', timeout: 0)
|
60
|
+
end.to raise_error(ImageOptim::Errors::TimeoutExceeded)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'does not leave zombie threads' do
|
64
|
+
expect do
|
65
|
+
begin
|
66
|
+
Cmd.run('sleep 10', timeout: 0)
|
67
|
+
rescue ImageOptim::Errors::TimeoutExceeded
|
68
|
+
# noop
|
69
|
+
end
|
70
|
+
end.not_to change{ Thread.list }
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'receives TERM', skip: SkipConditions[:signals_support] do
|
74
|
+
waiter = double
|
75
|
+
allow(Process).to receive(:detach).once{ |pid| @pid = pid; waiter }
|
76
|
+
allow(waiter).to receive(:join){ sleep 0.1; nil }
|
77
|
+
|
78
|
+
expect do
|
79
|
+
Cmd.run('sleep 5', timeout: 0.1)
|
80
|
+
end.to raise_error(ImageOptim::Errors::TimeoutExceeded)
|
81
|
+
|
82
|
+
expect(Process.wait2(@pid).last.termsig).to eq(Signal.list['TERM'])
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'receives KILL if it does not react on TERM', skip: SkipConditions[:signals_support] do
|
86
|
+
waiter = double
|
87
|
+
allow(Process).to receive(:detach).once{ |pid| @pid = pid; waiter }
|
88
|
+
allow(waiter).to receive(:join){ sleep 0.1; nil }
|
89
|
+
|
90
|
+
expect do
|
91
|
+
Cmd.run('trap "" TERM; sleep 5', timeout: 0.1)
|
92
|
+
end.to raise_error(ImageOptim::Errors::TimeoutExceeded)
|
93
|
+
|
94
|
+
expect(Process.wait2(@pid).last.termsig).to eq(Signal.list['KILL'])
|
95
|
+
end
|
96
|
+
end
|
44
97
|
end
|
45
98
|
|
46
99
|
describe '.capture' do
|
@@ -62,8 +115,7 @@ describe ImageOptim::Cmd do
|
|
62
115
|
expect($CHILD_STATUS.exitstatus).to eq(66)
|
63
116
|
end
|
64
117
|
|
65
|
-
it 'raises SignalException if process terminates after signal' do
|
66
|
-
skip 'signals are not supported' unless signals_supported?
|
118
|
+
it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
|
67
119
|
expect_int_exception do
|
68
120
|
Cmd.capture('kill -s INT $$')
|
69
121
|
end
|
@@ -19,7 +19,7 @@ describe ImageOptim::Config do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'raises when there are unused options' do
|
22
|
-
config = IOConfig.new(:
|
22
|
+
config = IOConfig.new(unused: true)
|
23
23
|
expect do
|
24
24
|
config.assert_no_unused_options!
|
25
25
|
end.to raise_error(ImageOptim::ConfigurationError)
|
@@ -37,12 +37,12 @@ describe ImageOptim::Config do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'is 0 if disabled' do
|
40
|
-
config = IOConfig.new(:
|
40
|
+
config = IOConfig.new(nice: false)
|
41
41
|
expect(config.nice).to eq(0)
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'converts value to number' do
|
45
|
-
config = IOConfig.new(:
|
45
|
+
config = IOConfig.new(nice: '13')
|
46
46
|
expect(config.nice).to eq(13)
|
47
47
|
end
|
48
48
|
end
|
@@ -59,16 +59,32 @@ describe ImageOptim::Config do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
it 'is 1 if disabled' do
|
62
|
-
config = IOConfig.new(:
|
62
|
+
config = IOConfig.new(threads: false)
|
63
63
|
expect(config.threads).to eq(1)
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'converts value to number' do
|
67
|
-
config = IOConfig.new(:
|
67
|
+
config = IOConfig.new(threads: '616')
|
68
68
|
expect(config.threads).to eq(616)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
describe '#timeout' do
|
73
|
+
before do
|
74
|
+
allow(IOConfig).to receive(:read_options).and_return({})
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'is nil by default' do
|
78
|
+
config = IOConfig.new({})
|
79
|
+
expect(config.timeout).to eq(nil)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'converts value to a float' do
|
83
|
+
config = IOConfig.new(timeout: '15.1')
|
84
|
+
expect(config.timeout).to eq(15.1)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
72
88
|
describe '#cache_dir' do
|
73
89
|
before do
|
74
90
|
allow(IOConfig).to receive(:read_options).and_return({})
|
@@ -80,7 +96,7 @@ describe ImageOptim::Config do
|
|
80
96
|
end
|
81
97
|
|
82
98
|
it 'is nil if set to the empty string' do
|
83
|
-
config = IOConfig.new(:
|
99
|
+
config = IOConfig.new(cache_dir: '')
|
84
100
|
expect(config.cache_dir).to be nil
|
85
101
|
end
|
86
102
|
end
|
@@ -112,17 +128,17 @@ describe ImageOptim::Config do
|
|
112
128
|
end
|
113
129
|
|
114
130
|
it 'returns passed hash' do
|
115
|
-
config = IOConfig.new(:
|
116
|
-
expect(config.for_worker(Abc)).to eq(:
|
131
|
+
config = IOConfig.new(abc: {option: true})
|
132
|
+
expect(config.for_worker(Abc)).to eq(option: true)
|
117
133
|
end
|
118
134
|
|
119
135
|
it 'returns {:disable => true} for false' do
|
120
|
-
config = IOConfig.new(:
|
121
|
-
expect(config.for_worker(Abc)).to eq(:
|
136
|
+
config = IOConfig.new(abc: false)
|
137
|
+
expect(config.for_worker(Abc)).to eq(disable: true)
|
122
138
|
end
|
123
139
|
|
124
140
|
it 'raises on unknown option' do
|
125
|
-
config = IOConfig.new(:
|
141
|
+
config = IOConfig.new(abc: 13)
|
126
142
|
expect do
|
127
143
|
config.for_worker(Abc)
|
128
144
|
end.to raise_error(ImageOptim::ConfigurationError)
|
@@ -132,11 +148,11 @@ describe ImageOptim::Config do
|
|
132
148
|
describe '#initialize' do
|
133
149
|
it 'reads options from default locations' do
|
134
150
|
expect(IOConfig).to receive(:read_options).
|
135
|
-
with(IOConfig::GLOBAL_PATH).and_return(:
|
151
|
+
with(IOConfig::GLOBAL_PATH).and_return(a: 1, b: 2, c: 3)
|
136
152
|
expect(IOConfig).to receive(:read_options).
|
137
|
-
with(IOConfig::LOCAL_PATH).and_return(:
|
153
|
+
with(IOConfig::LOCAL_PATH).and_return(a: 10, b: 20)
|
138
154
|
|
139
|
-
config = IOConfig.new(:
|
155
|
+
config = IOConfig.new(a: 100)
|
140
156
|
expect(config.get!(:a)).to eq(100)
|
141
157
|
expect(config.get!(:b)).to eq(20)
|
142
158
|
expect(config.get!(:c)).to eq(3)
|
@@ -146,17 +162,17 @@ describe ImageOptim::Config do
|
|
146
162
|
it 'does not read options with empty config_paths' do
|
147
163
|
expect(IOConfig).not_to receive(:read_options)
|
148
164
|
|
149
|
-
config = IOConfig.new(:
|
165
|
+
config = IOConfig.new(config_paths: [])
|
150
166
|
config.assert_no_unused_options!
|
151
167
|
end
|
152
168
|
|
153
169
|
it 'reads options from specified paths' do
|
154
170
|
expect(IOConfig).to receive(:read_options).
|
155
|
-
with('/etc/image_optim.yml').and_return(:
|
171
|
+
with('/etc/image_optim.yml').and_return(a: 1, b: 2, c: 3)
|
156
172
|
expect(IOConfig).to receive(:read_options).
|
157
|
-
with('config/image_optim.yml').and_return(:
|
173
|
+
with('config/image_optim.yml').and_return(a: 10, b: 20)
|
158
174
|
|
159
|
-
config = IOConfig.new(:
|
175
|
+
config = IOConfig.new(a: 100, config_paths: %w[
|
160
176
|
/etc/image_optim.yml
|
161
177
|
config/image_optim.yml
|
162
178
|
])
|
@@ -170,7 +186,7 @@ describe ImageOptim::Config do
|
|
170
186
|
expect(IOConfig).to receive(:read_options).
|
171
187
|
with('config/image_optim.yml').and_return({})
|
172
188
|
|
173
|
-
config = IOConfig.new(:
|
189
|
+
config = IOConfig.new(config_paths: 'config/image_optim.yml')
|
174
190
|
config.assert_no_unused_options!
|
175
191
|
end
|
176
192
|
end
|
@@ -200,7 +216,7 @@ describe ImageOptim::Config do
|
|
200
216
|
|
201
217
|
it 'returns hash with deep symbolised keys from reader' do
|
202
218
|
stringified = {'config' => {'this' => true}}
|
203
|
-
symbolized = {:
|
219
|
+
symbolized = {config: {this: true}}
|
204
220
|
|
205
221
|
expect(IOConfig).not_to receive(:warn)
|
206
222
|
expect(File).to receive(:expand_path).
|