infopark-user_io 1.2.1 → 1.3.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.
- checksums.yaml +5 -5
- data/.rubocop.yml +142 -0
- data/.ruby-version +1 -0
- data/Gemfile +9 -0
- data/Rakefile +3 -1
- data/lib/infopark/user_io/global.rb +10 -4
- data/lib/infopark/user_io/version.rb +3 -1
- data/lib/infopark/user_io.rb +263 -254
- data/lib/infopark-user_io.rb +3 -1
- data/spec/progress_spec.rb +114 -115
- data/spec/spec_helper.rb +51 -51
- data/spec/user_io/global_spec.rb +7 -5
- data/spec/user_io_spec.rb +297 -305
- data/user_io.gemspec +10 -10
- metadata +13 -53
data/spec/user_io_spec.rb
CHANGED
@@ -1,337 +1,300 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module Infopark
|
4
|
+
RSpec.describe(UserIO) do
|
5
|
+
let(:options) { {} }
|
5
6
|
|
6
|
-
|
7
|
+
subject(:user_io) { UserIO.new(**options) }
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
before do
|
10
|
+
allow($stdout).to(receive(:puts))
|
11
|
+
# for debugging: .and_call_original
|
12
|
+
allow($stdout).to(receive(:write))
|
13
|
+
# for debugging: .and_call_original
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
describe ".global" do
|
17
|
+
subject(:global) { UserIO.global }
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
it { is_expected.to(be_nil) }
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
describe ".global=" do
|
23
|
+
subject(:assign_global) { UserIO.global = user_io }
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
}.to change {
|
28
|
-
UserIO.global
|
29
|
-
}.to(user_io)
|
25
|
+
it "assigns the global UserIO" do
|
26
|
+
expect { assign_global }.to(change { UserIO.global }.to(user_io))
|
27
|
+
end
|
30
28
|
end
|
31
|
-
end
|
32
29
|
|
33
|
-
|
34
|
-
|
30
|
+
describe "#acknowledge" do
|
31
|
+
before { allow($stdin).to(receive(:gets).and_return("\n")) }
|
35
32
|
|
36
|
-
|
33
|
+
let(:message) { "Some important statement." }
|
37
34
|
|
38
|
-
|
35
|
+
subject(:acknowledge) { user_io.acknowledge(message) }
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
it "presents the message (colorized)" do
|
38
|
+
expect($stdout).to(receive(:write).with("\e[1;36mSome important statement.\e[22;39m\n"))
|
39
|
+
acknowledge
|
40
|
+
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
it "asks for pressing “Enter”" do
|
43
|
+
expect($stdout).to(receive(:write).with("Please press ENTER to continue.\n"))
|
44
|
+
acknowledge
|
45
|
+
end
|
49
46
|
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
it "requests input" do
|
48
|
+
expect($stdin).to(receive(:gets).and_return("\n"))
|
49
|
+
acknowledge
|
50
|
+
end
|
53
51
|
end
|
54
|
-
end
|
55
52
|
|
56
|
-
|
57
|
-
|
53
|
+
describe "#ask" do
|
54
|
+
before { allow($stdin).to(receive(:gets).and_return("yes\n")) }
|
58
55
|
|
59
|
-
|
60
|
-
|
56
|
+
let(:ask_options) { {} }
|
57
|
+
let(:question) { "do you want to?" }
|
61
58
|
|
62
|
-
|
59
|
+
subject(:ask) { user_io.ask(*Array(question), **ask_options) }
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
61
|
+
shared_examples_for "any question" do
|
62
|
+
# TODO
|
63
|
+
# it_behaves_like "handling valid answer"
|
64
|
+
# it_behaves_like "handling invalid input"
|
65
|
+
# it_behaves_like "printing prefix on every line"
|
66
|
+
end
|
70
67
|
|
71
|
-
|
72
|
-
|
68
|
+
context "with default" do
|
69
|
+
let(:ask_options) { {default: default_value} }
|
73
70
|
|
74
|
-
|
75
|
-
|
71
|
+
context "“true”" do
|
72
|
+
let(:default_value) { true }
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
it "presents default answer “yes”" do
|
75
|
+
expect($stdout).to(receive(:write).with("(yes/no) [yes] > "))
|
76
|
+
ask
|
77
|
+
end
|
81
78
|
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
it "returns “true” on empty input" do
|
80
|
+
expect($stdin).to(receive(:gets).and_return("\n"))
|
81
|
+
expect(ask).to(be(true))
|
82
|
+
end
|
83
|
+
|
84
|
+
it_behaves_like "any question"
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
87
|
+
context "“false”" do
|
88
|
+
let(:default_value) { false }
|
89
|
+
|
90
|
+
it "presents default answer “no”" do
|
91
|
+
expect($stdout).to(receive(:write).with("(yes/no) [no] > "))
|
92
|
+
ask
|
93
|
+
end
|
89
94
|
|
90
|
-
|
91
|
-
|
95
|
+
it "returns “false” on empty input" do
|
96
|
+
expect($stdin).to(receive(:gets).and_return("\n"))
|
97
|
+
expect(ask).to(be(false))
|
98
|
+
end
|
92
99
|
|
93
|
-
|
94
|
-
expect($stdout).to receive(:write).with("(yes/no) [no] > ")
|
95
|
-
ask
|
100
|
+
it_behaves_like "any question"
|
96
101
|
end
|
97
102
|
|
98
|
-
|
99
|
-
|
100
|
-
expect(ask).to be false
|
103
|
+
context "non boolean" do
|
104
|
+
# TODO
|
101
105
|
end
|
102
|
-
|
103
|
-
it_behaves_like "any question"
|
104
106
|
end
|
105
107
|
|
106
|
-
context "
|
107
|
-
|
108
|
-
end
|
109
|
-
end
|
108
|
+
context "with “expected”" do
|
109
|
+
let(:ask_options) { {expected: expected_value} }
|
110
110
|
|
111
|
-
|
112
|
-
|
111
|
+
context "“yes”" do
|
112
|
+
let(:expected_value) { "yes" }
|
113
113
|
|
114
|
-
|
115
|
-
let(:expected_value) { "yes" }
|
114
|
+
it_behaves_like "any question"
|
116
115
|
|
117
|
-
|
116
|
+
it "returns “true” when answering “yes”" do
|
117
|
+
expect($stdin).to(receive(:gets).and_return("yes\n"))
|
118
|
+
expect(ask).to(be(true))
|
119
|
+
end
|
118
120
|
|
119
|
-
|
120
|
-
|
121
|
-
|
121
|
+
it "returns “false” when answering “no”" do
|
122
|
+
expect($stdin).to(receive(:gets).and_return("no\n"))
|
123
|
+
expect(ask).to(be(false))
|
124
|
+
end
|
122
125
|
end
|
123
126
|
|
124
|
-
|
125
|
-
|
126
|
-
expect(ask).to be false
|
127
|
-
end
|
128
|
-
end
|
127
|
+
context "“no”" do
|
128
|
+
let(:expected_value) { "no" }
|
129
129
|
|
130
|
-
|
131
|
-
let(:expected_value) { "no" }
|
130
|
+
it_behaves_like "any question"
|
132
131
|
|
133
|
-
|
132
|
+
it "returns “true” when answering “no”" do
|
133
|
+
expect($stdin).to(receive(:gets).and_return("no\n"))
|
134
|
+
expect(ask).to(be(true))
|
135
|
+
end
|
134
136
|
|
135
|
-
|
136
|
-
|
137
|
-
|
137
|
+
it "returns “false” when answering “yes”" do
|
138
|
+
expect($stdin).to(receive(:gets).and_return("yes\n"))
|
139
|
+
expect(ask).to(be(false))
|
140
|
+
end
|
138
141
|
end
|
139
142
|
|
140
|
-
|
141
|
-
|
142
|
-
expect(ask).to be false
|
143
|
+
context "other" do
|
144
|
+
# TODO
|
143
145
|
end
|
144
146
|
end
|
145
|
-
|
146
|
-
context "other" do
|
147
|
-
# TODO
|
148
|
-
end
|
149
147
|
end
|
150
|
-
end
|
151
148
|
|
152
|
-
|
153
|
-
|
149
|
+
describe "#select" do
|
150
|
+
before { allow($stdin).to(receive(:gets).and_return("1\n")) }
|
154
151
|
|
155
|
-
|
156
|
-
|
157
|
-
|
152
|
+
let(:description) { "a thing" }
|
153
|
+
let(:items) { %i[a b c] }
|
154
|
+
let(:select_options) { {} }
|
158
155
|
|
159
|
-
|
156
|
+
subject(:select) { user_io.select(description, items, **select_options) }
|
160
157
|
|
161
|
-
|
162
|
-
|
158
|
+
context "with default" do
|
159
|
+
let(:select_options) { {default: :b} }
|
163
160
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
161
|
+
it "presents the default's index as default answer" do
|
162
|
+
expect($stdout).to(receive(:write).with("Your choice [2] > "))
|
163
|
+
select
|
164
|
+
end
|
168
165
|
|
169
|
-
|
170
|
-
|
171
|
-
|
166
|
+
it "returns the default on empty input" do
|
167
|
+
expect($stdin).to(receive(:gets).and_return("\n"))
|
168
|
+
expect(select).to(eq(:b))
|
169
|
+
end
|
172
170
|
end
|
173
171
|
end
|
174
|
-
end
|
175
172
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
subject(:tell_error) { user_io.tell_error(error, **tell_options) }
|
181
|
-
|
182
|
-
it "tells the given thing in bright red" do
|
183
|
-
expect(user_io).to receive(:tell).with(error, color: :red, bright: true)
|
184
|
-
tell_error
|
185
|
-
end
|
173
|
+
describe "#tell_error" do
|
174
|
+
let(:error) { {my: :error} }
|
175
|
+
let(:tell_options) { {} }
|
186
176
|
|
187
|
-
|
188
|
-
let(:tell_options) { {newline: false} }
|
177
|
+
subject(:tell_error) { user_io.tell_error(error, **tell_options) }
|
189
178
|
|
190
|
-
it "
|
191
|
-
expect(user_io).to
|
179
|
+
it "tells the given thing in bright red" do
|
180
|
+
expect(user_io).to(receive(:tell).with(error, color: :red, bright: true))
|
192
181
|
tell_error
|
193
182
|
end
|
194
|
-
end
|
195
|
-
|
196
|
-
context "when error is a kind of an exception" do
|
197
|
-
let(:error) { UserIO::Aborted.new }
|
198
183
|
|
199
|
-
|
184
|
+
context "with options" do
|
185
|
+
let(:tell_options) { {newline: false} }
|
200
186
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
187
|
+
it "delegates them to #tell" do
|
188
|
+
expect(user_io).to(receive(:tell).with(error, newline: false, color: :red, bright: true))
|
189
|
+
tell_error
|
190
|
+
end
|
205
191
|
end
|
206
|
-
end
|
207
|
-
end
|
208
192
|
|
209
|
-
|
210
|
-
|
211
|
-
let(:stream) { instance_double(IO) }
|
212
|
-
let(:data) { "test data" }
|
193
|
+
context "when error is a kind of an exception" do
|
194
|
+
let(:error) { UserIO::Aborted.new }
|
213
195
|
|
214
|
-
|
196
|
+
before { allow(error).to(receive(:backtrace).and_return(%w(a b c))) }
|
215
197
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
198
|
+
it "tells the error and the whole backtrace" do
|
199
|
+
expect(user_io).to(receive(:tell).with(error, color: :red, bright: true))
|
200
|
+
expect(user_io).to(receive(:tell).with(%w(a b c), color: :red))
|
201
|
+
tell_error
|
202
|
+
end
|
203
|
+
end
|
222
204
|
end
|
223
205
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
expect($stdout).to receive(:write).with("first\nchunk")
|
229
|
-
expect($stdout).to receive(:write).with("second chunk")
|
230
|
-
expect($stdout).to receive(:write).with("\nlast chunk")
|
231
|
-
tell
|
232
|
-
end
|
206
|
+
describe "#tell_pty_stream" do
|
207
|
+
let(:color_options) { {} }
|
208
|
+
let(:stream) { instance_double(IO) }
|
209
|
+
let(:data) { "test data" }
|
233
210
|
|
234
|
-
|
235
|
-
let(:color_options) { {color: :yellow} }
|
211
|
+
subject(:tell) { user_io.tell_pty_stream(stream, **color_options) }
|
236
212
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
213
|
+
before do
|
214
|
+
chunks = Array(data)
|
215
|
+
allow(stream).to(receive(:eof?).and_return(*[false] * chunks.size, true))
|
216
|
+
allow(stream).to(receive(:read_nonblock).and_return(*chunks))
|
217
|
+
RSpec::Mocks.space.proxy_for($stdout).reset
|
218
|
+
allow($stdout).to(receive(:write).with(nil))
|
242
219
|
end
|
243
|
-
end
|
244
220
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
expect($stdout).to
|
250
|
-
expect($stdout).to
|
221
|
+
it "tells all data from stream in non blocking chunks" do
|
222
|
+
expect(stream).to(receive(:eof?).and_return(false, false, false, true))
|
223
|
+
expect(stream).to(receive(:read_nonblock).with(100)
|
224
|
+
.and_return("first\nchunk", "second chunk", "\nlast chunk"))
|
225
|
+
expect($stdout).to(receive(:write).with("first\nchunk"))
|
226
|
+
expect($stdout).to(receive(:write).with("second chunk"))
|
227
|
+
expect($stdout).to(receive(:write).with("\nlast chunk"))
|
251
228
|
tell
|
252
229
|
end
|
253
230
|
|
254
231
|
context "with color" do
|
255
232
|
let(:color_options) { {color: :yellow} }
|
256
233
|
|
257
|
-
it "
|
258
|
-
expect($stdout).to
|
259
|
-
expect($stdout).to
|
260
|
-
expect($stdout).to
|
261
|
-
expect($stdout).to receive(:write).with("\e[22;39m").ordered
|
234
|
+
it "colorizes the output" do
|
235
|
+
expect($stdout).to(receive(:write).with("\e[33m").ordered)
|
236
|
+
expect($stdout).to(receive(:write).with("test data").ordered)
|
237
|
+
expect($stdout).to(receive(:write).with("\e[22;39m").ordered)
|
262
238
|
tell
|
263
239
|
end
|
264
240
|
end
|
265
241
|
|
266
|
-
context "
|
267
|
-
let(:
|
242
|
+
context "with output_prefix" do
|
243
|
+
let(:options) { {output_prefix: "the prefix"} }
|
268
244
|
|
269
|
-
it "
|
270
|
-
expect($stdout).to
|
271
|
-
expect($stdout).to
|
272
|
-
with("some\r[the prefix] data\r[the prefix] with\r[the prefix] CRs").ordered
|
245
|
+
it "prefixes the output" do
|
246
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
247
|
+
expect($stdout).to(receive(:write).with("test data").ordered)
|
273
248
|
tell
|
274
249
|
end
|
275
250
|
|
276
251
|
context "with color" do
|
277
252
|
let(:color_options) { {color: :yellow} }
|
278
253
|
|
279
|
-
it "
|
280
|
-
expect($stdout).to
|
281
|
-
expect($stdout).to
|
282
|
-
expect($stdout).to
|
283
|
-
|
284
|
-
"\e[22;39m" "[the prefix] " "\e[33m" "data\r"\
|
285
|
-
"\e[22;39m" "[the prefix] " "\e[33m" "with\r"\
|
286
|
-
"\e[22;39m" "[the prefix] " "\e[33m" "CRs"
|
287
|
-
).ordered
|
288
|
-
expect($stdout).to receive(:write).with("\e[22;39m").ordered
|
254
|
+
it "does not colorize the prefix" do
|
255
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
256
|
+
expect($stdout).to(receive(:write).with("\e[33m").ordered)
|
257
|
+
expect($stdout).to(receive(:write).with("test data").ordered)
|
258
|
+
expect($stdout).to(receive(:write).with("\e[22;39m").ordered)
|
289
259
|
tell
|
290
260
|
end
|
291
261
|
end
|
292
|
-
end
|
293
262
|
|
294
|
-
|
295
|
-
|
263
|
+
context "when stream contains carriage return" do
|
264
|
+
let(:data) { "some\rdata\rwith\rCRs" }
|
296
265
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
266
|
+
it "writes the prefix right after the CR" do
|
267
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
268
|
+
expect($stdout).to(receive(:write)
|
269
|
+
.with("some\r[the prefix] data\r[the prefix] with\r[the prefix] CRs").ordered)
|
270
|
+
tell
|
271
|
+
end
|
303
272
|
|
304
|
-
|
305
|
-
|
273
|
+
context "with color" do
|
274
|
+
let(:color_options) { {color: :yellow} }
|
306
275
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
276
|
+
it "uncolorizes the prefix" do
|
277
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
278
|
+
expect($stdout).to(receive(:write).with("\e[33m").ordered)
|
279
|
+
expect($stdout).to(receive(:write).with(
|
280
|
+
"some\r" \
|
281
|
+
"\e[22;39m[the prefix] \e[33mdata\r" \
|
282
|
+
"\e[22;39m[the prefix] \e[33mwith\r" \
|
283
|
+
"\e[22;39m[the prefix] \e[33mCRs",
|
284
|
+
).ordered)
|
285
|
+
expect($stdout).to(receive(:write).with("\e[22;39m").ordered)
|
286
|
+
tell
|
287
|
+
end
|
318
288
|
end
|
319
289
|
end
|
320
290
|
|
321
|
-
context "when stream
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
expect($stdout).to
|
327
|
-
|
328
|
-
expect($stdout).to receive(:write).with("\n" "[the prefix] ").ordered
|
329
|
-
expect($stdout).to receive(:write).with("data").ordered
|
330
|
-
expect($stdout).to receive(:write).with("\n" "[the prefix] ").ordered
|
331
|
-
expect($stdout).to receive(:write).with("with").ordered
|
332
|
-
expect($stdout).to receive(:write).with("\n" "[the prefix] ").ordered
|
333
|
-
expect($stdout).to receive(:write).with("NLs").ordered
|
334
|
-
expect($stdout).to receive(:write).with("\n").ordered
|
291
|
+
context "when stream contains newline" do
|
292
|
+
let(:data) { "some\ndata\nwith\nNLs" }
|
293
|
+
|
294
|
+
it "writes the prefix right after the NL" do
|
295
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
296
|
+
expect($stdout).to(receive(:write)
|
297
|
+
.with("some\n[the prefix] data\n[the prefix] with\n[the prefix] NLs"))
|
335
298
|
tell
|
336
299
|
end
|
337
300
|
|
@@ -339,92 +302,121 @@ RSpec.describe UserIO do
|
|
339
302
|
let(:color_options) { {color: :yellow} }
|
340
303
|
|
341
304
|
it "uncolorizes the prefix" do
|
342
|
-
expect($stdout).to
|
343
|
-
expect($stdout).to
|
344
|
-
expect($stdout).to
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
expect($stdout).to
|
351
|
-
expect($stdout).to receive(:write).
|
352
|
-
with("\n" "\e[22;39m" "[the prefix] " "\e[33m").ordered
|
353
|
-
expect($stdout).to receive(:write).with("NLs").ordered
|
354
|
-
expect($stdout).to receive(:write).with("\n").ordered
|
355
|
-
expect($stdout).to receive(:write).with("\e[22;39m").ordered
|
305
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
306
|
+
expect($stdout).to(receive(:write).with("\e[33m").ordered)
|
307
|
+
expect($stdout).to(receive(:write).with(
|
308
|
+
"some\n" \
|
309
|
+
"\e[22;39m[the prefix] \e[33mdata\n" \
|
310
|
+
"\e[22;39m[the prefix] \e[33mwith\n" \
|
311
|
+
"\e[22;39m[the prefix] \e[33mNLs",
|
312
|
+
).ordered)
|
313
|
+
expect($stdout).to(receive(:write).with("\e[22;39m").ordered)
|
356
314
|
tell
|
357
315
|
end
|
358
316
|
end
|
359
|
-
end
|
360
|
-
end
|
361
317
|
|
362
|
-
|
363
|
-
|
318
|
+
context "when stream ends with newline" do
|
319
|
+
# includes an empty chunk to verify, that they don't consume the pending NL
|
320
|
+
let(:data) { ["some\n", "data\n", "with\n", "", "NLs\n", ""] }
|
321
|
+
|
322
|
+
it "does not write prefix after the last newline" do
|
323
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
324
|
+
expect($stdout).to(receive(:write).with("some").ordered)
|
325
|
+
expect($stdout).to(receive(:write).with("\n[the prefix] ").ordered)
|
326
|
+
expect($stdout).to(receive(:write).with("data").ordered)
|
327
|
+
expect($stdout).to(receive(:write).with("\n[the prefix] ").ordered)
|
328
|
+
expect($stdout).to(receive(:write).with("with").ordered)
|
329
|
+
expect($stdout).to(receive(:write).with("\n[the prefix] ").ordered)
|
330
|
+
expect($stdout).to(receive(:write).with("NLs").ordered)
|
331
|
+
expect($stdout).to(receive(:write).with("\n").ordered)
|
332
|
+
tell
|
333
|
+
end
|
364
334
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
335
|
+
context "with color" do
|
336
|
+
let(:color_options) { {color: :yellow} }
|
337
|
+
|
338
|
+
it "uncolorizes the prefix" do
|
339
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
340
|
+
expect($stdout).to(receive(:write).with("\e[33m").ordered)
|
341
|
+
expect($stdout).to(receive(:write).with("some").ordered)
|
342
|
+
expect($stdout).to(receive(:write).with("\n\e[22;39m[the prefix] \e[33m").ordered)
|
343
|
+
expect($stdout).to(receive(:write).with("data").ordered)
|
344
|
+
expect($stdout).to(receive(:write).with("\n\e[22;39m[the prefix] \e[33m").ordered)
|
345
|
+
expect($stdout).to(receive(:write).with("with").ordered)
|
346
|
+
expect($stdout).to(receive(:write).with("\n\e[22;39m[the prefix] \e[33m").ordered)
|
347
|
+
expect($stdout).to(receive(:write).with("NLs").ordered)
|
348
|
+
expect($stdout).to(receive(:write).with("\n").ordered)
|
349
|
+
expect($stdout).to(receive(:write).with("\e[22;39m").ordered)
|
350
|
+
tell
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
371
354
|
end
|
372
|
-
end
|
373
355
|
|
374
|
-
|
375
|
-
|
376
|
-
expect($stdout).to receive(:write).with("[the prefix] no newline").ordered
|
377
|
-
user_io.tell("no newline", newline: false)
|
378
|
-
end
|
356
|
+
context "when data does not end with newline" do
|
357
|
+
let(:data) { "foo" }
|
379
358
|
|
380
|
-
|
381
|
-
|
382
|
-
|
359
|
+
it "writes prefix on next output nevertheless" do
|
360
|
+
expect($stdout).to(receive(:write).with("[the prefix] ").ordered)
|
361
|
+
expect($stdout).to(receive(:write).with("foo").ordered)
|
362
|
+
tell
|
363
|
+
expect($stdout).to(receive(:write).with("[the prefix] next\n"))
|
364
|
+
user_io.tell("next")
|
365
|
+
end
|
383
366
|
end
|
384
367
|
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
368
|
+
context "when no newline was printed before" do
|
369
|
+
before do
|
370
|
+
expect($stdout).to(receive(:write).with("[the prefix] no newline").ordered)
|
371
|
+
user_io.tell("no newline", newline: false)
|
372
|
+
end
|
373
|
+
|
374
|
+
it "does not prepend prefix" do
|
375
|
+
expect($stdout).to(receive(:write).with("test data").ordered)
|
376
|
+
tell
|
377
|
+
end
|
378
|
+
|
379
|
+
it "prints prefix on following output" do
|
380
|
+
expect($stdout).to(receive(:write).with("test data").ordered)
|
381
|
+
tell
|
382
|
+
expect($stdout).to(receive(:write).with("[the prefix] next\n"))
|
383
|
+
user_io.tell("next")
|
384
|
+
end
|
390
385
|
end
|
391
386
|
end
|
392
|
-
end
|
393
387
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
388
|
+
context "when in background" do
|
389
|
+
let(:color_options) { {color: :yellow} }
|
390
|
+
let(:options) { {output_prefix: "foo"} }
|
391
|
+
let(:data) { ["data\n", "in\nchunks", "", "yo\n", ""] }
|
392
|
+
|
393
|
+
let!(:foreground_thread) do
|
394
|
+
@finished = false
|
395
|
+
Thread.new do
|
396
|
+
user_io.background_other_threads
|
397
|
+
sleep(0.1) until @finished
|
398
|
+
user_io.foreground
|
399
|
+
end
|
405
400
|
end
|
406
|
-
end
|
407
401
|
|
408
|
-
|
402
|
+
after { foreground_thread.kill.join }
|
409
403
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
404
|
+
it "holds back the output until coming back to foreground" do
|
405
|
+
expect($stdout).to_not(receive(:write))
|
406
|
+
tell
|
407
|
+
RSpec::Mocks.space.proxy_for($stdout).reset
|
408
|
+
expect($stdout).to(receive(:write).with("[foo] ").ordered)
|
409
|
+
expect($stdout).to(receive(:write).with("\e[33m").ordered)
|
410
|
+
expect($stdout).to(receive(:write).with("data").ordered)
|
411
|
+
expect($stdout).to(receive(:write).with("\n\e[22;39m[foo] \e[33m").ordered)
|
412
|
+
expect($stdout).to(receive(:write).with("in\n\e[22;39m[foo] \e[33mchunks").ordered)
|
413
|
+
expect($stdout).to(receive(:write).with("yo").ordered)
|
414
|
+
expect($stdout).to(receive(:write).with("\n").ordered)
|
415
|
+
expect($stdout).to(receive(:write).with("\e[22;39m").ordered)
|
416
|
+
@finished = true
|
417
|
+
foreground_thread.join
|
418
|
+
end
|
425
419
|
end
|
426
420
|
end
|
427
421
|
end
|
428
422
|
end
|
429
|
-
|
430
|
-
end
|