image_optim 0.28.0 → 0.31.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check.yml +89 -0
  3. data/.pre-commit-hooks.yaml +9 -0
  4. data/.rubocop.yml +6 -3
  5. data/CHANGELOG.markdown +20 -0
  6. data/CONTRIBUTING.markdown +1 -1
  7. data/Gemfile +1 -7
  8. data/LICENSE.txt +1 -1
  9. data/README.markdown +18 -9
  10. data/Vagrantfile +1 -1
  11. data/image_optim.gemspec +6 -3
  12. data/lib/image_optim/bin_resolver/bin.rb +9 -9
  13. data/lib/image_optim/cache.rb +6 -0
  14. data/lib/image_optim/cmd.rb +45 -6
  15. data/lib/image_optim/config.rb +11 -5
  16. data/lib/image_optim/elapsed_time.rb +26 -0
  17. data/lib/image_optim/errors.rb +9 -0
  18. data/lib/image_optim/path.rb +1 -1
  19. data/lib/image_optim/runner/option_parser.rb +21 -17
  20. data/lib/image_optim/runner.rb +1 -1
  21. data/lib/image_optim/timer.rb +25 -0
  22. data/lib/image_optim/worker/advpng.rb +7 -7
  23. data/lib/image_optim/worker/gifsicle.rb +11 -11
  24. data/lib/image_optim/worker/jhead.rb +2 -2
  25. data/lib/image_optim/worker/jpegoptim.rb +11 -11
  26. data/lib/image_optim/worker/jpegrecompress.rb +6 -6
  27. data/lib/image_optim/worker/jpegtran.rb +4 -4
  28. data/lib/image_optim/worker/optipng.rb +7 -7
  29. data/lib/image_optim/worker/oxipng.rb +53 -0
  30. data/lib/image_optim/worker/pngcrush.rb +6 -6
  31. data/lib/image_optim/worker/pngout.rb +7 -7
  32. data/lib/image_optim/worker/pngquant.rb +9 -9
  33. data/lib/image_optim/worker/svgo.rb +2 -2
  34. data/lib/image_optim/worker.rb +32 -29
  35. data/lib/image_optim.rb +16 -10
  36. data/script/update_worker_options_in_readme +1 -1
  37. data/script/worker_analysis +16 -18
  38. data/spec/image_optim/bin_resolver_spec.rb +5 -5
  39. data/spec/image_optim/cache_path_spec.rb +7 -10
  40. data/spec/image_optim/cache_spec.rb +7 -7
  41. data/spec/image_optim/cmd_spec.rb +64 -6
  42. data/spec/image_optim/config_spec.rb +36 -20
  43. data/spec/image_optim/elapsed_time_spec.rb +14 -0
  44. data/spec/image_optim/handler_spec.rb +1 -1
  45. data/spec/image_optim/hash_helpers_spec.rb +18 -18
  46. data/spec/image_optim/option_definition_spec.rb +6 -6
  47. data/spec/image_optim/path_spec.rb +8 -11
  48. data/spec/image_optim/runner/option_parser_spec.rb +4 -4
  49. data/spec/image_optim/timer_spec.rb +32 -0
  50. data/spec/image_optim/worker/jpegrecompress_spec.rb +2 -2
  51. data/spec/image_optim/worker/optipng_spec.rb +11 -11
  52. data/spec/image_optim/worker/oxipng_spec.rb +89 -0
  53. data/spec/image_optim/worker/pngquant_spec.rb +5 -5
  54. data/spec/image_optim/worker_spec.rb +17 -17
  55. data/spec/image_optim_spec.rb +47 -10
  56. data/spec/images/invisiblepixels/generate +1 -1
  57. data/spec/spec_helper.rb +24 -21
  58. metadata +35 -11
  59. data/.appveyor.yml +0 -53
  60. data/.travis.yml +0 -48
@@ -29,7 +29,7 @@ end
29
29
  def write_marked(io)
30
30
  io.puts BEGIN_MARKER
31
31
  io.puts '<!-- markdown for worker options is generated by '\
32
- "`#{Pathname($PROGRAM_NAME).cleanpath}` -->"
32
+ "`#{Pathname($PROGRAM_NAME).cleanpath}` -->"
33
33
  io.puts
34
34
 
35
35
  ImageOptim::Worker.klasses.sort_by(&:name).each do |klass|
@@ -358,20 +358,18 @@ class Analyser
358
358
  end
359
359
 
360
360
  def flatten_animation(image)
361
- run_cache[:flatten][image.digest] ||= begin
362
- if image.image_format == :gif
363
- flattened = image.temp_path
364
- Cmd.run(*%W[
365
- convert
366
- #{image.image_format}:#{image}
367
- -coalesce
368
- -append
369
- #{image.image_format}:#{flattened}
370
- ]) || fail("failed flattening of #{image}")
371
- flattened
372
- else
373
- image
374
- end
361
+ run_cache[:flatten][image.digest] ||= if image.image_format == :gif
362
+ flattened = image.temp_path
363
+ Cmd.run(*%W[
364
+ convert
365
+ #{image.image_format}:#{image}
366
+ -coalesce
367
+ -append
368
+ #{image.image_format}:#{flattened}
369
+ ]) || fail("failed flattening of #{image}")
370
+ flattened
371
+ else
372
+ image
375
373
  end
376
374
  end
377
375
 
@@ -527,10 +525,10 @@ class Analyser
527
525
  stats = Stats.new('all', by_format[format], worker_ids2names)
528
526
  path = FSPath("#{DIR}/#{basenames[format]}")
529
527
  model = {
530
- :stats_format => format,
531
- :stats => stats,
532
- :format_links => basenames,
533
- :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),
534
532
  }
535
533
  html = template.result(OpenStruct.new(model).instance_eval{ binding })
536
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)
@@ -45,22 +42,22 @@ describe ImageOptim::CachePath do
45
42
  end
46
43
 
47
44
  it 'does not preserve mtime of destination file' do
48
- time = src.mtime
45
+ time = src.mtime - 1000
46
+ dst.utime(time, time)
49
47
 
50
- dst.utime(time - 1000, time - 1000)
48
+ time = dst.mtime
51
49
 
52
50
  src.replace(dst)
53
51
 
54
- expect(dst.mtime).to be >= time
52
+ expect(dst.mtime).to_not eq(time)
55
53
  end
56
54
 
57
- it 'changes inode of destination' do
58
- skip 'inodes are not supported' unless inodes_supported?
55
+ it 'changes inode of destination', skip: SkipConditions[:inodes_support] do
59
56
  expect{ src.replace(dst) }.to change{ dst.stat.ino }
60
57
  end
61
58
 
62
59
  it 'is using temporary file with .tmp extension' do
63
- expect(src).to receive(:copy).with(having_attributes(:extname => '.tmp')).at_least(:once)
60
+ expect(src).to receive(:copy).with(having_attributes(extname: '.tmp')).at_least(:once)
64
61
 
65
62
  src.replace(dst)
66
63
  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, {})
@@ -2,10 +2,9 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'image_optim/cmd'
5
+ require 'image_optim/timer'
5
6
 
6
7
  describe ImageOptim::Cmd do
7
- include CapabilityCheckHelpers
8
-
9
8
  before do
10
9
  stub_const('Cmd', ImageOptim::Cmd)
11
10
  end
@@ -35,12 +34,72 @@ describe ImageOptim::Cmd do
35
34
  expect($CHILD_STATUS.exitstatus).to eq(66)
36
35
  end
37
36
 
38
- it 'raises SignalException if process terminates after signal' do
39
- skip 'signals are not supported' unless signals_supported?
37
+ it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
40
38
  expect_int_exception do
41
39
  Cmd.run('kill -s INT $$')
42
40
  end
43
41
  end
42
+
43
+ context 'with timeout' do
44
+ it 'returns process success status' do
45
+ expect(Cmd.run('sh -c "exit 0"', timeout: 1)).to eq(true)
46
+
47
+ expect(Cmd.run('sh -c "exit 1"', timeout: 1)).to eq(false)
48
+
49
+ expect(Cmd.run('sh -c "exit 66"', timeout: 1)).to eq(false)
50
+ end
51
+
52
+ it 'returns process success status when timeout is instance of ImageOptim::Timer' do
53
+ timeout = ImageOptim::Timer.new(1.0)
54
+ expect(Cmd.run('sh -c "exit 0"', timeout: timeout)).to eq(true)
55
+ end
56
+
57
+ it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
58
+ expect_int_exception do
59
+ Cmd.run('kill -s INT $$', timeout: 1)
60
+ end
61
+ end
62
+
63
+ it 'raises TimeoutExceeded if process does not exit until timeout' do
64
+ expect do
65
+ Cmd.run('sleep 10', timeout: 0)
66
+ end.to raise_error(ImageOptim::Errors::TimeoutExceeded)
67
+ end
68
+
69
+ it 'does not leave zombie threads' do
70
+ expect do
71
+ begin
72
+ Cmd.run('sleep 10', timeout: 0)
73
+ rescue ImageOptim::Errors::TimeoutExceeded
74
+ # noop
75
+ end
76
+ end.not_to change{ Thread.list }
77
+ end
78
+
79
+ it 'receives TERM', skip: SkipConditions[:signals_support] do
80
+ waiter = double
81
+ allow(Process).to receive(:detach).once{ |pid| @pid = pid; waiter }
82
+ allow(waiter).to receive(:join){ sleep 0.1; nil }
83
+
84
+ expect do
85
+ Cmd.run('sleep 5', timeout: 0.1)
86
+ end.to raise_error(ImageOptim::Errors::TimeoutExceeded)
87
+
88
+ expect(Process.wait2(@pid).last.termsig).to eq(Signal.list['TERM'])
89
+ end
90
+
91
+ it 'receives KILL if it does not react on TERM', skip: SkipConditions[:signals_support] do
92
+ waiter = double
93
+ allow(Process).to receive(:detach).once{ |pid| @pid = pid; waiter }
94
+ allow(waiter).to receive(:join){ sleep 0.1; nil }
95
+
96
+ expect do
97
+ Cmd.run('trap "" TERM; sleep 5', timeout: 0.1)
98
+ end.to raise_error(ImageOptim::Errors::TimeoutExceeded)
99
+
100
+ expect(Process.wait2(@pid).last.termsig).to eq(Signal.list['KILL'])
101
+ end
102
+ end
44
103
  end
45
104
 
46
105
  describe '.capture' do
@@ -62,8 +121,7 @@ describe ImageOptim::Cmd do
62
121
  expect($CHILD_STATUS.exitstatus).to eq(66)
63
122
  end
64
123
 
65
- it 'raises SignalException if process terminates after signal' do
66
- skip 'signals are not supported' unless signals_supported?
124
+ it 'raises SignalException if process terminates after signal', skip: SkipConditions[:signals_support] do
67
125
  expect_int_exception do
68
126
  Cmd.capture('kill -s INT $$')
69
127
  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).
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'image_optim/elapsed_time'
5
+
6
+ describe ImageOptim::ElapsedTime do
7
+ let(:timeout){ 0.01 }
8
+
9
+ describe '.now' do
10
+ it 'returns incrementing value' do
11
+ expect{ sleep timeout }.to change{ described_class.now }.by_at_least(timeout)
12
+ end
13
+ end
14
+ end
@@ -9,7 +9,7 @@ describe ImageOptim::Handler do
9
9
  end
10
10
 
11
11
  it 'uses original as source for first conversion '\
12
- 'and two temp files for further conversions' do
12
+ 'and two temp files for further conversions' do
13
13
  original = double(:original)
14
14
  allow(original).to receive(:respond_to?).with(:temp_path).and_return(true)
15
15
 
@@ -10,10 +10,10 @@ describe ImageOptim::HashHelpers do
10
10
 
11
11
  context 'stringify/simbolyze' do
12
12
  symbol_keys = {
13
- :a => 1,
14
- :b => {
15
- :c => [:a, 'a'],
16
- :d => {},
13
+ a: 1,
14
+ b: {
15
+ c: [:a, 'a'],
16
+ d: {},
17
17
  },
18
18
  }
19
19
 
@@ -38,22 +38,22 @@ describe ImageOptim::HashHelpers do
38
38
 
39
39
  it 'deep merges hashes' do
40
40
  merge_a = {
41
- :a => {
42
- :b => 1,
43
- :c => {
44
- :d => 2,
45
- :e => {:f => true},
41
+ a: {
42
+ b: 1,
43
+ c: {
44
+ d: 2,
45
+ e: {f: true},
46
46
  },
47
47
  },
48
- :y => 10,
48
+ y: 10,
49
49
  }
50
50
 
51
51
  merge_b = {
52
52
  :a => {
53
- :b => 2,
54
- :c => {
55
- :d => 3,
56
- :e => false,
53
+ b: 2,
54
+ c: {
55
+ d: 3,
56
+ e: false,
57
57
  },
58
58
  },
59
59
  'z' => 20,
@@ -61,10 +61,10 @@ describe ImageOptim::HashHelpers do
61
61
 
62
62
  merge_result = {
63
63
  :a => {
64
- :b => 2,
65
- :c => {
66
- :d => 3,
67
- :e => false,
64
+ b: 2,
65
+ c: {
66
+ d: 3,
67
+ e: false,
68
68
  },
69
69
  },
70
70
  :y => 10,
@@ -58,13 +58,13 @@ describe ImageOptim::OptionDefinition do
58
58
 
59
59
  context 'when option is nil' do
60
60
  it 'returns nil' do
61
- expect(subject.value(nil, :abc => nil)).to eq(nil)
61
+ expect(subject.value(nil, abc: nil)).to eq(nil)
62
62
  end
63
63
  end
64
64
 
65
65
  context 'when option is set' do
66
66
  it 'returns value' do
67
- expect(subject.value(nil, :abc => 123)).to eq(123)
67
+ expect(subject.value(nil, abc: 123)).to eq(123)
68
68
  end
69
69
  end
70
70
  end
@@ -84,13 +84,13 @@ describe ImageOptim::OptionDefinition do
84
84
 
85
85
  context 'when option is nil' do
86
86
  it 'returns nil passed through proc' do
87
- expect(subject.value(nil, :abc => nil)).to eq('nil')
87
+ expect(subject.value(nil, abc: nil)).to eq('nil')
88
88
  end
89
89
  end
90
90
 
91
91
  context 'when option is set' do
92
92
  it 'returns value passed through proc' do
93
- expect(subject.value(nil, :abc => 123)).to eq('123')
93
+ expect(subject.value(nil, abc: 123)).to eq('123')
94
94
  end
95
95
  end
96
96
  end
@@ -108,13 +108,13 @@ describe ImageOptim::OptionDefinition do
108
108
 
109
109
  context 'when option is nil' do
110
110
  it 'returns nil passed through proc' do
111
- expect(subject.value(nil, :abc => nil)).to eq(['nil', subject])
111
+ expect(subject.value(nil, abc: nil)).to eq(['nil', subject])
112
112
  end
113
113
  end
114
114
 
115
115
  context 'when option is set' do
116
116
  it 'returns value passed through proc' do
117
- expect(subject.value(nil, :abc => 123)).to eq(['123', subject])
117
+ expect(subject.value(nil, abc: 123)).to eq(['123', subject])
118
118
  end
119
119
  end
120
120
  end
@@ -5,8 +5,6 @@ require 'image_optim/path'
5
5
  require 'tempfile'
6
6
 
7
7
  describe ImageOptim::Path do
8
- include CapabilityCheckHelpers
9
-
10
8
  before do
11
9
  stub_const('Path', ImageOptim::Path)
12
10
  end
@@ -76,8 +74,7 @@ describe ImageOptim::Path do
76
74
  expect(src).to_not exist
77
75
  end
78
76
 
79
- it 'preserves attributes of destination file' do
80
- skip 'full file modes are not support' unless any_file_modes_allowed?
77
+ it 'preserves attributes of destination file', skip: SkipConditions[:any_file_mode_allowed] do
81
78
  mode = 0o666
82
79
 
83
80
  dst.chmod(mode)
@@ -89,17 +86,17 @@ describe ImageOptim::Path do
89
86
  end
90
87
 
91
88
  it 'does not preserve mtime of destination file' do
92
- time = src.mtime
89
+ time = src.mtime - 1000
90
+ dst.utime(time, time)
93
91
 
94
- dst.utime(time - 1000, time - 1000)
92
+ time = dst.mtime
95
93
 
96
94
  src.replace(dst)
97
95
 
98
- expect(dst.mtime).to be >= time
96
+ expect(dst.mtime).to_not eq(time)
99
97
  end
100
98
 
101
- it 'changes inode of destination' do
102
- skip 'inodes are not supported' unless inodes_supported?
99
+ it 'changes inode of destination', skip: SkipConditions[:inodes_support] do
103
100
  expect{ src.replace(dst) }.to change{ dst.stat.ino }
104
101
  end
105
102
  end
@@ -120,7 +117,7 @@ describe ImageOptim::Path do
120
117
  include_examples 'replaces file'
121
118
 
122
119
  it 'is using temporary file with .tmp extension' do
123
- expect(src).to receive(:move).with(having_attributes(:extname => '.tmp'))
120
+ expect(src).to receive(:move).with(having_attributes(extname: '.tmp'))
124
121
 
125
122
  src.replace(dst)
126
123
  end
@@ -135,7 +132,7 @@ describe ImageOptim::Path do
135
132
  include_examples 'replaces file'
136
133
 
137
134
  it 'is using temporary file with .tmp extension' do
138
- expect(src).to receive(:move).with(having_attributes(:extname => '.tmp'))
135
+ expect(src).to receive(:move).with(having_attributes(extname: '.tmp'))
139
136
 
140
137
  src.replace(dst)
141
138
  end
@@ -37,7 +37,7 @@ describe ImageOptim::Runner::OptionParser do
37
37
  %w[-r -R --recursive].each do |flag|
38
38
  it "is parsed from #{flag}" do
39
39
  args = %W[#{flag} foo bar]
40
- expect(OptionParser.parse!(args)).to eq(:recursive => true)
40
+ expect(OptionParser.parse!(args)).to eq(recursive: true)
41
41
  expect(args).to eq(%w[foo bar])
42
42
  end
43
43
  end
@@ -46,19 +46,19 @@ describe ImageOptim::Runner::OptionParser do
46
46
  describe 'numeric option threads' do
47
47
  it 'is parsed with space separator' do
48
48
  args = %w[--threads 616 foo bar]
49
- expect(OptionParser.parse!(args)).to eq(:threads => 616)
49
+ expect(OptionParser.parse!(args)).to eq(threads: 616)
50
50
  expect(args).to eq(%w[foo bar])
51
51
  end
52
52
 
53
53
  it 'is parsed with equal separator' do
54
54
  args = %w[--threads=616 foo bar]
55
- expect(OptionParser.parse!(args)).to eq(:threads => 616)
55
+ expect(OptionParser.parse!(args)).to eq(threads: 616)
56
56
  expect(args).to eq(%w[foo bar])
57
57
  end
58
58
 
59
59
  it 'is parsed with no- prefix' do
60
60
  args = %w[--no-threads 616 foo bar]
61
- expect(OptionParser.parse!(args)).to eq(:threads => false)
61
+ expect(OptionParser.parse!(args)).to eq(threads: false)
62
62
  expect(args).to eq(%w[616 foo bar])
63
63
  end
64
64
  end