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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -3
  3. data/CHANGELOG.markdown +4 -0
  4. data/README.markdown +2 -1
  5. data/Vagrantfile +1 -1
  6. data/image_optim.gemspec +1 -1
  7. data/lib/image_optim.rb +15 -3
  8. data/lib/image_optim/bin_resolver/bin.rb +7 -7
  9. data/lib/image_optim/cache.rb +6 -0
  10. data/lib/image_optim/cmd.rb +45 -6
  11. data/lib/image_optim/config.rb +9 -1
  12. data/lib/image_optim/elapsed_time.rb +26 -0
  13. data/lib/image_optim/errors.rb +9 -0
  14. data/lib/image_optim/runner/option_parser.rb +4 -0
  15. data/lib/image_optim/timer.rb +25 -0
  16. data/lib/image_optim/worker.rb +24 -12
  17. data/lib/image_optim/worker/advpng.rb +2 -2
  18. data/lib/image_optim/worker/gifsicle.rb +3 -3
  19. data/lib/image_optim/worker/jhead.rb +2 -2
  20. data/lib/image_optim/worker/jpegoptim.rb +2 -2
  21. data/lib/image_optim/worker/jpegrecompress.rb +2 -2
  22. data/lib/image_optim/worker/jpegtran.rb +3 -3
  23. data/lib/image_optim/worker/optipng.rb +2 -2
  24. data/lib/image_optim/worker/pngcrush.rb +2 -2
  25. data/lib/image_optim/worker/pngout.rb +2 -2
  26. data/lib/image_optim/worker/pngquant.rb +2 -2
  27. data/lib/image_optim/worker/svgo.rb +2 -2
  28. data/script/worker_analysis +4 -4
  29. data/spec/image_optim/bin_resolver_spec.rb +5 -5
  30. data/spec/image_optim/cache_path_spec.rb +3 -7
  31. data/spec/image_optim/cache_spec.rb +7 -7
  32. data/spec/image_optim/cmd_spec.rb +58 -6
  33. data/spec/image_optim/config_spec.rb +36 -20
  34. data/spec/image_optim/elapsed_time_spec.rb +14 -0
  35. data/spec/image_optim/hash_helpers_spec.rb +18 -18
  36. data/spec/image_optim/option_definition_spec.rb +6 -6
  37. data/spec/image_optim/path_spec.rb +4 -8
  38. data/spec/image_optim/runner/option_parser_spec.rb +4 -4
  39. data/spec/image_optim/timer_spec.rb +32 -0
  40. data/spec/image_optim/worker/jpegrecompress_spec.rb +2 -2
  41. data/spec/image_optim/worker/optipng_spec.rb +11 -11
  42. data/spec/image_optim/worker/pngquant_spec.rb +5 -5
  43. data/spec/image_optim/worker_spec.rb +17 -17
  44. data/spec/image_optim_spec.rb +46 -9
  45. data/spec/spec_helper.rb +16 -15
  46. 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, *args) && optimized?(src, dst)
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(:interlace => interlace))
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, *args) && optimized?(src, dst)
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, *args) && dst.size?
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, *args) && optimized?(src, dst)
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', *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
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, *args) && optimized?(src, dst)
30
+ execute(:svgo, args, options) && optimized?(src, dst)
31
31
  end
32
32
  end
33
33
  end
@@ -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
- :stats_format => format,
529
- :stats => stats,
530
- :format_links => basenames,
531
- :template_dir => template_path.dirname.relative_path_from(path.dirname),
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, :verbose => false, :pack => false) }
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, :to_str => '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(:exist? => exist?,
184
- :file? => file?,
185
- :executable? => executable?)
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(:extname => '.tmp')).at_least(:once)
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', :rename => 0) }
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', :image_format => :ext)
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', :format => :ext, :basename => '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, :cache_dir => nil, :cache_worker_digests => false)
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 => cache_dir, :cache_worker_digests => false)
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
- :cache_dir => cache_dir,
148
- :cache_worker_digests => true)
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(:unused => true)
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(:nice => false)
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(:nice => '13')
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(:threads => false)
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(:threads => '616')
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(:cache_dir => '')
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(:abc => {:option => true})
116
- expect(config.for_worker(Abc)).to eq(:option => true)
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(:abc => false)
121
- expect(config.for_worker(Abc)).to eq(:disable => true)
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(:abc => 13)
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(:a => 1, :b => 2, :c => 3)
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(:a => 10, :b => 20)
153
+ with(IOConfig::LOCAL_PATH).and_return(a: 10, b: 20)
138
154
 
139
- config = IOConfig.new(:a => 100)
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(:config_paths => [])
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(:a => 1, :b => 2, :c => 3)
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(:a => 10, :b => 20)
173
+ with('config/image_optim.yml').and_return(a: 10, b: 20)
158
174
 
159
- config = IOConfig.new(:a => 100, :config_paths => %w[
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(:config_paths => 'config/image_optim.yml')
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 = {:config => {:this => true}}
219
+ symbolized = {config: {this: true}}
204
220
 
205
221
  expect(IOConfig).not_to receive(:warn)
206
222
  expect(File).to receive(:expand_path).