tty-prompt 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +174 -63
  4. data/Rakefile +2 -2
  5. data/examples/ask_blank.rb +9 -0
  6. data/examples/enum_select_disabled.rb +1 -1
  7. data/examples/enum_select_paged.rb +1 -1
  8. data/examples/expand_auto.rb +29 -0
  9. data/examples/mask.rb +1 -1
  10. data/examples/multi_select.rb +1 -1
  11. data/examples/multi_select_disabled_paged.rb +22 -0
  12. data/examples/multi_select_paged.rb +1 -1
  13. data/examples/select_disabled_paged.rb +22 -0
  14. data/examples/select_paginated.rb +1 -1
  15. data/lib/tty/prompt.rb +46 -10
  16. data/lib/tty/prompt/{enum_paginator.rb → block_paginator.rb} +19 -18
  17. data/lib/tty/prompt/choice.rb +1 -3
  18. data/lib/tty/prompt/enum_list.rb +31 -9
  19. data/lib/tty/prompt/expander.rb +19 -1
  20. data/lib/tty/prompt/keypress.rb +30 -35
  21. data/lib/tty/prompt/list.rb +112 -40
  22. data/lib/tty/prompt/mask_question.rb +2 -3
  23. data/lib/tty/prompt/multi_list.rb +36 -12
  24. data/lib/tty/prompt/paginator.rb +37 -25
  25. data/lib/tty/prompt/question.rb +29 -5
  26. data/lib/tty/prompt/slider.rb +16 -8
  27. data/lib/tty/prompt/symbols.rb +30 -6
  28. data/lib/tty/prompt/timer.rb +75 -0
  29. data/lib/tty/prompt/version.rb +1 -1
  30. data/spec/spec_helper.rb +18 -2
  31. data/spec/unit/ask_spec.rb +45 -4
  32. data/spec/unit/{enum_paginator_spec.rb → block_paginator_spec.rb} +14 -5
  33. data/spec/unit/choice/from_spec.rb +16 -0
  34. data/spec/unit/enum_select_spec.rb +104 -32
  35. data/spec/unit/expand_spec.rb +104 -12
  36. data/spec/unit/keypress_spec.rb +2 -8
  37. data/spec/unit/mask_spec.rb +9 -1
  38. data/spec/unit/multi_select_spec.rb +348 -118
  39. data/spec/unit/paginator_spec.rb +29 -10
  40. data/spec/unit/select_spec.rb +390 -108
  41. data/spec/unit/slider_spec.rb +48 -6
  42. data/spec/unit/timer_spec.rb +29 -0
  43. data/tty-prompt.gemspec +4 -6
  44. metadata +17 -46
  45. data/lib/tty/prompt/timeout.rb +0 -78
@@ -2,6 +2,6 @@
2
2
 
3
3
  module TTY
4
4
  class Prompt
5
- VERSION = '0.18.1'
5
+ VERSION = '0.19.0'
6
6
  end # Prompt
7
7
  end # TTY
@@ -4,10 +4,10 @@ if ENV['COVERAGE'] || ENV['TRAVIS']
4
4
  require 'simplecov'
5
5
  require 'coveralls'
6
6
 
7
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
8
8
  SimpleCov::Formatter::HTMLFormatter,
9
9
  Coveralls::SimpleCov::Formatter
10
- ]
10
+ ])
11
11
 
12
12
  SimpleCov.start do
13
13
  command_name 'spec'
@@ -17,7 +17,23 @@ end
17
17
 
18
18
  require 'tty-prompt'
19
19
 
20
+ class StringIO
21
+ def wait_readable(*)
22
+ true
23
+ end
24
+ end
25
+
26
+ module Helpers
27
+ def diff_output(actual_output, expected_output)
28
+ puts "ACTUAL: #{actual_output.inspect}"
29
+ puts "--------------------------------\n"
30
+ puts "EXPECT: #{expected_output.inspect}"
31
+ end
32
+ end
33
+
20
34
  RSpec.configure do |config|
35
+ config.include(Helpers)
36
+
21
37
  config.expect_with :rspec do |expectations|
22
38
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
23
39
  end
@@ -14,16 +14,57 @@ RSpec.describe TTY::Prompt, '#ask' do
14
14
  end
15
15
 
16
16
  it 'asks an empty question ' do
17
- prompt.ask('')
18
- expect(prompt.output.string).to eql('')
17
+ prompt = TTY::TestPrompt.new
18
+ prompt.input << "\r"
19
+ prompt.input.rewind
20
+
21
+ answer = prompt.ask
22
+ expect(answer).to eq(nil)
23
+
24
+ expect(prompt.output.string).to eql("\e[2K\e[1G\n\e[1A\e[2K\e[1G\n")
19
25
  end
20
26
 
21
- it 'asks an empty question and returns nil if EOF is sent to stdin' do
27
+ it "asks an empty question and returns nil if EOF is sent to stdin" do
28
+ prompt = TTY::TestPrompt.new
22
29
  prompt.input << nil
23
30
  prompt.input.rewind
31
+
24
32
  answer = prompt.ask('')
33
+
25
34
  expect(answer).to eql(nil)
26
- expect(prompt.output.string).to eq('')
35
+ expect(prompt.output.string).to eq("\e[1A\e[2K\e[1G\n")
36
+ end
37
+
38
+ it "asks an empty question with prepopulated value" do
39
+ prompt = TTY::TestPrompt.new
40
+ prompt.input << "\n"
41
+ prompt.input.rewind
42
+
43
+ answer = prompt.ask value: "yes"
44
+
45
+ expect(answer).to eq("yes")
46
+ expect(prompt.output.string).to eq([
47
+ "yes\e[2K\e[1G",
48
+ "yes\n\e[1A\e[2K\e[1G",
49
+ "\e[32myes\e[0m\n"
50
+ ].join)
51
+ end
52
+
53
+ it "asks question with prepopulated value" do
54
+ prompt = TTY::TestPrompt.new prefix: "> "
55
+ prompt.input << "\n"
56
+ prompt.input.rewind
57
+
58
+ answer = prompt.ask("Say?") do |q|
59
+ q.value "yes"
60
+ end
61
+
62
+ expect(answer).to eq("yes")
63
+ expect(prompt.output.string).to eq([
64
+ "> Say? yes\e[2K\e[1G",
65
+ "> Say? yes\n\e[1A\e[2K\e[1G",
66
+ "> Say? \e[32myes\e[0m\n"
67
+ ].join)
27
68
  end
28
69
 
29
70
  it "asks a question with a prefix [?]" do
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe TTY::Prompt::EnumPaginator, '#paginate' do
3
+ RSpec.describe TTY::Prompt::BlockPaginator, '#paginate' do
4
4
  it "ignores per_page when equal items " do
5
5
  list = %w(a b c d)
6
6
  paginator = described_class.new({per_page: 4})
@@ -44,16 +44,25 @@ RSpec.describe TTY::Prompt::EnumPaginator, '#paginate' do
44
44
  expect(paginator.paginate(list, 8).to_a).to eq([['g',6]])
45
45
  end
46
46
 
47
- it "finds maximum index for current selection" do
47
+ it "finds both start and end index for current selection" do
48
48
  list = %w(a b c d e f g)
49
49
  paginator = described_class.new({per_page: 3, default: 0})
50
50
 
51
+ paginator.paginate(list, 3)
52
+ expect(paginator.start_index).to eq(0)
53
+ expect(paginator.end_index).to eq(2)
54
+
51
55
  paginator.paginate(list, 4)
52
- expect(paginator.max_index).to eq(5)
56
+ expect(paginator.start_index).to eq(3)
57
+ expect(paginator.end_index).to eq(5)
58
+
53
59
  paginator.paginate(list, 5)
54
- expect(paginator.max_index).to eq(5)
60
+ expect(paginator.start_index).to eq(3)
61
+ expect(paginator.end_index).to eq(5)
62
+
55
63
  paginator.paginate(list, 7)
56
- expect(paginator.max_index).to eq(8)
64
+ expect(paginator.start_index).to eq(6)
65
+ expect(paginator.end_index).to eq(6)
57
66
  end
58
67
 
59
68
  it "starts with default selection" do
@@ -93,4 +93,20 @@ RSpec.describe TTY::Prompt::Choice, '#from' do
93
93
  expect(choice.value).to eq(:none)
94
94
  expect(choice.disabled?).to eq(true)
95
95
  end
96
+
97
+ it "creates choice from an arbitrary object that responds to to_s call" do
98
+ stub_const("Size", Class.new do
99
+ def to_s
100
+ 'large'
101
+ end
102
+ end)
103
+ size = Size.new
104
+ expected_choice = described_class.new(size, size)
105
+ choice = described_class.from(size)
106
+
107
+ expect(choice).to eq(expected_choice)
108
+ expect(choice.name).to eq(size)
109
+ expect(choice.value).to eq(size)
110
+ expect(choice.disabled?).to eq(false)
111
+ end
96
112
  end
@@ -60,9 +60,10 @@ RSpec.describe TTY::Prompt do
60
60
  answer = prompt.enum_select("Select an editor?", choices)
61
61
  expect(answer).to eq('/bin/nano')
62
62
 
63
- expected_output =
64
- output_helper("Select an editor?", choices, "/bin/nano") +
63
+ expected_output = [
64
+ output_helper("Select an editor?", choices, "/bin/nano"),
65
65
  exit_message("Select an editor?", "/bin/nano")
66
+ ].join
66
67
 
67
68
  expect(prompt.output.string).to eq(expected_output)
68
69
  end
@@ -76,10 +77,11 @@ RSpec.describe TTY::Prompt do
76
77
  answer = prompt.enum_select("Select an editor?", choices, default: 2)
77
78
  expect(answer).to eq('/usr/bin/vim.tiny')
78
79
 
79
- expected_output =
80
- output_helper("Select an editor?", choices, "/usr/bin/vim.basic", default: 2) +
81
- output_helper("Select an editor?", choices, "/usr/bin/vim.tiny", default: 2, input: '3') +
80
+ expected_output = [
81
+ output_helper("Select an editor?", choices, "/usr/bin/vim.basic", default: 2),
82
+ output_helper("Select an editor?", choices, "/usr/bin/vim.tiny", default: 2, input: '3'),
82
83
  exit_message("Select an editor?", "/usr/bin/vim.tiny")
84
+ ].join
83
85
 
84
86
  expect(prompt.output.string).to eq(expected_output)
85
87
  end
@@ -99,10 +101,11 @@ RSpec.describe TTY::Prompt do
99
101
  end
100
102
  expect(answer).to eq('/bin/nano')
101
103
 
102
- expected_output =
103
- output_helper("Select an editor?", choices, "/usr/bin/vim.basic", default: 2, enum: '.') +
104
- output_helper("Select an editor?", choices, "/bin/nano", default: 2, enum: '.', input: 1) +
104
+ expected_output = [
105
+ output_helper("Select an editor?", choices, "/usr/bin/vim.basic", default: 2, enum: '.'),
106
+ output_helper("Select an editor?", choices, "/bin/nano", default: 2, enum: '.', input: 1),
105
107
  exit_message("Select an editor?", "/bin/nano")
108
+ ].join
106
109
 
107
110
  expect(prompt.output.string).to eq(expected_output)
108
111
  end
@@ -123,9 +126,10 @@ RSpec.describe TTY::Prompt do
123
126
 
124
127
  expect(answer).to eq('/usr/bin/vim')
125
128
 
126
- expected_output =
127
- output_helper("Select an editor?", choices, "vim", default: 2) +
129
+ expected_output = [
130
+ output_helper("Select an editor?", choices, "vim", default: 2),
128
131
  exit_message("Select an editor?", "vim")
132
+ ].join
129
133
 
130
134
  expect(prompt.output.string).to eq(expected_output)
131
135
  end
@@ -136,8 +140,12 @@ RSpec.describe TTY::Prompt do
136
140
  prompt.input << "\n"
137
141
  prompt.input.rewind
138
142
  options = {active_color: :red, help_color: :blue, error_color: :green}
139
- expect(prompt.enum_select("Select an editor?", choices, options)).to eq('/bin/nano')
140
- expect(prompt.output.string).to eq([
143
+
144
+ answer = prompt.enum_select("Select an editor?", choices, options)
145
+
146
+ expect(answer).to eq('/bin/nano')
147
+
148
+ expected_output = [
141
149
  "Select an editor? \n",
142
150
  " \e[31m1) /bin/nano\e[0m\n",
143
151
  " 2) /usr/bin/vim.basic\n",
@@ -146,7 +154,56 @@ RSpec.describe TTY::Prompt do
146
154
  "\e[2K\e[1G\e[1A" * 4,
147
155
  "\e[2K\e[1G\e[J",
148
156
  "Select an editor? \e[31m/bin/nano\e[0m\n"
149
- ].join)
157
+ ].join
158
+
159
+ expect(prompt.output.string).to eq(expected_output)
160
+ end
161
+
162
+ it "changes global symbols" do
163
+ prompt = TTY::TestPrompt.new(symbols: {cross: 'x'})
164
+ choices = ['A', {name: 'B', disabled: '(out)'}, 'C']
165
+ prompt.input << "\n"
166
+ prompt.input.rewind
167
+ answer = prompt.enum_select("What letter?", choices)
168
+ expect(answer).to eq("A")
169
+
170
+ expected_output = [
171
+ "What letter? \n",
172
+ " \e[32m1) A\e[0m\n",
173
+ "\e[31mx\e[0m 2) B (out)\n",
174
+ " 3) C\n",
175
+ " Choose 1-3 [1]: ",
176
+ "\e[2K\e[1G\e[1A" * 4,
177
+ "\e[2K\e[1G\e[J",
178
+ "What letter? \e[32mA\e[0m\n",
179
+ ].join
180
+
181
+ expect(prompt.output.string).to eq(expected_output)
182
+ end
183
+
184
+ it "changes global symbols through DSL" do
185
+ prompt = TTY::TestPrompt.new
186
+ choices = ['A', {name: 'B', disabled: '(out)'}, 'C']
187
+ prompt.input << "\n"
188
+ prompt.input.rewind
189
+ answer = prompt.enum_select("What letter?", choices) do |menu|
190
+ menu.symbols cross: 'x'
191
+ menu.choices choices
192
+ end
193
+ expect(answer).to eq("A")
194
+
195
+ expected_output = [
196
+ "What letter? \n",
197
+ " \e[32m1) A\e[0m\n",
198
+ "\e[31mx\e[0m 2) B (out)\n",
199
+ " 3) C\n",
200
+ " Choose 1-3 [1]: ",
201
+ "\e[2K\e[1G\e[1A" * 4,
202
+ "\e[2K\e[1G\e[J",
203
+ "What letter? \e[32mA\e[0m\n",
204
+ ].join
205
+
206
+ expect(prompt.output.string).to eq(expected_output)
150
207
  end
151
208
 
152
209
  it "displays error with unrecognized input" do
@@ -158,13 +215,14 @@ RSpec.describe TTY::Prompt do
158
215
  answer = prompt.enum_select("Select an editor?", choices)
159
216
  expect(answer).to eq('/usr/bin/vim.basic')
160
217
 
161
- expected_output =
162
- output_helper("Select an editor?", choices, "/bin/nano") +
163
- output_helper("Select an editor?", choices, "/bin/nano", input: '1') +
164
- output_helper("Select an editor?", choices, "/bin/nano", input: '11') +
165
- output_helper("Select an editor?", choices, "/bin/nano", error: 'Please enter a valid number', input: '') +
166
- output_helper("Select an editor?", choices, "/usr/bin/vim.basic", error: 'Please enter a valid number', input: '2') +
218
+ expected_output = [
219
+ output_helper("Select an editor?", choices, "/bin/nano"),
220
+ output_helper("Select an editor?", choices, "/bin/nano", input: '1'),
221
+ output_helper("Select an editor?", choices, "/bin/nano", input: '11'),
222
+ output_helper("Select an editor?", choices, "/bin/nano", error: 'Please enter a valid number', input: ''),
223
+ output_helper("Select an editor?", choices, "/usr/bin/vim.basic", error: 'Please enter a valid number', input: '2'),
167
224
  exit_message("Select an editor?", "/usr/bin/vim.basic")
225
+ ].join
168
226
 
169
227
  expect(prompt.output.string).to eq(expected_output)
170
228
  end
@@ -354,6 +412,7 @@ RSpec.describe TTY::Prompt do
354
412
  menu.choices choices
355
413
  end
356
414
  expect(value).to eq("A")
415
+
357
416
  expect(prompt.output.string).to eq([
358
417
  "What letter? \n",
359
418
  " \e[32m1) A\e[0m\n",
@@ -391,11 +450,22 @@ RSpec.describe TTY::Prompt do
391
450
  prompt = TTY::TestPrompt.new
392
451
  choices = [{name: 'A', disabled: true}, 'B', 'C', 'D', 'E']
393
452
  expect {
394
- prompt.enum_select("What letter?", choices)
453
+ prompt.enum_select("What letter?", choices, default: 1)
395
454
  }.to raise_error(TTY::Prompt::ConfigurationError,
396
455
  /default index 1 matches disabled choice item/)
397
456
  end
398
457
 
458
+ it "finds first non-disabled index" do
459
+ prompt = TTY::TestPrompt.new
460
+ choices = [{name: 'A', disabled: true}, {name:'B', disabled: true}, 'C', 'D']
461
+ prompt = TTY::TestPrompt.new
462
+ prompt.input << "\n"
463
+ prompt.input.rewind
464
+
465
+ answer = prompt.enum_select("What letter?", choices)
466
+ expect(answer).to eq('C')
467
+ end
468
+
399
469
  it "doesn't allow to choose disabled choice and defaults" do
400
470
  choices = ['A', {name: 'B', disabled: '(out)'}, 'C', 'D', 'E', 'F']
401
471
  prompt = TTY::TestPrompt.new
@@ -405,12 +475,13 @@ RSpec.describe TTY::Prompt do
405
475
  answer = prompt.enum_select("What letter?", choices)
406
476
  expect(answer).to eq("C")
407
477
 
408
- expected_output =
409
- output_helper("What letter?", choices, 'A') +
410
- output_helper("What letter?", choices, 'A', input: '2') +
411
- output_helper("What letter?", choices, 'A', input: '', error: 'Please enter a valid number') +
412
- output_helper("What letter?", choices, 'C', input: '3', error: 'Please enter a valid number') +
478
+ expected_output = [
479
+ output_helper("What letter?", choices, 'A'),
480
+ output_helper("What letter?", choices, 'A', input: '2'),
481
+ output_helper("What letter?", choices, 'A', input: '', error: 'Please enter a valid number'),
482
+ output_helper("What letter?", choices, 'C', input: '3', error: 'Please enter a valid number'),
413
483
  exit_message("What letter?", "C")
484
+ ].join
414
485
 
415
486
  expect(prompt.output.string).to eq(expected_output)
416
487
  end
@@ -431,14 +502,15 @@ RSpec.describe TTY::Prompt do
431
502
  answer = prompt.enum_select("What letter?", choices)
432
503
  expect(answer).to eq("D")
433
504
 
434
- expected_output =
435
- output_helper("What letter?", choices, 'A') +
436
- output_helper("What letter?", choices, 'A', input: '2') +
437
- output_helper("What letter?", choices, 'A', input: '') +
438
- output_helper("What letter?", choices, 'A', input: '3') +
439
- output_helper("What letter?", choices, 'A', input: '') +
440
- output_helper("What letter?", choices, 'D', input: '4') +
505
+ expected_output = [
506
+ output_helper("What letter?", choices, 'A'),
507
+ output_helper("What letter?", choices, 'A', input: '2'),
508
+ output_helper("What letter?", choices, 'A', input: ''),
509
+ output_helper("What letter?", choices, 'A', input: '3'),
510
+ output_helper("What letter?", choices, 'A', input: ''),
511
+ output_helper("What letter?", choices, 'D', input: '4'),
441
512
  exit_message("What letter?", "D")
513
+ ].join
442
514
 
443
515
  expect(prompt.output.string).to eq(expected_output)
444
516
  end
@@ -35,11 +35,13 @@ RSpec.describe TTY::Prompt, '#expand' do
35
35
  result = prompt.expand('Overwrite Gemfile?', choices)
36
36
  expect(result).to eq(:yes)
37
37
 
38
- expect(prompt.output.string).to eq([
38
+ expected_output = [
39
39
  "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
40
40
  "\e[2K\e[1G",
41
41
  "Overwrite Gemfile? \e[32mOverwrite\e[0m\n"
42
- ].join)
42
+ ].join
43
+
44
+ expect(prompt.output.string).to eq(expected_output)
43
45
  end
44
46
 
45
47
  it "changes default option" do
@@ -49,11 +51,13 @@ RSpec.describe TTY::Prompt, '#expand' do
49
51
  result = prompt.expand('Overwrite Gemfile?', choices, default: 3)
50
52
  expect(result).to eq(:all)
51
53
 
52
- expect(prompt.output.string).to eq([
54
+ expected_output = [
53
55
  "Overwrite Gemfile? (enter \"h\" for help) [y,n,\e[32ma\e[0m,d,q,h] ",
54
56
  "\e[2K\e[1G",
55
57
  "Overwrite Gemfile? \e[32mOverwrite all\e[0m\n"
56
- ].join)
58
+ ].join
59
+
60
+ expect(prompt.output.string).to eq(expected_output)
57
61
  end
58
62
 
59
63
  it "expands chosen option with extra information" do
@@ -63,7 +67,7 @@ RSpec.describe TTY::Prompt, '#expand' do
63
67
  result = prompt.expand('Overwrite Gemfile?', choices)
64
68
  expect(result).to eq(:all)
65
69
 
66
- expect(prompt.output.string).to eq([
70
+ expected_output = [
67
71
  "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
68
72
  "\e[2K\e[1G",
69
73
  "Overwrite Gemfile? (enter \"h\" for help) [y,n,\e[32ma\e[0m,d,q,h] ",
@@ -75,7 +79,9 @@ RSpec.describe TTY::Prompt, '#expand' do
75
79
  "\e[2K\e[1G",
76
80
  "\e[A\e[1G",
77
81
  "Overwrite Gemfile? \e[32mOverwrite all\e[0m\n"
78
- ].join)
82
+ ].join
83
+
84
+ expect(prompt.output.string).to eq(expected_output)
79
85
  end
80
86
 
81
87
  it "expands help option and then defaults" do
@@ -85,7 +91,7 @@ RSpec.describe TTY::Prompt, '#expand' do
85
91
  result = prompt.expand('Overwrite Gemfile?', choices)
86
92
  expect(result).to eq(:diff)
87
93
 
88
- expect(prompt.output.string).to eq([
94
+ expected_output = [
89
95
  "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
90
96
  "\e[2K\e[1G",
91
97
  "Overwrite Gemfile? (enter \"h\" for help) [y,n,a,d,q,\e[32mh\e[0m] h\n",
@@ -116,7 +122,89 @@ RSpec.describe TTY::Prompt, '#expand' do
116
122
  "\e[2K\e[1G\e[1A" * 7,
117
123
  "\e[2K\e[1G",
118
124
  "Overwrite Gemfile? \e[32mShow diff\e[0m\n",
119
- ].join)
125
+ ].join
126
+
127
+ expect(prompt.output.string).to eq(expected_output)
128
+ end
129
+
130
+ it "automatically expands hint" do
131
+ prompt.input << "d\n"
132
+ prompt.input.rewind
133
+
134
+ result = prompt.expand('Overwrite Gemfile?', choices, auto_hint: true)
135
+ expect(result).to eq(:diff)
136
+
137
+ expected_output = [
138
+ "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
139
+ "\n\e[32m>> \e[0mOverwrite",
140
+ "\e[A\e[1G\e[54C",
141
+ "\e[2K\e[1G",
142
+ "\e[1B",
143
+ "\e[2K\e[1G",
144
+ "\e[A\e[1G",
145
+ "Overwrite Gemfile? (enter \"h\" for help) [y,n,a,\e[32md\e[0m,q,h] ",
146
+ "d\n",
147
+ "\e[32m>> \e[0mShow diff",
148
+ "\e[A\e[1G\e[55C",
149
+ "\e[2K\e[1G",
150
+ "\e[1B",
151
+ "\e[2K\e[1G",
152
+ "\e[A\e[1G",
153
+ "Overwrite Gemfile? \e[32mShow diff\e[0m\n",
154
+ "\e[32m>> \e[0mShow diff",
155
+ "\e[A\e[1G\e[28C\n"
156
+ ].join
157
+
158
+ expect(prompt.output.string).to eq(expected_output)
159
+ end
160
+
161
+ it "informs about invalid input when automatically expanding hint" do
162
+ prompt = TTY::TestPrompt.new
163
+ prompt.on(:keypress) { |e| prompt.trigger(:keybackspace) if e.value == "w" }
164
+ prompt.input << "y" << "y" << "\u007F" << "\r"
165
+ prompt.input.rewind
166
+
167
+ result = prompt.expand('Overwrite Gemfile?', choices, defualt: 1, auto_hint: true)
168
+ expect(result).to eq(:yes)
169
+
170
+ expected_output = [
171
+ "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
172
+ "\n\e[32m>> \e[0mOverwrite",
173
+ "\e[A\e[1G\e[54C",
174
+ "\e[2K\e[1G",
175
+ "\e[1B",
176
+ "\e[2K\e[1G",
177
+ "\e[A\e[1G",
178
+ "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
179
+ "y\n",
180
+ "\e[32m>> \e[0mOverwrite",
181
+ "\e[A\e[1G\e[55C",
182
+ "\e[2K\e[1G",
183
+ "\e[1B",
184
+ "\e[2K\e[1G",
185
+ "\e[A\e[1G",
186
+ "Overwrite Gemfile? (enter \"h\" for help) [y,n,a,d,q,h] ",
187
+ "yy\n",
188
+ "\e[32m>> \e[0minvalid option",
189
+ "\e[A\e[1G\e[56C",
190
+ "\e[2K\e[1G",
191
+ "\e[1B",
192
+ "\e[2K\e[1G",
193
+ "\e[A\e[1G",
194
+ "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
195
+ "y\n",
196
+ "\e[32m>> \e[0mOverwrite",
197
+ "\e[A\e[1G\e[55C",
198
+ "\e[2K\e[1G",
199
+ "\e[1B",
200
+ "\e[2K\e[1G",
201
+ "\e[A\e[1G",
202
+ "Overwrite Gemfile? \e[32mOverwrite\e[0m\n",
203
+ "\e[32m>> \e[0mOverwrite",
204
+ "\e[A\e[1G\e[28C\n"
205
+ ].join
206
+
207
+ expect(prompt.output.string).to eq(expected_output)
120
208
  end
121
209
 
122
210
  it "specifies options through DSL" do
@@ -135,11 +223,13 @@ RSpec.describe TTY::Prompt, '#expand' do
135
223
 
136
224
  expect(result).to eq(:diff)
137
225
 
138
- expect(prompt.output.string).to eq([
226
+ expected_output = [
139
227
  "Overwrite Gemfile? (enter \"h\" for help) [y,n,a,\e[32md\e[0m,q,h] ",
140
228
  "\e[2K\e[1G",
141
229
  "Overwrite Gemfile? \e[32mShow diff\e[0m\n"
142
- ].join)
230
+ ].join
231
+
232
+ expect(prompt.output.string).to eq(expected_output)
143
233
  end
144
234
 
145
235
  it "specifies options through DSL and executes value" do
@@ -156,11 +246,13 @@ RSpec.describe TTY::Prompt, '#expand' do
156
246
 
157
247
  expect(result).to eq(:ok)
158
248
 
159
- expect(prompt.output.string).to eq([
249
+ expected_output = [
160
250
  "Overwrite Gemfile? (enter \"h\" for help) [\e[32my\e[0m,n,a,d,q,h] ",
161
251
  "\e[2K\e[1G",
162
252
  "Overwrite Gemfile? \e[32mOverwrite\e[0m\n"
163
- ].join)
253
+ ].join
254
+
255
+ expect(prompt.output.string).to eq(expected_output)
164
256
  end
165
257
 
166
258
  it "fails to expand due to lack of key attribute" do