image_optim 0.29.0 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- 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).
|