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.
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
@@ -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
@@ -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)
@@ -98,8 +95,7 @@ describe ImageOptim::Path do
98
95
  expect(dst.mtime).to be >= time
99
96
  end
100
97
 
101
- it 'changes inode of destination' do
102
- skip 'inodes are not supported' unless inodes_supported?
98
+ it 'changes inode of destination', skip: SkipConditions[:inodes_support] do
103
99
  expect{ src.replace(dst) }.to change{ dst.stat.ino }
104
100
  end
105
101
  end
@@ -120,7 +116,7 @@ describe ImageOptim::Path do
120
116
  include_examples 'replaces file'
121
117
 
122
118
  it 'is using temporary file with .tmp extension' do
123
- expect(src).to receive(:move).with(having_attributes(:extname => '.tmp'))
119
+ expect(src).to receive(:move).with(having_attributes(extname: '.tmp'))
124
120
 
125
121
  src.replace(dst)
126
122
  end
@@ -135,7 +131,7 @@ describe ImageOptim::Path do
135
131
  include_examples 'replaces file'
136
132
 
137
133
  it 'is using temporary file with .tmp extension' do
138
- expect(src).to receive(:move).with(having_attributes(:extname => '.tmp'))
134
+ expect(src).to receive(:move).with(having_attributes(extname: '.tmp'))
139
135
 
140
136
  src.replace(dst)
141
137
  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
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'image_optim/timer'
5
+
6
+ describe ImageOptim::Timer do
7
+ let!(:timer){ described_class.new(1) }
8
+
9
+ describe '#elapsed' do
10
+ it 'returns elapsed time' do
11
+ sleep 0.01
12
+
13
+ expect(timer.elapsed).to be >= 0.01
14
+ end
15
+ end
16
+
17
+ describe '#left' do
18
+ it 'returns time left' do
19
+ sleep 0.01
20
+
21
+ expect(timer.left).to be <= 0.99
22
+ end
23
+ end
24
+
25
+ describe '#to_f' do
26
+ it 'returns time left' do
27
+ sleep 0.01
28
+
29
+ expect(timer.to_f).to be <= 0.99
30
+ end
31
+ end
32
+ end
@@ -14,7 +14,7 @@ describe ImageOptim::Worker::Jpegrecompress do
14
14
  end
15
15
 
16
16
  context 'uses default when invalid' do
17
- let(:method){ {:method => 'invalid'} }
17
+ let(:method){ {method: 'invalid'} }
18
18
 
19
19
  it 'warns and keeps default' do
20
20
  expect_any_instance_of(described_class).
@@ -24,7 +24,7 @@ describe ImageOptim::Worker::Jpegrecompress do
24
24
  end
25
25
 
26
26
  context 'can use a valid option' do
27
- let(:method){ {:method => 'smallfry'} }
27
+ let(:method){ {method: 'smallfry'} }
28
28
 
29
29
  it{ is_expected.to eq('smallfry') }
30
30
  end
@@ -10,7 +10,7 @@ describe ImageOptim::Worker::Optipng do
10
10
 
11
11
  let(:options){ {} }
12
12
  let(:optipng_version){ '0.7' }
13
- let(:src){ instance_double(ImageOptim::Path, :copy => nil) }
13
+ let(:src){ instance_double(ImageOptim::Path, copy: nil) }
14
14
  let(:dst){ instance_double(ImageOptim::Path) }
15
15
 
16
16
  before do
@@ -34,7 +34,7 @@ describe ImageOptim::Worker::Optipng do
34
34
  end
35
35
 
36
36
  context 'when strip is disabled' do
37
- let(:options){ {:strip => false} }
37
+ let(:options){ {strip: false} }
38
38
 
39
39
  it 'should not add -strip all to arguments' do
40
40
  expect(subject).to receive(:execute) do |_bin, *args|
@@ -61,42 +61,42 @@ describe ImageOptim::Worker::Optipng do
61
61
  describe '#optimized?' do
62
62
  let(:src){ instance_double(ImageOptim::Path, src_options) }
63
63
  let(:dst){ instance_double(ImageOptim::Path, dst_options) }
64
- let(:src_options){ {:size => 10} }
65
- let(:dst_options){ {:size? => 9} }
64
+ let(:src_options){ {size: 10} }
65
+ let(:dst_options){ {size?: 9} }
66
66
  let(:instance){ described_class.new(ImageOptim.new, instance_options) }
67
67
  let(:instance_options){ {} }
68
68
 
69
69
  subject{ instance.optimized?(src, dst) }
70
70
 
71
71
  context 'when interlace option is enabled' do
72
- let(:instance_options){ {:interlace => true} }
72
+ let(:instance_options){ {interlace: true} }
73
73
 
74
74
  context 'when dst is empty' do
75
- let(:dst_options){ {:size? => nil} }
75
+ let(:dst_options){ {size?: nil} }
76
76
  it{ is_expected.to be_falsy }
77
77
  end
78
78
 
79
79
  context 'when dst is not empty' do
80
- let(:dst_options){ {:size? => 20} }
80
+ let(:dst_options){ {size?: 20} }
81
81
  it{ is_expected.to be_truthy }
82
82
  end
83
83
  end
84
84
 
85
85
  context 'when interlace option is disabled' do
86
- let(:instance_options){ {:interlace => false} }
86
+ let(:instance_options){ {interlace: false} }
87
87
 
88
88
  context 'when dst is empty' do
89
- let(:dst_options){ {:size? => nil} }
89
+ let(:dst_options){ {size?: nil} }
90
90
  it{ is_expected.to be_falsy }
91
91
  end
92
92
 
93
93
  context 'when dst is greater than or equal to src' do
94
- let(:dst_options){ {:size? => 10} }
94
+ let(:dst_options){ {size?: 10} }
95
95
  it{ is_expected.to be_falsy }
96
96
  end
97
97
 
98
98
  context 'when dst is less than src' do
99
- let(:dst_options){ {:size? => 9} }
99
+ let(:dst_options){ {size?: 9} }
100
100
  it{ is_expected.to be_truthy }
101
101
  end
102
102
  end
@@ -22,7 +22,7 @@ describe ImageOptim::Worker::Pngquant do
22
22
  end
23
23
 
24
24
  context 'when value is passed through options' do
25
- let(:options){ {:quality => 10..90} }
25
+ let(:options){ {quality: 10..90} }
26
26
 
27
27
  it 'warns and keeps default' do
28
28
  expect_any_instance_of(described_class).
@@ -34,13 +34,13 @@ describe ImageOptim::Worker::Pngquant do
34
34
 
35
35
  context 'when lossy allowed' do
36
36
  context 'by default' do
37
- let(:options){ {:allow_lossy => true} }
37
+ let(:options){ {allow_lossy: true} }
38
38
 
39
39
  it{ is_expected.to eq(0..100) }
40
40
  end
41
41
 
42
42
  context 'when value is passed through options' do
43
- let(:options){ {:allow_lossy => true, :quality => 10..90} }
43
+ let(:options){ {allow_lossy: true, quality: 10..90} }
44
44
 
45
45
  it 'sets the value without warning' do
46
46
  expect_any_instance_of(described_class).not_to receive(:warn)
@@ -49,7 +49,7 @@ describe ImageOptim::Worker::Pngquant do
49
49
  end
50
50
 
51
51
  context 'when passed range begin is less than 0' do
52
- let(:options){ {:allow_lossy => true, :quality => -50..50} }
52
+ let(:options){ {allow_lossy: true, quality: -50..50} }
53
53
 
54
54
  it 'sets begin to 0' do
55
55
  is_expected.to eq(0..50)
@@ -57,7 +57,7 @@ describe ImageOptim::Worker::Pngquant do
57
57
  end
58
58
 
59
59
  context 'when passed range end is more than 100' do
60
- let(:options){ {:allow_lossy => true, :quality => 50..150} }
60
+ let(:options){ {allow_lossy: true, quality: 50..150} }
61
61
 
62
62
  it 'sets end to 100' do
63
63
  is_expected.to eq(50..100)
@@ -29,9 +29,9 @@ describe ImageOptim::Worker do
29
29
  option(:three, 3, 'Three')
30
30
  end
31
31
 
32
- worker = worker_class.new(ImageOptim.new, :three => '...')
32
+ worker = worker_class.new(ImageOptim.new, three: '...')
33
33
 
34
- expect(worker.options).to eq(:one => 1, :two => 2, :three => '...')
34
+ expect(worker.options).to eq(one: 1, two: 2, three: '...')
35
35
  end
36
36
  end
37
37
 
@@ -72,7 +72,7 @@ describe ImageOptim::Worker do
72
72
  option(:three, 3, 'Three')
73
73
  end)
74
74
 
75
- worker = DefOptim.new(ImageOptim.new, :three => '...')
75
+ worker = DefOptim.new(ImageOptim.new, three: '...')
76
76
 
77
77
  expect(worker.inspect).to eq('#<DefOptim @one=1, @two=2, @three="...">')
78
78
  end
@@ -104,17 +104,17 @@ describe ImageOptim::Worker do
104
104
 
105
105
  it 'create hash by format' do
106
106
  workers = [
107
- double(:image_formats => [:a]),
108
- double(:image_formats => [:a, :b]),
109
- double(:image_formats => [:b, :c]),
107
+ double(image_formats: [:a]),
108
+ double(image_formats: [:a, :b]),
109
+ double(image_formats: [:b, :c]),
110
110
  ]
111
111
 
112
112
  expect(Worker).to receive(:create_all).and_return(workers)
113
113
 
114
114
  worker_by_format = {
115
- :a => [workers[0], workers[1]],
116
- :b => [workers[1], workers[2]],
117
- :c => [workers[2]],
115
+ a: [workers[0], workers[1]],
116
+ b: [workers[1], workers[2]],
117
+ c: [workers[2]],
118
118
  }
119
119
 
120
120
  expect(Worker.create_all_by_format(double)).to eq(worker_by_format)
@@ -123,21 +123,21 @@ describe ImageOptim::Worker do
123
123
 
124
124
  describe '.create_all' do
125
125
  def worker_double(override = {})
126
- stubs = {:resolve_used_bins! => nil, :run_order => 0}.merge(override)
126
+ stubs = {resolve_used_bins!: nil, run_order: 0}.merge(override)
127
127
  instance_double(Worker, stubs)
128
128
  end
129
129
 
130
130
  def worker_class_doubles(workers)
131
- workers.map{ |worker| class_double(Worker, :init => worker) }
131
+ workers.map{ |worker| class_double(Worker, init: worker) }
132
132
  end
133
133
 
134
- let(:image_optim){ double(:allow_lossy => false) }
134
+ let(:image_optim){ double(allow_lossy: false) }
135
135
 
136
136
  it 'creates all workers for which options_proc returns true' do
137
137
  workers = Array.new(3){ worker_double }
138
138
  klasses = worker_class_doubles(workers)
139
139
  options_proc = proc do |klass|
140
- klass == klasses[1] ? {:disable => true} : {}
140
+ klass == klasses[1] ? {disable: true} : {}
141
141
  end
142
142
 
143
143
  allow(Worker).to receive(:klasses).and_return(klasses)
@@ -206,7 +206,7 @@ describe ImageOptim::Worker do
206
206
  it 'orders workers by run_order' do
207
207
  run_orders = [10, -10, 0, 0, 0, 10, -10]
208
208
  workers = run_orders.map do |run_order|
209
- worker_double(:run_order => run_order)
209
+ worker_double(run_order: run_order)
210
210
  end
211
211
  klasses_list = worker_class_doubles(workers)
212
212
 
@@ -243,16 +243,16 @@ describe ImageOptim::Worker do
243
243
  it 'allows overriding per worker' do
244
244
  klasses = worker_class_doubles([worker_double, worker_double])
245
245
  options_proc = proc do |klass|
246
- klass == klasses[1] ? {:allow_lossy => :b} : {}
246
+ klass == klasses[1] ? {allow_lossy: :b} : {}
247
247
  end
248
248
 
249
249
  allow(Worker).to receive(:klasses).and_return(klasses)
250
250
 
251
251
  klasses.each{ |klass| klass.send(:attr_reader, :allow_lossy) }
252
252
  expect(klasses[0]).to receive(:init).
253
- with(image_optim, hash_including(:allow_lossy => false))
253
+ with(image_optim, hash_including(allow_lossy: false))
254
254
  expect(klasses[1]).to receive(:init).
255
- with(image_optim, hash_including(:allow_lossy => :b))
255
+ with(image_optim, hash_including(allow_lossy: :b))
256
256
 
257
257
  Worker.create_all(image_optim, &options_proc)
258
258
  end