ruby-progressbar 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +32 -3
- data/lib/ruby-progressbar/base.rb +44 -16
- data/lib/ruby-progressbar/components/bar.rb +4 -1
- data/lib/ruby-progressbar/format/base.rb +4 -2
- data/lib/ruby-progressbar/formatter.rb +3 -2
- data/lib/ruby-progressbar/version.rb +1 -1
- data/spec/lib/ruby-progressbar/base_spec.rb +290 -188
- data/spec/lib/ruby-progressbar/components/bar_spec.rb +13 -1
- metadata +7 -16
- data/.gitignore +0 -14
- data/.rspec +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -8
- data/CHANGELOG.md +0 -10
- data/Gemfile +0 -10
- data/Rakefile +0 -2
- data/ruby-progressbar.gemspec +0 -39
data/README.md
CHANGED
@@ -12,6 +12,7 @@ Supported Rubies
|
|
12
12
|
* MRI Ruby 1.8.7
|
13
13
|
* MRI Ruby 1.9.2
|
14
14
|
* MRI Ruby 1.9.3
|
15
|
+
* MRI Ruby 2.0.0
|
15
16
|
* JRuby (in 1.8 compat mode)
|
16
17
|
* JRuby (in 1.9 compat mode)
|
17
18
|
|
@@ -98,6 +99,7 @@ The following are the list of options you can use:
|
|
98
99
|
* `:total` - _(Defaults to `100`)_ The total number of the items that can be completed.
|
99
100
|
* `:starting_at` - _(Defaults to `0`)_ The number of items that should be considered completed when the bar first starts. This is also the default number that the bar will be set to if `#reset` is called.
|
100
101
|
* `:progress_mark` - _(Defaults to `=`)_ The mark which indicates the amount of progress that has been made.
|
102
|
+
* `:remainder_mark` - _(Defaults to ` `)_ The mark which indicates the remaining amount of progress to be made.
|
101
103
|
* `:format` - _(Defaults to `%t: |%B|`)_ The format string which determines how the bar is displayed. See [**Formatting**](#formatting) below.
|
102
104
|
* `:length` - _(Defaults to full width if possible, otherwise `80`)_ The preferred width of the entire progress bar including any format options.
|
103
105
|
* `:output` - _(Defaults to `STDOUT`)_ All output will be sent to this object. Can be any object which responds to `.print`.
|
@@ -267,6 +269,7 @@ _Note: If the terminal width is less than 20 characters or ruby-progressbar is b
|
|
267
269
|
The following items can be set at any time. Changes cause an immediate bar refresh so no other action is needed:
|
268
270
|
|
269
271
|
* `#progress_mark=`: Sets the string used to represent progress along the bar.
|
272
|
+
* `#remainder_mark=`: Sets the string used to represent the empty part of the bar.
|
270
273
|
* `#title=`: Sets the string used to represent the items the bar is tracking (or I guess whatever else you want it to be).
|
271
274
|
* `#format(format_string)`: If you need to adjust the format that the bar uses when rendering itself, just pass in a string in the same format as describe [above](#formatting).
|
272
275
|
|
@@ -321,9 +324,35 @@ You can have an array of as many elements as you'd like and they will be used in
|
|
321
324
|
|
322
325
|
Whatever element is chosen is repeated along the entire 'incomplete' portion of the bar.
|
323
326
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
+
### Non-TTY Output
|
328
|
+
|
329
|
+
Typically, when the progress bar is updated, the entire previous bar is 'overwritten' with the updated information. Unfortunately when the bar is being output on a non-TTY enabled output stream (such as a file or pipe), that standard behavior of outputting the progress bar will not work. This is mainly due to the fact that we can't easily go back and replace the content that the bar had previously written.
|
330
|
+
|
331
|
+
To try to solve this, ruby-progressbar, when it determines that it is being used on a non-TTY device, will override any format which was set in the initializer to something which more closely resembles this:
|
332
|
+
|
333
|
+
Progress: |=============
|
334
|
+
|
335
|
+
Notice that there are no dynamically updating segments like counters or ETA. Dynamic segments are not compatible with non-TTY devices because, by their very nature, they must be updated on each refresh of the bar and as stated previously, that is not possible in non-TTY mode.
|
336
|
+
|
337
|
+
Also notice that there is no end cap on the righthand side of the bar. Again, we cannot output something which is past the point at which we next need to output text. If we added an end cap, that would mean that any additional progress text would be placed _after_ the end cap. Definitely not what we want.
|
338
|
+
|
339
|
+
So how does it work? First we output the title and the first end cap:
|
340
|
+
|
341
|
+
Progress: |
|
342
|
+
|
343
|
+
Next, every time we increment the bar, we check whether the progress bar has grown. If it has, we output _only the additional portion_ of the bar to the output.
|
344
|
+
|
345
|
+
For example, given the previous title output, if we increment the bar once, we would get:
|
346
|
+
|
347
|
+
Progress: |=
|
348
|
+
|
349
|
+
But in this case, only one `=` was output. Not the entire `Progress: |=`.
|
350
|
+
|
351
|
+
Once the bar gets to be completely finished though:
|
352
|
+
|
353
|
+
Progress: |====================================================================|
|
354
|
+
|
355
|
+
The end cap can now be added (since there is no more progress to be displayed).
|
327
356
|
|
328
357
|
Issues
|
329
358
|
--------------------------------
|
@@ -7,6 +7,7 @@ class ProgressBar
|
|
7
7
|
|
8
8
|
def initialize(options = {})
|
9
9
|
self.output = options[:output] || DEFAULT_OUTPUT_STREAM
|
10
|
+
autostart = options.fetch(:autostart, true)
|
10
11
|
|
11
12
|
super(options)
|
12
13
|
|
@@ -15,7 +16,7 @@ class ProgressBar
|
|
15
16
|
@elapsed_time = Components::ElapsedTimer.new
|
16
17
|
@throttle = Components::Throttle.new(options)
|
17
18
|
|
18
|
-
start :at => options[:starting_at]
|
19
|
+
start :at => options[:starting_at] if autostart
|
19
20
|
end
|
20
21
|
|
21
22
|
###
|
@@ -53,19 +54,19 @@ class ProgressBar
|
|
53
54
|
# Stopping The Bar
|
54
55
|
#
|
55
56
|
def finish
|
56
|
-
with_update { with_progressables(:finish) }
|
57
|
+
with_update { with_progressables(:finish) } unless finished?
|
57
58
|
end
|
58
59
|
|
59
60
|
def pause
|
60
|
-
with_update { with_timers(:pause) }
|
61
|
+
with_update { with_timers(:pause) } unless paused?
|
61
62
|
end
|
62
63
|
|
63
64
|
def stop
|
64
|
-
with_update { with_timers(:stop) }
|
65
|
+
with_update { with_timers(:stop) } unless stopped?
|
65
66
|
end
|
66
67
|
|
67
68
|
def resume
|
68
|
-
with_update { with_timers(:resume) }
|
69
|
+
with_update { with_timers(:resume) } if stopped?
|
69
70
|
end
|
70
71
|
|
71
72
|
def reset
|
@@ -92,6 +93,10 @@ class ProgressBar
|
|
92
93
|
with_update { @bar.progress_mark = mark }
|
93
94
|
end
|
94
95
|
|
96
|
+
def remainder_mark=(mark)
|
97
|
+
with_update { @bar.remainder_mark = mark }
|
98
|
+
end
|
99
|
+
|
95
100
|
def title=(title)
|
96
101
|
with_update { super }
|
97
102
|
end
|
@@ -100,9 +105,13 @@ class ProgressBar
|
|
100
105
|
# Output
|
101
106
|
#
|
102
107
|
def clear
|
108
|
+
self.last_update_length = 0
|
109
|
+
|
103
110
|
if output.tty?
|
104
111
|
output.print clear_string
|
105
112
|
output.print "\r"
|
113
|
+
else
|
114
|
+
output.print "\n"
|
106
115
|
end
|
107
116
|
end
|
108
117
|
|
@@ -128,12 +137,17 @@ class ProgressBar
|
|
128
137
|
end
|
129
138
|
|
130
139
|
private
|
131
|
-
attr_accessor :output
|
140
|
+
attr_accessor :output,
|
141
|
+
:last_update_length
|
132
142
|
|
133
143
|
def clear_string
|
134
144
|
"#{" " * length}"
|
135
145
|
end
|
136
146
|
|
147
|
+
def last_update_length
|
148
|
+
@last_update_length ||= 0
|
149
|
+
end
|
150
|
+
|
137
151
|
def with_progressables(*args)
|
138
152
|
@bar.send(*args)
|
139
153
|
@estimated_time.send(*args)
|
@@ -150,23 +164,37 @@ class ProgressBar
|
|
150
164
|
end
|
151
165
|
|
152
166
|
def update(options = {})
|
153
|
-
if
|
154
|
-
with_timers(:stop) if finished?
|
167
|
+
with_timers(:stop) if finished?
|
155
168
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
169
|
+
if length_changed?
|
170
|
+
clear
|
171
|
+
reset_length
|
172
|
+
end
|
161
173
|
|
162
|
-
|
163
|
-
|
174
|
+
@throttle.choke( stopped? || options[:force] ) do
|
175
|
+
if output.tty?
|
176
|
+
formatted_string = self.to_s
|
177
|
+
output_string = formatted_string
|
178
|
+
else
|
179
|
+
formatted_string = self.to_s(DEFAULT_NON_TTY_FORMAT_STRING)
|
180
|
+
formatted_string = formatted_string[0...-1] unless finished?
|
181
|
+
|
182
|
+
output_string = formatted_string[last_update_length..-1]
|
164
183
|
end
|
184
|
+
|
185
|
+
self.last_update_length = formatted_string.length
|
186
|
+
|
187
|
+
output.print output_string + eol
|
188
|
+
output.flush
|
165
189
|
end
|
166
190
|
end
|
167
191
|
|
168
192
|
def eol
|
169
|
-
|
193
|
+
if output.tty?
|
194
|
+
stopped? ? "\n" : "\r"
|
195
|
+
else
|
196
|
+
stopped? ? "\n" : ""
|
197
|
+
end
|
170
198
|
end
|
171
199
|
end
|
172
200
|
end
|
@@ -4,9 +4,11 @@ class ProgressBar
|
|
4
4
|
include Progressable
|
5
5
|
|
6
6
|
DEFAULT_PROGRESS_MARK = '='
|
7
|
+
DEFAULT_REMAINDER_MARK = ' '
|
7
8
|
DEFAULT_UNKNOWN_PROGRESS_ANIMATION_STEPS = ['=---', '-=--', '--=-', '---=']
|
8
9
|
|
9
10
|
attr_accessor :progress_mark
|
11
|
+
attr_accessor :remainder_mark
|
10
12
|
attr_accessor :length
|
11
13
|
attr_accessor :unknown_progress_animation_steps
|
12
14
|
|
@@ -15,6 +17,7 @@ class ProgressBar
|
|
15
17
|
|
16
18
|
self.unknown_progress_animation_steps = options[:unknown_progress_animation_steps] || DEFAULT_UNKNOWN_PROGRESS_ANIMATION_STEPS
|
17
19
|
self.progress_mark = options[:progress_mark] || DEFAULT_PROGRESS_MARK
|
20
|
+
self.remainder_mark = options[:remainder_mark] || DEFAULT_REMAINDER_MARK
|
18
21
|
end
|
19
22
|
|
20
23
|
def to_s(options = {:format => :standard})
|
@@ -44,7 +47,7 @@ class ProgressBar
|
|
44
47
|
|
45
48
|
unknown_incomplete_string[0, incomplete_length]
|
46
49
|
else
|
47
|
-
|
50
|
+
remainder_mark * incomplete_length
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
@@ -10,6 +10,7 @@ class ProgressBar
|
|
10
10
|
|
11
11
|
def process(environment)
|
12
12
|
processed_string = @format_string.dup
|
13
|
+
ansi_sgr_codes = %r{\e\[[\d;]+m}
|
13
14
|
|
14
15
|
non_bar_molecules.each do |molecule|
|
15
16
|
processed_string.gsub!("%#{molecule.key}", environment.send(molecule.method_name).to_s)
|
@@ -20,8 +21,9 @@ class ProgressBar
|
|
20
21
|
|
21
22
|
processed_string.gsub! '%%', '%'
|
22
23
|
|
23
|
-
|
24
|
-
leftover_bar_length
|
24
|
+
processed_string_length = processed_string.gsub(ansi_sgr_codes, '').length
|
25
|
+
leftover_bar_length = environment.send(:length) - processed_string_length + placeholder_length
|
26
|
+
leftover_bar_length = leftover_bar_length < 0 ? 0 : leftover_bar_length
|
25
27
|
|
26
28
|
bar_molecules.each do |molecule|
|
27
29
|
processed_string.gsub!("%#{molecule.key}", environment.send(molecule.method_name, leftover_bar_length).to_s)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class ProgressBar
|
2
2
|
module Formatter
|
3
|
-
DEFAULT_FORMAT_STRING
|
4
|
-
|
3
|
+
DEFAULT_FORMAT_STRING = '%t: |%B|'
|
4
|
+
DEFAULT_NON_TTY_FORMAT_STRING = '%t: |%b|'
|
5
|
+
DEFAULT_TITLE = 'Progress'
|
5
6
|
|
6
7
|
def initialize(options)
|
7
8
|
self.format_string = options[:format] || DEFAULT_FORMAT_STRING
|
@@ -2,86 +2,89 @@ require 'spec_helper'
|
|
2
2
|
require 'stringio'
|
3
3
|
|
4
4
|
describe ProgressBar::Base do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@non_tty_output.stub(:tty?).and_return false
|
5
|
+
let(:output) do
|
6
|
+
StringIO.new('', 'w+').tap do |io|
|
7
|
+
io.stub(:tty?).and_return true
|
8
|
+
end
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
let(:non_tty_output) do
|
12
|
+
StringIO.new('', 'w+').tap do |io|
|
13
|
+
io.stub(:tty?).and_return false
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
17
|
+
let(:progressbar) { ProgressBar::Base.new(:output => output, :length => 80, :throttle_rate => 0.0) }
|
18
|
+
|
16
19
|
context 'when the terminal width is shorter than the string being output' do
|
17
20
|
it 'can properly handle outputting the bar when the length changes on the fly to less than the minimum width' do
|
18
21
|
IO.stub_chain(:console, :winsize).and_return [1, 30]
|
19
|
-
|
22
|
+
progressbar = ProgressBar::Base.new(:output => output, :title => 'a' * 25, :format => '%t%B', :throttle_rate => 0.0)
|
20
23
|
|
21
|
-
|
24
|
+
progressbar.start
|
22
25
|
|
23
26
|
IO.stub_chain(:console, :winsize).and_return [1, 20]
|
24
|
-
|
27
|
+
progressbar.increment
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
output.rewind
|
30
|
+
output.read.should match /\raaaaaaaaaaaaaaaaaaaaaaaaa \r\s+\raaaaaaaaaaaaaaaaaaaaaaaaa\r\z/
|
28
31
|
end
|
29
32
|
|
30
33
|
context 'and the bar length is calculated' do
|
31
34
|
it 'returns the proper string' do
|
32
35
|
IO.stub_chain(:console, :winsize).and_return [1, 20]
|
33
|
-
|
36
|
+
progressbar = ProgressBar::Base.new(:output => output, :title => ('*' * 21), :starting_at => 5, :total => 10)
|
34
37
|
|
35
|
-
|
38
|
+
progressbar.to_s('%t%w').should eql '*********************'
|
36
39
|
end
|
37
40
|
end
|
38
41
|
|
39
42
|
context 'and the incomplete bar length is calculated' do
|
40
43
|
it 'returns the proper string' do
|
41
44
|
IO.stub_chain(:console, :winsize).and_return [1, 20]
|
42
|
-
|
45
|
+
progressbar = ProgressBar::Base.new(:output => output, :title => ('*' * 21))
|
43
46
|
|
44
|
-
|
47
|
+
progressbar.to_s('%t%i').should eql '*********************'
|
45
48
|
end
|
46
49
|
|
47
50
|
it 'returns the proper string' do
|
48
51
|
IO.stub_chain(:console, :winsize).and_return [1, 20]
|
49
|
-
|
52
|
+
progressbar = ProgressBar::Base.new(:output => output, :title => ('*' * 21), :starting_at => 5, :total => 10)
|
50
53
|
|
51
|
-
|
54
|
+
progressbar.to_s('%t%i').should eql '*********************'
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
58
|
context 'and the full bar length is calculated (but lacks the space to output the entire bar)' do
|
56
59
|
it 'returns the proper string' do
|
57
60
|
IO.stub_chain(:console, :winsize).and_return [1, 20]
|
58
|
-
|
61
|
+
progressbar = ProgressBar::Base.new(:output => output, :title => ('*' * 19), :starting_at => 5, :total => 10)
|
59
62
|
|
60
|
-
|
63
|
+
progressbar.to_s('%t%B').should eql '******************* '
|
61
64
|
end
|
62
65
|
|
63
66
|
it 'returns the proper string' do
|
64
67
|
IO.stub_chain(:console, :winsize).and_return [1, 20]
|
65
|
-
|
68
|
+
progressbar = ProgressBar::Base.new(:output => output, :title => ('*' * 19), :starting_at => 5, :total => 10)
|
66
69
|
|
67
|
-
|
70
|
+
progressbar.to_s('%t%w%i').should eql '******************* '
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
75
|
context 'when a new bar is created' do
|
73
76
|
context 'and no options are passed' do
|
74
|
-
|
77
|
+
let(:progressbar) { ProgressBar::Base.new }
|
75
78
|
|
76
79
|
describe '#title' do
|
77
80
|
it 'returns the default title' do
|
78
|
-
|
81
|
+
progressbar.send(:title).to_s.should eql ProgressBar::Base::DEFAULT_TITLE
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
82
85
|
describe '#output' do
|
83
86
|
it 'returns the default output stream' do
|
84
|
-
|
87
|
+
progressbar.send(:output).should eql ProgressBar::Base::DEFAULT_OUTPUT_STREAM
|
85
88
|
end
|
86
89
|
end
|
87
90
|
|
@@ -91,8 +94,8 @@ describe ProgressBar::Base do
|
|
91
94
|
after { ENV['RUBY_PROGRESS_BAR_LENGTH'] = nil }
|
92
95
|
|
93
96
|
it 'returns the length of the environment variable as an integer' do
|
94
|
-
|
95
|
-
|
97
|
+
progressbar = ProgressBar::Base.new
|
98
|
+
progressbar.send(:length).should eql 44
|
96
99
|
end
|
97
100
|
end
|
98
101
|
|
@@ -101,22 +104,22 @@ describe ProgressBar::Base do
|
|
101
104
|
|
102
105
|
context 'but the length option was passed in' do
|
103
106
|
it 'returns the length specified in the option' do
|
104
|
-
|
105
|
-
|
107
|
+
progressbar = ProgressBar::Base.new(:length => 88)
|
108
|
+
progressbar.send(:length).should eql 88
|
106
109
|
end
|
107
110
|
end
|
108
111
|
|
109
112
|
context 'and no length option was passed in' do
|
110
113
|
it 'returns the width of the terminal if it is a Unix environment' do
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
+
progressbar.stub(:terminal_width).and_return(99)
|
115
|
+
progressbar.send(:reset_length)
|
116
|
+
progressbar.send(:length).should eql 99
|
114
117
|
end
|
115
118
|
|
116
119
|
it 'returns 80 if it is not a Unix environment' do
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
+
progressbar.stub(:unix?).and_return(false)
|
121
|
+
progressbar.send(:reset_length)
|
122
|
+
progressbar.send(:length).should eql 80
|
120
123
|
end
|
121
124
|
end
|
122
125
|
end
|
@@ -124,23 +127,23 @@ describe ProgressBar::Base do
|
|
124
127
|
end
|
125
128
|
|
126
129
|
context 'and options are passed' do
|
127
|
-
|
130
|
+
let(:progressbar) { ProgressBar::Base.new(:title => 'We All Float', :total => 12, :output => STDOUT, :progress_mark => 'x', :length => 88, :starting_at => 5) }
|
128
131
|
|
129
132
|
describe '#title' do
|
130
133
|
it 'returns the overridden title' do
|
131
|
-
|
134
|
+
progressbar.send(:title).to_s.should eql 'We All Float'
|
132
135
|
end
|
133
136
|
end
|
134
137
|
|
135
138
|
describe '#output' do
|
136
139
|
it 'returns the overridden output stream' do
|
137
|
-
|
140
|
+
progressbar.send(:output).should eql STDOUT
|
138
141
|
end
|
139
142
|
end
|
140
143
|
|
141
144
|
describe '#length' do
|
142
145
|
it 'returns the overridden length' do
|
143
|
-
|
146
|
+
progressbar.send(:length).should eql 88
|
144
147
|
end
|
145
148
|
end
|
146
149
|
end
|
@@ -148,170 +151,267 @@ describe ProgressBar::Base do
|
|
148
151
|
context 'if the bar was started 4 minutes ago' do
|
149
152
|
before do
|
150
153
|
Timecop.travel(-240) do
|
151
|
-
|
154
|
+
progressbar.start
|
152
155
|
end
|
153
156
|
end
|
154
157
|
|
155
158
|
context 'and within 2 minutes it was halfway done' do
|
156
159
|
before do
|
157
160
|
Timecop.travel(-120) do
|
158
|
-
50.times {
|
161
|
+
50.times { progressbar.increment }
|
159
162
|
end
|
160
163
|
end
|
161
164
|
|
162
165
|
describe '#finish' do
|
163
166
|
before do
|
164
167
|
Timecop.travel(-120) do
|
165
|
-
|
168
|
+
progressbar.finish
|
166
169
|
end
|
167
170
|
end
|
168
171
|
|
169
172
|
it 'completes the bar' do
|
170
|
-
|
171
|
-
|
173
|
+
output.rewind
|
174
|
+
output.read.should match /Progress: \|#{'=' * 68}\|\n/
|
172
175
|
end
|
173
176
|
|
174
177
|
it 'shows the elapsed time instead of the estimated time since the bar is completed' do
|
175
|
-
|
178
|
+
progressbar.to_s('%e').should eql 'Time: 00:02:00'
|
176
179
|
end
|
177
180
|
|
178
181
|
it 'calculates the elapsed time to 00:02:00' do
|
179
|
-
|
182
|
+
progressbar.to_s('%a').should eql 'Time: 00:02:00'
|
180
183
|
end
|
181
184
|
end
|
182
185
|
end
|
183
186
|
end
|
184
187
|
|
188
|
+
context 'which includes ANSI SGR codes in the format string' do
|
189
|
+
it 'properly calculates the length of the bar by removing the long version of the ANSI codes from the calculated length' do
|
190
|
+
@color_code = "\e[0m\e[32m\e[7m\e[1m"
|
191
|
+
@reset_code = "\e[0m"
|
192
|
+
@progress_mark = "#{@color_code} #{@reset_code}"
|
193
|
+
progressbar = ProgressBar::Base.new(:format => "#{@color_code}Processing... %b%i#{@reset_code}#{@color_code} %p%%#{@reset_code}",
|
194
|
+
:progress_mark => @progress_mark,
|
195
|
+
:output => output,
|
196
|
+
:length => 24,
|
197
|
+
:starting_at => 3,
|
198
|
+
:total => 6,
|
199
|
+
:throttle_rate => 0.0)
|
200
|
+
|
201
|
+
progressbar.increment
|
202
|
+
progressbar.increment
|
203
|
+
|
204
|
+
output.rewind
|
205
|
+
output.read.should include "#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 50%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 66%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 4}#{' ' * 2}#{@reset_code}#{@color_code} 83%#{@reset_code}\r"
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'properly calculates the length of the bar by removing the short version of the ANSI codes from the calculated length' do
|
209
|
+
@color_code = "\e[0;32;7;1m"
|
210
|
+
@reset_code = "\e[0m"
|
211
|
+
@progress_mark = "#{@color_code} #{@reset_code}"
|
212
|
+
progressbar = ProgressBar::Base.new(:format => "#{@color_code}Processing... %b%i#{@reset_code}#{@color_code} %p%%#{@reset_code}",
|
213
|
+
:progress_mark => @progress_mark,
|
214
|
+
:output => output,
|
215
|
+
:length => 24,
|
216
|
+
:starting_at => 3,
|
217
|
+
:total => 6,
|
218
|
+
:throttle_rate => 0.0)
|
219
|
+
|
220
|
+
progressbar.increment
|
221
|
+
progressbar.increment
|
222
|
+
|
223
|
+
output.rewind
|
224
|
+
output.read.should include "#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 50%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 3}#{' ' * 3}#{@reset_code}#{@color_code} 66%#{@reset_code}\r#{@color_code}Processing... #{@progress_mark * 4}#{' ' * 2}#{@reset_code}#{@color_code} 83%#{@reset_code}\r"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
185
228
|
context 'for a TTY enabled device' do
|
186
229
|
it 'can log messages' do
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
230
|
+
progressbar = ProgressBar::Base.new(:output => output, :length => 20, :starting_at => 3, :total => 6, :throttle_rate => 0.0)
|
231
|
+
progressbar.increment
|
232
|
+
progressbar.log 'We All Float'
|
233
|
+
progressbar.increment
|
191
234
|
|
192
|
-
|
193
|
-
|
235
|
+
output.rewind
|
236
|
+
output.read.should include "Progress: |==== |\rProgress: |===== |\r \rWe All Float\nProgress: |===== |\rProgress: |====== |\r"
|
194
237
|
end
|
195
238
|
end
|
196
239
|
|
197
240
|
context 'for a non-TTY enabled device' do
|
198
241
|
it 'can log messages' do
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
242
|
+
progressbar = ProgressBar::Base.new(:output => non_tty_output, :length => 20, :starting_at => 4, :total => 6, :throttle_rate => 0.0)
|
243
|
+
progressbar.increment
|
244
|
+
progressbar.log 'We All Float'
|
245
|
+
progressbar.increment
|
246
|
+
progressbar.finish
|
247
|
+
|
248
|
+
non_tty_output.rewind
|
249
|
+
non_tty_output.read.should include "We All Float\nProgress: |========|\n"
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'can output the bar properly so that it does not spam the screen' do
|
253
|
+
progressbar = ProgressBar::Base.new(:output => non_tty_output, :length => 20, :starting_at => 0, :total => 6, :throttle_rate => 0.0)
|
254
|
+
|
255
|
+
6.times { progressbar.increment }
|
256
|
+
|
257
|
+
non_tty_output.rewind
|
258
|
+
non_tty_output.read.should eql "\n\nProgress: |========|\n"
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'can output the bar properly if finished in the middle of its progress' do
|
262
|
+
progressbar = ProgressBar::Base.new(:output => non_tty_output, :length => 20, :starting_at => 0, :total => 6, :throttle_rate => 0.0)
|
263
|
+
|
264
|
+
3.times { progressbar.increment }
|
265
|
+
|
266
|
+
progressbar.finish
|
267
|
+
|
268
|
+
non_tty_output.rewind
|
269
|
+
non_tty_output.read.should eql "\n\nProgress: |========|\n"
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'can output the bar properly if stopped in the middle of its progress' do
|
273
|
+
progressbar = ProgressBar::Base.new(:output => non_tty_output, :length => 20, :starting_at => 0, :total => 6, :throttle_rate => 0.0)
|
274
|
+
|
275
|
+
3.times { progressbar.increment }
|
204
276
|
|
205
|
-
|
206
|
-
|
277
|
+
progressbar.stop
|
278
|
+
|
279
|
+
non_tty_output.rewind
|
280
|
+
non_tty_output.read.should eql "\n\nProgress: |====\n"
|
207
281
|
end
|
208
282
|
end
|
209
283
|
end
|
210
284
|
|
211
285
|
context 'when a bar is about to be completed' do
|
212
|
-
|
213
|
-
@progressbar = ProgressBar::Base.new(:starting_at => 99, :total => 100, :output => @output, :length => 80)
|
214
|
-
end
|
286
|
+
let(:progressbar) { ProgressBar::Base.new(:starting_at => 5, :total => 6, :output => output, :length => 20) }
|
215
287
|
|
216
288
|
context 'and it is incremented' do
|
217
|
-
before {
|
289
|
+
before { progressbar.increment }
|
218
290
|
|
219
291
|
it 'registers as being "finished"' do
|
220
|
-
|
292
|
+
progressbar.should be_finished
|
221
293
|
end
|
222
294
|
|
223
295
|
it 'prints a new line' do
|
224
|
-
|
225
|
-
|
296
|
+
output.rewind
|
297
|
+
output.read.end_with?("\n").should be_true
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'does not continue to print bars if finish is subsequently called' do
|
301
|
+
progressbar.finish
|
302
|
+
|
303
|
+
output.rewind
|
304
|
+
output.read.should end_with " \rProgress: |====== |\rProgress: |========|\n"
|
226
305
|
end
|
227
306
|
end
|
228
307
|
end
|
229
308
|
|
230
309
|
context 'when a bar has an unknown amount to completion' do
|
231
|
-
|
232
|
-
@progressbar = ProgressBar::Base.new(:total => nil, :output => @output, :length => 80, :unknown_progress_animation_steps => ['=--', '-=-', '--='])
|
233
|
-
end
|
310
|
+
let(:progressbar) { ProgressBar::Base.new(:total => nil, :output => output, :length => 80, :unknown_progress_animation_steps => ['=--', '-=-', '--=']) }
|
234
311
|
|
235
312
|
it 'is represented correctly' do
|
236
|
-
|
313
|
+
progressbar.to_s('%i').should eql '=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-'
|
237
314
|
end
|
238
315
|
|
239
316
|
it 'is represented after being incremented once' do
|
240
|
-
|
241
|
-
|
317
|
+
progressbar.increment
|
318
|
+
progressbar.to_s('%i').should eql '-=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--='
|
242
319
|
end
|
243
320
|
|
244
321
|
it 'is represented after being incremented twice' do
|
245
|
-
|
246
|
-
|
247
|
-
|
322
|
+
progressbar.increment
|
323
|
+
progressbar.increment
|
324
|
+
progressbar.to_s('%i').should eql '--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--'
|
248
325
|
end
|
249
326
|
|
250
327
|
it 'displays the proper ETA' do
|
251
|
-
|
328
|
+
progressbar.to_s('%i%e').should eql '=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-- ETA: ??:??:??'
|
252
329
|
end
|
253
330
|
end
|
254
331
|
|
255
332
|
context 'when a bar is started' do
|
256
|
-
|
257
|
-
@progressbar = ProgressBar::Base.new(:starting_at => 0, :total => 100, :output => @output, :length => 80, :throttle_rate => 0.0)
|
258
|
-
end
|
333
|
+
let(:progressbar) { ProgressBar::Base.new(:starting_at => 0, :total => 100, :output => output, :length => 80, :throttle_rate => 0.0) }
|
259
334
|
|
260
335
|
context 'and it is incremented any number of times' do
|
261
|
-
before { 10.times {
|
336
|
+
before { 10.times { progressbar.increment } }
|
262
337
|
|
263
338
|
describe '#progress_mark=' do
|
264
339
|
it 'changes the mark used to represent progress and updates the output' do
|
265
|
-
|
340
|
+
progressbar.progress_mark = 'x'
|
341
|
+
|
342
|
+
output.rewind
|
343
|
+
output.read.should match /\rProgress: \|xxxxxx#{' ' * 62}\|\r\z/
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
describe '#remainder_mark=' do
|
348
|
+
it 'changes the mark used to represent the remaining part of the bar and updates the output' do
|
349
|
+
progressbar.remainder_mark = 'x'
|
266
350
|
|
267
|
-
|
268
|
-
|
351
|
+
output.rewind
|
352
|
+
output.read.should match /\rProgress: \|======#{'x' * 62}\|\r\z/
|
269
353
|
end
|
270
354
|
end
|
271
355
|
|
272
356
|
describe '#title=' do
|
273
357
|
it 'changes the title used to represent the items being progressed and updates the output' do
|
274
|
-
|
358
|
+
progressbar.title = 'Items'
|
275
359
|
|
276
|
-
|
277
|
-
|
360
|
+
output.rewind
|
361
|
+
output.read.should match /\rItems: \|=======#{' ' * 64}\|\r\z/
|
278
362
|
end
|
279
363
|
end
|
280
364
|
|
281
365
|
describe '#reset' do
|
282
|
-
before {
|
366
|
+
before { progressbar.reset }
|
283
367
|
|
284
368
|
it 'resets the bar back to the starting value' do
|
285
|
-
|
286
|
-
|
369
|
+
output.rewind
|
370
|
+
output.read.should match /\rProgress: \|#{' ' * 68}\|\r\z/
|
287
371
|
end
|
288
372
|
end
|
289
373
|
|
290
374
|
describe '#stop' do
|
291
|
-
before {
|
375
|
+
before { progressbar.stop }
|
292
376
|
|
293
377
|
it 'forcibly halts the bar wherever it is and cancels it' do
|
294
|
-
|
295
|
-
|
378
|
+
output.rewind
|
379
|
+
output.read.should match /\rProgress: \|======#{' ' * 62}\|\n\z/
|
380
|
+
end
|
381
|
+
|
382
|
+
it 'does not output the bar multiple times if the bar is already stopped' do
|
383
|
+
output.rewind
|
384
|
+
progressbar.stop
|
385
|
+
output.rewind
|
386
|
+
|
387
|
+
output.read.should_not start_with "Progress: |======#{' ' * 62}|"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
describe '#resume' do
|
392
|
+
it 'does not output the bar multiple times' do
|
393
|
+
output.rewind
|
394
|
+
progressbar.resume
|
395
|
+
output.rewind
|
396
|
+
|
397
|
+
output.read.should_not start_with "Progress: |======#{' ' * 62}|"
|
296
398
|
end
|
297
399
|
end
|
298
400
|
end
|
299
401
|
end
|
300
402
|
|
301
403
|
context 'when a bar is started from 10/100' do
|
302
|
-
|
303
|
-
@progressbar = ProgressBar::Base.new(:starting_at => 10, :total => 100, :output => @output, :length => 112)
|
304
|
-
end
|
404
|
+
let(:progressbar) { ProgressBar::Base.new(:starting_at => 10, :total => 100, :output => output, :length => 112) }
|
305
405
|
|
306
406
|
context 'and it is incremented any number of times' do
|
307
|
-
before { 10.times {
|
407
|
+
before { 10.times { progressbar.increment } }
|
308
408
|
|
309
409
|
describe '#reset' do
|
310
|
-
before {
|
410
|
+
before { progressbar.reset }
|
311
411
|
|
312
412
|
it 'resets the bar back to the starting value' do
|
313
|
-
|
314
|
-
|
413
|
+
output.rewind
|
414
|
+
output.read.should match /\rProgress: \|==========#{' ' * 90}\|\r\z/
|
315
415
|
end
|
316
416
|
end
|
317
417
|
end
|
@@ -319,246 +419,248 @@ describe ProgressBar::Base do
|
|
319
419
|
|
320
420
|
describe '#clear' do
|
321
421
|
it 'clears the current terminal line and/or bar text' do
|
322
|
-
|
422
|
+
progressbar.clear
|
323
423
|
|
324
|
-
|
325
|
-
|
424
|
+
output.rewind
|
425
|
+
output.read.should match /^#{progressbar.send(:clear_string)}/
|
326
426
|
end
|
327
427
|
end
|
328
428
|
|
329
429
|
describe '#start' do
|
330
430
|
it 'clears the current terminal line' do
|
331
|
-
|
431
|
+
progressbar.start
|
332
432
|
|
333
|
-
|
334
|
-
|
433
|
+
output.rewind
|
434
|
+
output.read.should match /^#{progressbar.send(:clear_string)}/
|
335
435
|
end
|
336
436
|
|
337
437
|
it 'prints the bar for the first time' do
|
338
|
-
|
438
|
+
progressbar.start
|
339
439
|
|
340
|
-
|
341
|
-
|
440
|
+
output.rewind
|
441
|
+
output.read.should match /Progress: \| \|\r\z/
|
342
442
|
end
|
343
443
|
|
344
444
|
it 'prints correctly if passed a position to start at' do
|
345
|
-
|
445
|
+
progressbar.start(:at => 20)
|
346
446
|
|
347
|
-
|
348
|
-
|
447
|
+
output.rewind
|
448
|
+
output.read.should match /Progress: \|============= \|\r\z/
|
349
449
|
end
|
350
450
|
end
|
351
451
|
|
352
452
|
context 'when the bar has not been completed' do
|
353
|
-
|
453
|
+
let(:progressbar) { ProgressBar::Base.new(:length => 112, :starting_at => 0, :total => 50, :output => output, :throttle_rate => 0.0) }
|
354
454
|
|
355
455
|
describe '#increment' do
|
356
|
-
before {
|
456
|
+
before { progressbar.increment }
|
357
457
|
|
358
458
|
it 'displays the bar with the correct formatting' do
|
359
|
-
|
360
|
-
|
459
|
+
output.rewind
|
460
|
+
output.read.should match /Progress: \|== \|\r\z/
|
361
461
|
end
|
362
462
|
end
|
363
463
|
end
|
364
464
|
|
365
465
|
context 'when a new bar is created with a specific format' do
|
366
466
|
context '#format' do
|
367
|
-
|
467
|
+
let(:progressbar) { ProgressBar::Base.new(:format => '%B %p%%') }
|
368
468
|
|
369
469
|
context 'if called with no arguments' do
|
370
|
-
before {
|
470
|
+
before { progressbar.format }
|
371
471
|
|
372
472
|
it 'resets the format back to the default' do
|
373
|
-
|
473
|
+
progressbar.to_s.should match /^Progress: \|\s+\|\z/
|
374
474
|
end
|
375
475
|
end
|
376
476
|
|
377
477
|
context 'if called with a specific format string' do
|
378
|
-
before {
|
478
|
+
before { progressbar.format '%t' }
|
379
479
|
|
380
480
|
it 'sets it as the new format for the bar' do
|
381
|
-
|
481
|
+
progressbar.to_s.should match /^Progress\z/
|
382
482
|
end
|
383
483
|
end
|
384
484
|
end
|
385
485
|
|
386
486
|
context '#to_s' do
|
387
487
|
it 'displays the title when passed the "%t" format flag' do
|
388
|
-
|
488
|
+
progressbar.to_s('%t').should match /^Progress\z/
|
389
489
|
end
|
390
490
|
|
391
491
|
it 'displays the title when passed the "%T" format flag' do
|
392
|
-
|
492
|
+
progressbar.to_s('%T').should match /^Progress\z/
|
393
493
|
end
|
394
494
|
|
395
495
|
it 'displays the bar when passed the "%B" format flag (including empty space)' do
|
396
|
-
|
397
|
-
|
496
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
497
|
+
progressbar.to_s('%B').should match /^#{'=' * 20}#{' ' * 80}\z/
|
398
498
|
end
|
399
499
|
|
400
500
|
it 'displays the bar when passed the combined "%b%i" format flags' do
|
401
|
-
|
402
|
-
|
501
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
502
|
+
progressbar.to_s('%b%i').should match /^#{'=' * 20}#{' ' * 80}\z/
|
403
503
|
end
|
404
504
|
|
405
505
|
it 'displays the bar when passed the "%b" format flag (excluding empty space)' do
|
406
|
-
|
407
|
-
|
506
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
507
|
+
progressbar.to_s('%b').should match /^#{'=' * 20}\z/
|
408
508
|
end
|
409
509
|
|
410
510
|
it 'displays the incomplete space when passed the "%i" format flag' do
|
411
|
-
|
412
|
-
|
511
|
+
progressbar = ProgressBar::Base.new(:length => 100, :starting_at => 20)
|
512
|
+
progressbar.to_s('%i').should match /^#{' ' * 80}\z/
|
413
513
|
end
|
414
514
|
|
415
515
|
it 'displays the bar when passed the "%w" format flag' do
|
416
|
-
|
516
|
+
progressbar = ProgressBar::Base.new(:output => output, :length => 100, :starting_at => 0)
|
417
517
|
|
418
|
-
|
419
|
-
4.times {
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
5.times {
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
91.times {
|
428
|
-
|
518
|
+
progressbar.to_s('%w').should match /^\z/
|
519
|
+
4.times { progressbar.increment }
|
520
|
+
progressbar.to_s('%w').should match /^====\z/
|
521
|
+
progressbar.increment
|
522
|
+
progressbar.to_s('%w').should match /^= 5 =\z/
|
523
|
+
5.times { progressbar.increment }
|
524
|
+
progressbar.to_s('%w').should match /^=== 10 ===\z/
|
525
|
+
progressbar.decrement
|
526
|
+
progressbar.to_s('%w').should match /^=== 9 ===\z/
|
527
|
+
91.times { progressbar.increment }
|
528
|
+
progressbar.to_s('%w').should match /^#{'=' * 47} 100 #{'=' * 48}\z/
|
429
529
|
end
|
430
530
|
|
431
531
|
it 'calculates the remaining negative space properly with an integrated percentage bar of 0 percent' do
|
432
|
-
|
532
|
+
progressbar = ProgressBar::Base.new(:output => output, :length => 100, :total => 200, :starting_at => 0)
|
433
533
|
|
434
|
-
|
435
|
-
9.times {
|
436
|
-
|
437
|
-
|
438
|
-
|
534
|
+
progressbar.to_s('%w%i').should match /^\s{100}\z/
|
535
|
+
9.times { progressbar.increment }
|
536
|
+
progressbar.to_s('%w%i').should match /^====\s{96}\z/
|
537
|
+
progressbar.increment
|
538
|
+
progressbar.to_s('%w%i').should match /^= 5 =\s{95}\z/
|
439
539
|
end
|
440
540
|
|
441
541
|
it 'displays the current capacity when passed the "%c" format flag' do
|
442
|
-
|
542
|
+
progressbar = ProgressBar::Base.new(:output => output, :starting_at => 0)
|
443
543
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
544
|
+
progressbar.to_s('%c').should match /^0\z/
|
545
|
+
progressbar.increment
|
546
|
+
progressbar.to_s('%c').should match /^1\z/
|
547
|
+
progressbar.decrement
|
548
|
+
progressbar.to_s('%c').should match /^0\z/
|
449
549
|
end
|
450
550
|
|
451
551
|
it 'displays the total capacity when passed the "%C" format flag' do
|
452
|
-
|
552
|
+
progressbar = ProgressBar::Base.new(:total => 100)
|
453
553
|
|
454
|
-
|
554
|
+
progressbar.to_s('%C').should match /^100\z/
|
455
555
|
end
|
456
556
|
|
457
557
|
it 'displays the percentage complete when passed the "%p" format flag' do
|
458
|
-
|
558
|
+
progressbar = ProgressBar::Base.new(:starting_at => 33, :total => 200)
|
459
559
|
|
460
|
-
|
560
|
+
progressbar.to_s('%p').should match /^16\z/
|
461
561
|
end
|
462
562
|
|
463
563
|
it 'displays the percentage complete when passed the "%P" format flag' do
|
464
|
-
|
564
|
+
progressbar = ProgressBar::Base.new(:starting_at => 33, :total => 200)
|
465
565
|
|
466
|
-
|
566
|
+
progressbar.to_s('%P').should match /^16.50\z/
|
467
567
|
end
|
468
568
|
|
469
569
|
it 'displays only up to 2 decimal places when using the "%P" flag' do
|
470
|
-
|
570
|
+
progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
|
471
571
|
|
472
|
-
|
572
|
+
progressbar.to_s('%P').should match /^66.66\z/
|
473
573
|
end
|
474
574
|
|
475
575
|
it 'displays a literal percent sign when using the "%%" flag' do
|
476
|
-
|
576
|
+
progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
|
477
577
|
|
478
|
-
|
578
|
+
progressbar.to_s('%%').should match /^%\z/
|
479
579
|
end
|
480
580
|
|
481
581
|
it 'displays a literal percent sign when using the "%%" flag' do
|
482
|
-
|
582
|
+
progressbar = ProgressBar::Base.new(:starting_at => 66, :total => 99)
|
483
583
|
|
484
|
-
|
584
|
+
progressbar.to_s('%%').should match /^%\z/
|
485
585
|
end
|
486
586
|
|
487
587
|
# Autostarting for now. This will be applicable later.
|
488
588
|
# context "when called before #start" do
|
489
589
|
# it "displays unknown time elapsed when using the %a flag" do
|
490
|
-
#
|
590
|
+
# progressbar.to_s('%a').should match /^Time: --:--:--\z/
|
491
591
|
# end
|
492
592
|
# end
|
493
593
|
|
494
594
|
context 'when called after #start' do
|
495
595
|
before do
|
496
596
|
Timecop.travel(-3723) do
|
497
|
-
|
597
|
+
progressbar.start
|
498
598
|
end
|
499
599
|
end
|
500
600
|
|
501
601
|
context 'and the bar is reset' do
|
502
|
-
before {
|
602
|
+
before { progressbar.reset }
|
503
603
|
|
504
604
|
it 'displays "??:??:??" until finished when passed the %e flag' do
|
505
|
-
|
605
|
+
progressbar.to_s('%a').should match /^Time: --:--:--\z/
|
506
606
|
end
|
507
607
|
end
|
508
608
|
|
509
609
|
it 'displays the time elapsed when using the "%a" flag' do
|
510
|
-
|
610
|
+
progressbar.to_s('%a').should match /^Time: 01:02:03\z/
|
511
611
|
end
|
512
612
|
end
|
513
613
|
|
514
614
|
context 'when called before #start' do
|
515
615
|
it 'displays unknown time until finished when passed the "%e" flag' do
|
516
|
-
|
517
|
-
|
616
|
+
progressbar = ProgressBar::Base.new
|
617
|
+
progressbar.to_s('%e').should match /^ ETA: \?\?:\?\?:\?\?\z/
|
518
618
|
end
|
519
619
|
end
|
520
620
|
|
521
621
|
context 'when called after #start' do
|
522
|
-
|
622
|
+
let(:progressbar) do
|
523
623
|
Timecop.travel(-3723) do
|
524
|
-
|
525
|
-
|
526
|
-
|
624
|
+
progressbar = ProgressBar::Base.new(:starting_at => 0, :output => output, :smoothing => 0.0)
|
625
|
+
progressbar.start
|
626
|
+
progressbar.progress = 50
|
627
|
+
progressbar
|
527
628
|
end
|
528
629
|
end
|
529
630
|
|
530
631
|
context 'and the bar is reset' do
|
531
|
-
before {
|
632
|
+
before { progressbar.reset }
|
532
633
|
|
533
634
|
it 'displays "??:??:??" until finished when passed the "%e" flag' do
|
534
|
-
|
635
|
+
progressbar.to_s('%e').should match /^ ETA: \?\?:\?\?:\?\?\z/
|
535
636
|
end
|
536
637
|
end
|
537
638
|
|
538
639
|
it 'displays the estimated time remaining when using the "%e" flag' do
|
539
|
-
|
640
|
+
progressbar.to_s('%e').should match /^ ETA: 01:02:02\z/
|
540
641
|
end
|
541
642
|
end
|
542
643
|
|
543
644
|
context 'when it could take 100 hours or longer to finish' do
|
544
|
-
|
645
|
+
let(:progressbar) do
|
545
646
|
Timecop.travel(-120000) do
|
546
|
-
|
547
|
-
|
548
|
-
|
647
|
+
progressbar = ProgressBar::Base.new(:starting_at => 0, :total => 100, :output => output, :smoothing => 0.0)
|
648
|
+
progressbar.start
|
649
|
+
progressbar.progress = 25
|
650
|
+
progressbar
|
549
651
|
end
|
550
652
|
end
|
551
653
|
|
552
654
|
it 'displays "> 4 Days" until finished when passed the "%E" flag' do
|
553
|
-
|
655
|
+
progressbar.to_s('%E').should match /^ ETA: > 4 Days\z/
|
554
656
|
end
|
555
657
|
|
556
658
|
it 'displays "??:??:??" until finished when passed the "%e" flag' do
|
557
|
-
|
659
|
+
progressbar.to_s('%e').should match /^ ETA: \?\?:\?\?:\?\?\z/
|
558
660
|
end
|
559
661
|
|
560
662
|
it 'displays the exact estimated time until finished when passed the "%f" flag' do
|
561
|
-
|
663
|
+
progressbar.to_s('%f').should match /^ ETA: 100:00:00\z/
|
562
664
|
end
|
563
665
|
end
|
564
666
|
end
|