image_optim 0.17.1 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.gitignore +1 -0
- data/.travis.yml +5 -18
- data/CHANGELOG.markdown +10 -0
- data/README.markdown +31 -1
- data/bin/image_optim +3 -137
- data/image_optim.gemspec +6 -3
- data/lib/image_optim.rb +20 -3
- data/lib/image_optim/bin_resolver.rb +28 -1
- data/lib/image_optim/bin_resolver/bin.rb +17 -7
- data/lib/image_optim/cmd.rb +49 -0
- data/lib/image_optim/config.rb +64 -4
- data/lib/image_optim/image_path.rb +5 -0
- data/lib/image_optim/option_definition.rb +5 -3
- data/lib/image_optim/runner.rb +1 -2
- data/lib/image_optim/runner/option_parser.rb +216 -0
- data/lib/image_optim/worker.rb +32 -17
- data/lib/image_optim/worker/advpng.rb +7 -1
- data/lib/image_optim/worker/gifsicle.rb +16 -3
- data/lib/image_optim/worker/jhead.rb +15 -8
- data/lib/image_optim/worker/jpegoptim.rb +6 -2
- data/lib/image_optim/worker/jpegtran.rb +10 -3
- data/lib/image_optim/worker/optipng.rb +6 -1
- data/lib/image_optim/worker/pngcrush.rb +8 -1
- data/lib/image_optim/worker/pngout.rb +8 -1
- data/lib/image_optim/worker/svgo.rb +4 -1
- data/script/worker_analysis +523 -0
- data/script/worker_analysis.haml +153 -0
- data/spec/image_optim/bin_resolver/comparable_condition_spec.rb +4 -5
- data/spec/image_optim/bin_resolver/simple_version_spec.rb +44 -21
- data/spec/image_optim/bin_resolver_spec.rb +63 -29
- data/spec/image_optim/cmd_spec.rb +66 -0
- data/spec/image_optim/config_spec.rb +38 -38
- data/spec/image_optim/handler_spec.rb +15 -12
- data/spec/image_optim/hash_helpers_spec.rb +14 -13
- data/spec/image_optim/image_path_spec.rb +22 -7
- data/spec/image_optim/runner/glob_helpers_spec.rb +6 -5
- data/spec/image_optim/runner/option_parser_spec.rb +99 -0
- data/spec/image_optim/space_spec.rb +5 -4
- data/spec/image_optim/worker_spec.rb +6 -5
- data/spec/image_optim_spec.rb +209 -237
- data/spec/spec_helper.rb +3 -0
- metadata +43 -11
@@ -1,21 +1,22 @@
|
|
1
|
-
|
2
|
-
require 'rspec'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'image_optim/config'
|
4
3
|
|
5
4
|
describe ImageOptim::Config do
|
6
|
-
|
5
|
+
before do
|
6
|
+
stub_const('IOConfig', ImageOptim::Config)
|
7
|
+
end
|
7
8
|
|
8
|
-
describe
|
9
|
+
describe :assert_no_unused_options! do
|
9
10
|
before do
|
10
11
|
allow(IOConfig).to receive(:read_options).and_return({})
|
11
12
|
end
|
12
13
|
|
13
|
-
it '
|
14
|
+
it 'does not raise when no unused options' do
|
14
15
|
config = IOConfig.new({})
|
15
16
|
config.assert_no_unused_options!
|
16
17
|
end
|
17
18
|
|
18
|
-
it '
|
19
|
+
it 'raises when there are unused options' do
|
19
20
|
config = IOConfig.new(:unused => true)
|
20
21
|
expect do
|
21
22
|
config.assert_no_unused_options!
|
@@ -23,80 +24,79 @@ describe ImageOptim::Config do
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
describe
|
27
|
+
describe :nice do
|
27
28
|
before do
|
28
29
|
allow(IOConfig).to receive(:read_options).and_return({})
|
29
30
|
end
|
30
31
|
|
31
|
-
it '
|
32
|
+
it 'is 10 by default' do
|
32
33
|
config = IOConfig.new({})
|
33
34
|
expect(config.nice).to eq(10)
|
34
35
|
end
|
35
36
|
|
36
|
-
it '
|
37
|
+
it 'is 0 if disabled' do
|
37
38
|
config = IOConfig.new(:nice => false)
|
38
39
|
expect(config.nice).to eq(0)
|
39
40
|
end
|
40
41
|
|
41
|
-
it '
|
42
|
+
it 'converts value to number' do
|
42
43
|
config = IOConfig.new(:nice => '13')
|
43
44
|
expect(config.nice).to eq(13)
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
|
-
describe
|
48
|
+
describe :threads do
|
48
49
|
before do
|
49
50
|
allow(IOConfig).to receive(:read_options).and_return({})
|
50
51
|
end
|
51
52
|
|
52
|
-
it '
|
53
|
+
it 'is processor_count by default' do
|
53
54
|
config = IOConfig.new({})
|
54
55
|
allow(config).to receive(:processor_count).and_return(13)
|
55
56
|
expect(config.threads).to eq(13)
|
56
57
|
end
|
57
58
|
|
58
|
-
it '
|
59
|
+
it 'is 1 if disabled' do
|
59
60
|
config = IOConfig.new(:threads => false)
|
60
61
|
expect(config.threads).to eq(1)
|
61
62
|
end
|
62
63
|
|
63
|
-
it '
|
64
|
+
it 'converts value to number' do
|
64
65
|
config = IOConfig.new(:threads => '616')
|
65
66
|
expect(config.threads).to eq(616)
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
69
|
-
describe
|
70
|
+
describe :for_worker do
|
70
71
|
before do
|
71
72
|
allow(IOConfig).to receive(:read_options).and_return({})
|
72
|
-
|
73
|
+
stub_const('Abc', Class.new do
|
74
|
+
def self.bin_sym
|
75
|
+
:abc
|
76
|
+
end
|
73
77
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
def image_formats
|
80
|
-
[]
|
81
|
-
end
|
78
|
+
def image_formats
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
end)
|
82
82
|
end
|
83
83
|
|
84
|
-
it '
|
84
|
+
it 'returns empty hash by default' do
|
85
85
|
config = IOConfig.new({})
|
86
86
|
expect(config.for_worker(Abc)).to eq({})
|
87
87
|
end
|
88
88
|
|
89
|
-
it '
|
89
|
+
it 'returns passed hash' do
|
90
90
|
config = IOConfig.new(:abc => {:option => true})
|
91
91
|
expect(config.for_worker(Abc)).to eq(:option => true)
|
92
92
|
end
|
93
93
|
|
94
|
-
it '
|
94
|
+
it 'returns passed false' do
|
95
95
|
config = IOConfig.new(:abc => false)
|
96
96
|
expect(config.for_worker(Abc)).to eq(false)
|
97
97
|
end
|
98
98
|
|
99
|
-
it '
|
99
|
+
it 'raises on unknown option' do
|
100
100
|
config = IOConfig.new(:abc => 13)
|
101
101
|
expect do
|
102
102
|
config.for_worker(Abc)
|
@@ -105,7 +105,7 @@ describe ImageOptim::Config do
|
|
105
105
|
end
|
106
106
|
|
107
107
|
describe 'config' do
|
108
|
-
it '
|
108
|
+
it 'reads options from default locations' do
|
109
109
|
expect(IOConfig).to receive(:read_options).
|
110
110
|
with(IOConfig::GLOBAL_PATH).and_return(:a => 1, :b => 2, :c => 3)
|
111
111
|
expect(IOConfig).to receive(:read_options).
|
@@ -118,14 +118,14 @@ describe ImageOptim::Config do
|
|
118
118
|
config.assert_no_unused_options!
|
119
119
|
end
|
120
120
|
|
121
|
-
it '
|
121
|
+
it 'does not read options with empty config_paths' do
|
122
122
|
expect(IOConfig).not_to receive(:read_options)
|
123
123
|
|
124
124
|
config = IOConfig.new(:config_paths => [])
|
125
125
|
config.assert_no_unused_options!
|
126
126
|
end
|
127
127
|
|
128
|
-
it '
|
128
|
+
it 'reads options from specified paths' do
|
129
129
|
expect(IOConfig).to receive(:read_options).
|
130
130
|
with('/etc/image_optim.yml').and_return(:a => 1, :b => 2, :c => 3)
|
131
131
|
expect(IOConfig).to receive(:read_options).
|
@@ -141,7 +141,7 @@ describe ImageOptim::Config do
|
|
141
141
|
config.assert_no_unused_options!
|
142
142
|
end
|
143
143
|
|
144
|
-
it '
|
144
|
+
it 'converts config_paths to array' do
|
145
145
|
expect(IOConfig).to receive(:read_options).
|
146
146
|
with('config/image_optim.yml').and_return({})
|
147
147
|
|
@@ -151,11 +151,11 @@ describe ImageOptim::Config do
|
|
151
151
|
end
|
152
152
|
|
153
153
|
describe 'class methods' do
|
154
|
-
describe
|
154
|
+
describe :read_options do
|
155
155
|
let(:path){ double(:path) }
|
156
156
|
let(:full_path){ double(:full_path) }
|
157
157
|
|
158
|
-
it '
|
158
|
+
it 'warns if expand path fails' do
|
159
159
|
expect(IOConfig).to receive(:warn)
|
160
160
|
expect(File).to receive(:expand_path).
|
161
161
|
with(path).and_raise(ArgumentError)
|
@@ -164,7 +164,7 @@ describe ImageOptim::Config do
|
|
164
164
|
expect(IOConfig.read_options(path)).to eq({})
|
165
165
|
end
|
166
166
|
|
167
|
-
it '
|
167
|
+
it 'returns empty hash if path is not a file' do
|
168
168
|
expect(IOConfig).not_to receive(:warn)
|
169
169
|
expect(File).to receive(:expand_path).
|
170
170
|
with(path).and_return(full_path)
|
@@ -174,7 +174,7 @@ describe ImageOptim::Config do
|
|
174
174
|
expect(IOConfig.read_options(path)).to eq({})
|
175
175
|
end
|
176
176
|
|
177
|
-
it '
|
177
|
+
it 'returns hash with deep symbolised keys from reader' do
|
178
178
|
stringified = {'config' => {'this' => true}}
|
179
179
|
symbolized = {:config => {:this => true}}
|
180
180
|
|
@@ -189,7 +189,7 @@ describe ImageOptim::Config do
|
|
189
189
|
expect(IOConfig.read_options(path)).to eq(symbolized)
|
190
190
|
end
|
191
191
|
|
192
|
-
it '
|
192
|
+
it 'warns and returns an empty hash if reader returns non hash' do
|
193
193
|
expect(IOConfig).to receive(:warn)
|
194
194
|
expect(File).to receive(:expand_path).
|
195
195
|
with(path).and_return(full_path)
|
@@ -201,7 +201,7 @@ describe ImageOptim::Config do
|
|
201
201
|
expect(IOConfig.read_options(path)).to eq({})
|
202
202
|
end
|
203
203
|
|
204
|
-
it '
|
204
|
+
it 'warns and returns an empty hash if reader raises exception' do
|
205
205
|
expect(IOConfig).to receive(:warn)
|
206
206
|
expect(File).to receive(:expand_path).
|
207
207
|
with(path).and_return(full_path)
|
@@ -1,16 +1,19 @@
|
|
1
|
-
|
2
|
-
require 'rspec'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'image_optim/handler'
|
4
3
|
|
5
4
|
describe ImageOptim::Handler do
|
6
|
-
|
5
|
+
before do
|
6
|
+
stub_const('Handler', ImageOptim::Handler)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'uses original as source for first conversion '\
|
7
10
|
'and two temp files for further conversions' do
|
8
11
|
original = double(:original)
|
9
12
|
allow(original).to receive(:temp_path) do
|
10
13
|
fail 'temp_path called unexpectedly'
|
11
14
|
end
|
12
15
|
|
13
|
-
handler =
|
16
|
+
handler = Handler.new(original)
|
14
17
|
temp_a = double(:temp_a)
|
15
18
|
temp_b = double(:temp_b)
|
16
19
|
expect(original).to receive(:temp_path).once.and_return(temp_a)
|
@@ -58,32 +61,32 @@ describe ImageOptim::Handler do
|
|
58
61
|
end
|
59
62
|
|
60
63
|
describe :open do
|
61
|
-
it '
|
64
|
+
it 'yields instance, runs cleanup and returns result' do
|
62
65
|
original = double
|
63
66
|
handler = double
|
64
67
|
result = double
|
65
68
|
|
66
|
-
expect(
|
67
|
-
|
69
|
+
expect(Handler).to receive(:new).
|
70
|
+
with(original).and_return(handler)
|
68
71
|
expect(handler).to receive(:process)
|
69
72
|
expect(handler).to receive(:cleanup)
|
70
73
|
expect(handler).to receive(:result).and_return(result)
|
71
74
|
|
72
|
-
expect(
|
75
|
+
expect(Handler.for(original) do |h|
|
73
76
|
h.process
|
74
77
|
end).to eq(result)
|
75
78
|
end
|
76
79
|
|
77
|
-
it '
|
80
|
+
it 'cleans up if exception is raised' do
|
78
81
|
original = double
|
79
82
|
handler = double
|
80
83
|
|
81
|
-
expect(
|
82
|
-
|
84
|
+
expect(Handler).to receive(:new).
|
85
|
+
with(original).and_return(handler)
|
83
86
|
expect(handler).to receive(:cleanup)
|
84
87
|
|
85
88
|
expect do
|
86
|
-
|
89
|
+
Handler.for(original) do
|
87
90
|
fail 'hello'
|
88
91
|
end
|
89
92
|
end.to raise_error 'hello'
|
@@ -1,12 +1,13 @@
|
|
1
|
-
|
2
|
-
require 'rspec'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'image_optim/hash_helpers'
|
4
3
|
|
5
4
|
describe ImageOptim::HashHelpers do
|
6
|
-
|
5
|
+
before do
|
6
|
+
stub_const('HashHelpers', ImageOptim::HashHelpers)
|
7
|
+
end
|
7
8
|
|
8
9
|
context 'stringify/simbolyze' do
|
9
|
-
|
10
|
+
symbol_keys = {
|
10
11
|
:a => 1,
|
11
12
|
:b => {
|
12
13
|
:c => [:a, 'a'],
|
@@ -14,7 +15,7 @@ describe ImageOptim::HashHelpers do
|
|
14
15
|
},
|
15
16
|
}
|
16
17
|
|
17
|
-
|
18
|
+
string_keys = {
|
18
19
|
'a' => 1,
|
19
20
|
'b' => {
|
20
21
|
'c' => [:a, 'a'],
|
@@ -22,18 +23,18 @@ describe ImageOptim::HashHelpers do
|
|
22
23
|
},
|
23
24
|
}
|
24
25
|
|
25
|
-
it '
|
26
|
-
expect(
|
27
|
-
expect(
|
26
|
+
it 'deep stringifies hash keys' do
|
27
|
+
expect(HashHelpers.deep_stringify_keys(symbol_keys)).to eq(string_keys)
|
28
|
+
expect(HashHelpers.deep_stringify_keys(string_keys)).to eq(string_keys)
|
28
29
|
end
|
29
30
|
|
30
|
-
it '
|
31
|
-
expect(
|
32
|
-
expect(
|
31
|
+
it 'deep symbolises hash keys' do
|
32
|
+
expect(HashHelpers.deep_symbolise_keys(string_keys)).to eq(symbol_keys)
|
33
|
+
expect(HashHelpers.deep_symbolise_keys(symbol_keys)).to eq(symbol_keys)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
it '
|
37
|
+
it 'deep merges hashes' do
|
37
38
|
merge_a = {
|
38
39
|
:a => {
|
39
40
|
:b => 1,
|
@@ -70,7 +71,7 @@ describe ImageOptim::HashHelpers do
|
|
70
71
|
'z' => 20,
|
71
72
|
}
|
72
73
|
|
73
|
-
expect(
|
74
|
+
expect(HashHelpers.deep_merge(merge_a, merge_b)).to eq(merge_result)
|
74
75
|
end
|
75
76
|
|
76
77
|
end
|
@@ -1,12 +1,13 @@
|
|
1
|
-
|
2
|
-
require 'rspec'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'image_optim/image_path'
|
4
3
|
|
5
4
|
describe ImageOptim::ImagePath do
|
6
|
-
|
5
|
+
before do
|
6
|
+
stub_const('ImagePath', ImageOptim::ImagePath)
|
7
|
+
end
|
7
8
|
|
8
|
-
describe
|
9
|
-
it '
|
9
|
+
describe :convert do
|
10
|
+
it 'returns ImagePath for string' do
|
10
11
|
path = 'a'
|
11
12
|
|
12
13
|
expect(ImagePath.convert(path)).to be_a(ImagePath)
|
@@ -16,7 +17,7 @@ describe ImageOptim::ImagePath do
|
|
16
17
|
expect(ImagePath.convert(path)).not_to be(path)
|
17
18
|
end
|
18
19
|
|
19
|
-
it '
|
20
|
+
it 'returns ImagePath for Pathname' do
|
20
21
|
pathname = Pathname.new('a')
|
21
22
|
|
22
23
|
expect(ImagePath.convert(pathname)).to be_a(ImagePath)
|
@@ -26,7 +27,7 @@ describe ImageOptim::ImagePath do
|
|
26
27
|
expect(ImagePath.convert(pathname)).not_to be(pathname)
|
27
28
|
end
|
28
29
|
|
29
|
-
it '
|
30
|
+
it 'returns same instance for ImagePath' do
|
30
31
|
image_path = ImagePath.new('a')
|
31
32
|
|
32
33
|
expect(ImagePath.convert(image_path)).to be_a(ImagePath)
|
@@ -36,4 +37,18 @@ describe ImageOptim::ImagePath do
|
|
36
37
|
expect(ImagePath.convert(image_path)).to be(image_path)
|
37
38
|
end
|
38
39
|
end
|
40
|
+
|
41
|
+
describe :binread do
|
42
|
+
it 'reads binary data' do
|
43
|
+
data = (0..255).to_a.pack('c*')
|
44
|
+
|
45
|
+
path = ImagePath.temp_file_path
|
46
|
+
path.write(data)
|
47
|
+
|
48
|
+
expect(path.binread).to eq(data)
|
49
|
+
if ''.respond_to?(:encoding)
|
50
|
+
expect(path.binread.encoding).to eq(Encoding.find('ASCII-8BIT'))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
39
54
|
end
|
@@ -1,9 +1,10 @@
|
|
1
|
-
|
2
|
-
require 'rspec'
|
1
|
+
require 'spec_helper'
|
3
2
|
require 'image_optim/runner/glob_helpers'
|
4
3
|
|
5
4
|
describe ImageOptim::Runner::GlobHelpers do
|
6
|
-
|
5
|
+
before do
|
6
|
+
stub_const('GlobHelpers', ImageOptim::Runner::GlobHelpers)
|
7
|
+
end
|
7
8
|
|
8
9
|
describe :expand_braces do
|
9
10
|
{
|
@@ -16,8 +17,8 @@ describe ImageOptim::Runner::GlobHelpers do
|
|
16
17
|
'{\{a,b\},\{c,d\}}' => %w[\\{a b\\} \\{c d\\}],
|
17
18
|
'test{ing,}' => %w[testing test],
|
18
19
|
}.each do |glob, expected|
|
19
|
-
it "
|
20
|
-
expect(
|
20
|
+
it "expands #{glob}" do
|
21
|
+
expect(GlobHelpers.expand_braces(glob)).to match_array(expected)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'image_optim/runner/option_parser'
|
3
|
+
|
4
|
+
describe ImageOptim::Runner::OptionParser do
|
5
|
+
before do
|
6
|
+
stub_const('OptionParser', ImageOptim::Runner::OptionParser)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe :parse! do
|
10
|
+
it 'returns empty hash for arguments without options' do
|
11
|
+
args = %w[foo bar]
|
12
|
+
expect(OptionParser.parse!(args)).to eq({})
|
13
|
+
expect(args).to eq(%w[foo bar])
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'removes options from arguments' do
|
17
|
+
args = %w[-r foo bar]
|
18
|
+
OptionParser.parse!(args)
|
19
|
+
expect(args).to eq(%w[foo bar])
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'stops parsing optiosn after --' do
|
23
|
+
args = %w[-- -r foo bar]
|
24
|
+
OptionParser.parse!(args)
|
25
|
+
expect(args).to eq(%w[-r foo bar])
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'boolean option recursive' do
|
29
|
+
%w[-r -R --recursive].each do |flag|
|
30
|
+
it "is parsed from #{flag}" do
|
31
|
+
args = %W[#{flag} foo bar]
|
32
|
+
expect(OptionParser.parse!(args)).to eq(:recursive => true)
|
33
|
+
expect(args).to eq(%w[foo bar])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'numeric option threads' do
|
39
|
+
it 'is parsed with space separator' do
|
40
|
+
args = %w[--threads 616 foo bar]
|
41
|
+
expect(OptionParser.parse!(args)).to eq(:threads => 616)
|
42
|
+
expect(args).to eq(%w[foo bar])
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'is parsed with equal separator' do
|
46
|
+
args = %w[--threads=616 foo bar]
|
47
|
+
expect(OptionParser.parse!(args)).to eq(:threads => 616)
|
48
|
+
expect(args).to eq(%w[foo bar])
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'is parsed with no- prefix' do
|
52
|
+
args = %w[--no-threads 616 foo bar]
|
53
|
+
expect(OptionParser.parse!(args)).to eq(:threads => false)
|
54
|
+
expect(args).to eq(%w[616 foo bar])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'help option' do
|
59
|
+
it 'prints help text to stdout and exits' do
|
60
|
+
parser = OptionParser.new({})
|
61
|
+
expect(OptionParser).to receive(:new).and_return(parser)
|
62
|
+
|
63
|
+
help = double
|
64
|
+
expect(parser).to receive(:help).and_return(help)
|
65
|
+
|
66
|
+
expect do
|
67
|
+
OptionParser.parse!(%w[--help])
|
68
|
+
end.to output("#{help}\n").to_stdout &
|
69
|
+
raise_error(SystemExit){ |e| expect(e.status).to eq(0) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'wrong option' do
|
74
|
+
it 'prints help text to stdout and exits' do
|
75
|
+
parser = OptionParser.new({})
|
76
|
+
expect(OptionParser).to receive(:new).and_return(parser)
|
77
|
+
|
78
|
+
help = double
|
79
|
+
expect(parser).to receive(:help).and_return(help)
|
80
|
+
|
81
|
+
expect do
|
82
|
+
OptionParser.parse!(%w[--unknown-option])
|
83
|
+
end.to output("invalid option: --unknown-option\n\n#{help}\n").
|
84
|
+
to_stderr & raise_error(SystemExit){ |e| expect(e.status).to eq(1) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe :help do
|
90
|
+
it 'returns wrapped text' do
|
91
|
+
parser = OptionParser.new({})
|
92
|
+
|
93
|
+
allow(parser).to receive(:terminal_columns).and_return(80)
|
94
|
+
|
95
|
+
expect(parser.help.split("\n")).
|
96
|
+
to all(satisfy{ |line| line.length <= 80 })
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|